From e91fa307d0f0690ff9d71e17738ddf6e37cc28d0 Mon Sep 17 00:00:00 2001 From: csolisr Date: Fri, 7 Jul 2023 17:02:44 +0200 Subject: [PATCH 001/388] fix: tweak z-index to not clash with sidebar on mobile By default, the z-index of the toggle button is above the z-index of the sidebar on mobile devices. This fix tweaks the z-index so that it remains below the sidebar while it's open. --- showmore_dyn/showmore_dyn.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/showmore_dyn/showmore_dyn.css b/showmore_dyn/showmore_dyn.css index 93cc87a53..250d95c67 100644 --- a/showmore_dyn/showmore_dyn.css +++ b/showmore_dyn/showmore_dyn.css @@ -7,7 +7,7 @@ position: absolute; top: auto; bottom: 0; - z-index: 11; + z-index: 9; left: 0; display: none; } From d80d3767628536955d59e1007ca1192102e45e49 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 8 Jul 2023 14:54:56 +0000 Subject: [PATCH 002/388] Bluesky: don't remove hashtags upon posting --- bluesky/bluesky.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index c3e621f2b..d96766d71 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -659,8 +659,8 @@ function bluesky_create_post(array $item, stdClass $root = null, stdClass $paren function bluesky_get_urls(string $body): array { - // Remove all hashtags and mentions - $body = preg_replace("/([#@!])\[url\=(.*?)\](.*?)\[\/url\]/ism", '', $body); + // Remove all hashtag and mention links + $body = preg_replace("/([#@!])\[url\=(.*?)\](.*?)\[\/url\]/ism", '$1$3', $body); $urls = []; From cf435277a78139312e557a13466c95b4d3764b10 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 9 Jul 2023 13:38:06 +0000 Subject: [PATCH 003/388] Bluesky: Fix for quoted posts with media --- bluesky/bluesky.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index d96766d71..3e3e2aaf5 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -1150,16 +1150,12 @@ function bluesky_add_media(stdClass $embed, array $item, int $fetch_uid, int $le $shared = bluesky_get_header($embed->record->record, $uri, 0, $fetch_uid); $shared = bluesky_get_content($shared, $embed->record->record->value, $uri, $item['uid'], $level); if (!empty($shared)) { - if (!empty($embed->record->embeds)) { + if (!empty($embed->record->record->embeds)) { foreach ($embed->record->record->embeds as $single) { $shared = bluesky_add_media($single, $shared, $fetch_uid, $level); } } - if (!empty($embed->media)) { - bluesky_add_media($embed->media, $item, $fetch_uid, $level); - } - $id = Item::insert($shared); $shared = Post::selectFirst(['uri-id'], ['id' => $id]); } @@ -1167,6 +1163,10 @@ function bluesky_add_media(stdClass $embed, array $item, int $fetch_uid, int $le if (!empty($shared)) { $item['quote-uri-id'] = $shared['uri-id']; } + + if (!empty($embed->media)) { + bluesky_add_media($embed->media, $item, $fetch_uid, $level); + } break; default: From f4110880a152a09c5dac5d5db2f3beb12f57e2b5 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 16 Jul 2023 10:37:33 +0000 Subject: [PATCH 004/388] Use "convertForUriId" whenever possible --- impressum/impressum.php | 8 ++++---- langfilter/langfilter.php | 2 +- mailstream/mailstream.php | 11 ++++++----- newmemberwidget/newmemberwidget.php | 3 ++- notifyall/NotifyAllEmail.php | 5 +++-- saml/saml.php | 6 ++---- tumblr/tumblr.php | 2 +- wppost/wppost.php | 3 ++- 8 files changed, 21 insertions(+), 19 deletions(-) diff --git a/impressum/impressum.php b/impressum/impressum.php index 1d572f856..754cb8286 100644 --- a/impressum/impressum.php +++ b/impressum/impressum.php @@ -14,7 +14,7 @@ use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\DI; use Friendica\Core\Config\Util\ConfigFileManager; -use Friendica\Util\Proxy as ProxyUtils; +use Friendica\Model\User; function impressum_install() { @@ -45,7 +45,7 @@ function obfuscate_email (string $s): string function impressum_footer(string &$body) { - $text = ProxyUtils::proxifyHtml(BBCode::convert(DI::config()->get('impressum', 'footer_text'))); + $text = BBCode::convertForUriId(User::getSystemUriId(), DI::config()->get('impressum', 'footer_text')); if ($text != '') { DI::page()['htmlhead'] .= ''; @@ -64,8 +64,8 @@ function impressum_show(string &$body) $body .= '

' . DI::l10n()->t('Impressum') . '

'; $owner = DI::config()->get('impressum', 'owner'); $owner_profile = DI::config()->get('impressum', 'ownerprofile'); - $postal = ProxyUtils::proxifyHtml(BBCode::convert(DI::config()->get('impressum', 'postal'))); - $notes = ProxyUtils::proxifyHtml(BBCode::convert(DI::config()->get('impressum', 'notes'))); + $postal = BBCode::convertForUriId(User::getSystemUriId(), DI::config()->get('impressum', 'postal')); + $notes = BBCode::convertForUriId(User::getSystemUriId(), DI::config()->get('impressum', 'notes')); if ($owner) { if ($owner_profile) { diff --git a/langfilter/langfilter.php b/langfilter/langfilter.php index 61b357f6c..9cb57a6ce 100644 --- a/langfilter/langfilter.php +++ b/langfilter/langfilter.php @@ -122,7 +122,7 @@ function langfilter_prepare_body_content_filter(&$hook_data) $naked_body = strip_tags( $hook_data['item']['rendered-html'] ??''?: // Equivalent of !empty() - BBCode::convert($hook_data['item']['body'], false, BBCode::ACTIVITYPUB, true) + BBCode::convertForUriId($hook_data['item']['uri-id'], $hook_data['item']['body'], BBCode::ACTIVITYPUB) ); $naked_body = preg_replace('#\s+#', ' ', trim($naked_body)); diff --git a/mailstream/mailstream.php b/mailstream/mailstream.php index 56e7fa132..d76ccf86e 100644 --- a/mailstream/mailstream.php +++ b/mailstream/mailstream.php @@ -258,12 +258,13 @@ function mailstream_sender(array $item): string * Converts a bbcode-encoded subject line into a plaintext version suitable for the subject line of an email * * @param string $subject bbcode-encoded subject line + * @param int $uri_id * * @return string plaintext subject line */ -function mailstream_decode_subject(string $subject): string +function mailstream_decode_subject(string $subject, int $uri_id): string { - $html = BBCode::convert($subject); + $html = BBCode::convertForUriId($uri_id, $subject); if (!$html) { return $subject; } @@ -298,7 +299,7 @@ function mailstream_decode_subject(string $subject): string function mailstream_subject(array $item): string { if ($item['title']) { - return mailstream_decode_subject($item['title']); + return mailstream_decode_subject($item['title'], $item['uri-id']); } $parent = $item['thr-parent']; // Don't look more than 100 levels deep for a subject, in case of loops @@ -311,7 +312,7 @@ function mailstream_subject(array $item): string break; } if ($parent_item['title']) { - return DI::l10n()->t('Re:') . ' ' . mailstream_decode_subject($parent_item['title']); + return DI::l10n()->t('Re:') . ' ' . mailstream_decode_subject($parent_item['title'], $item['uri-id']); } $parent = $parent_item['thr-parent']; } @@ -333,7 +334,7 @@ function mailstream_subject(array $item): string return DI::l10n()->t("Diaspora post"); } if ($contact['network'] === 'face') { - $text = mailstream_decode_subject($item['body']); + $text = mailstream_decode_subject($item['body'], $item['uri-id']); // For some reason these do show up in Facebook $text = preg_replace('/\xA0$/', '', $text); $subject = (strlen($text) > 150) ? (substr($text, 0, 140) . '...') : $text; diff --git a/newmemberwidget/newmemberwidget.php b/newmemberwidget/newmemberwidget.php index 6cd79c37b..01977d0c3 100644 --- a/newmemberwidget/newmemberwidget.php +++ b/newmemberwidget/newmemberwidget.php @@ -12,6 +12,7 @@ use Friendica\Core\Hook; use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\DI; +use Friendica\Model\User; function newmemberwidget_install() { @@ -39,7 +40,7 @@ function newmemberwidget_network_mod_init ($b) $ft = DI::config()->get('newmemberwidget','freetext', ''); if (!empty($ft)) { - $t .= '

'.BBCode::convert(trim($ft)).'

'; + $t .= '

'.BBCode::convertForUriId(User::getSystemUriId(), trim($ft)).'

'; } $t .= '
'; diff --git a/notifyall/NotifyAllEmail.php b/notifyall/NotifyAllEmail.php index 3bb16f274..7a00a2c97 100644 --- a/notifyall/NotifyAllEmail.php +++ b/notifyall/NotifyAllEmail.php @@ -25,6 +25,7 @@ use Friendica\App\BaseURL; use Friendica\Content\Text\BBCode; use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Core\L10n; +use Friendica\Model\User; use Friendica\Object\Email; /** @@ -50,9 +51,9 @@ class NotifyAllEmail extends Email $subject = $_REQUEST['subject']; - $textversion = strip_tags(html_entity_decode(BBCode::convert(stripslashes(str_replace(["\\r", "\\n"], ["", "\n"], $text))), ENT_QUOTES, 'UTF-8')); + $textversion = strip_tags(html_entity_decode(BBCode::convertForUriId(User::getSystemUriId(), stripslashes(str_replace(["\\r", "\\n"], ["", "\n"], $text))), ENT_QUOTES, 'UTF-8')); - $htmlversion = BBCode::convert(stripslashes(str_replace(["\\r", "\\n"], ["", "
\n"], $text))); + $htmlversion = BBCode::convertForUriId(User::getSystemUriId(), stripslashes(str_replace(["\\r", "\\n"], ["", "
\n"], $text))); parent::__construct($sender_name, $sender_email, $sender_email, '', $subject, $htmlversion, $textversion); } diff --git a/saml/saml.php b/saml/saml.php index 050ac00fc..56dd0f5d2 100755 --- a/saml/saml.php +++ b/saml/saml.php @@ -6,7 +6,6 @@ * Author: Ryan */ -use Friendica\App; use Friendica\Content\Text\BBCode; use Friendica\Core\Hook; use Friendica\Core\Logger; @@ -14,7 +13,6 @@ use Friendica\Core\Renderer; use Friendica\Database\DBA; use Friendica\DI; use Friendica\Model\User; -use Friendica\Util\Strings; use OneLogin\Saml2\Utils; require_once(__DIR__ . '/vendor/autoload.php'); @@ -84,7 +82,7 @@ function saml_head(string &$body) function saml_footer(string &$body) { - $fragment = addslashes(BBCode::convert(DI::config()->get('saml', 'settings_statement'))); + $fragment = addslashes(BBCode::convertForUriId(User::getSystemUriId(), DI::config()->get('saml', 'settings_statement'))); $body .= << var target=$("#settings-nickname-desc"); @@ -163,7 +161,7 @@ function saml_sso_reply() } if (!empty($user['uid'])) { - DI::auth()->setForUser($user); + DI::auth()->setForUser(DI::app(), $user); } if (isset($_POST['RelayState']) && Utils::getSelfURL() != $_POST['RelayState']) { diff --git a/tumblr/tumblr.php b/tumblr/tumblr.php index 09b5af867..78c7d3849 100644 --- a/tumblr/tumblr.php +++ b/tumblr/tumblr.php @@ -1267,7 +1267,7 @@ function tumblr_get_contact_by_url(string $url): ?array return null; } - if (is_array($data->response->blog)) { + if (is_array($data->response->blog) || empty($data->response->blog)) { Logger::warning('Unexpected blog format', ['blog' => $blog, 'data' => $data]); return null; } diff --git a/wppost/wppost.php b/wppost/wppost.php index 51ee7247f..0405f78ad 100644 --- a/wppost/wppost.php +++ b/wppost/wppost.php @@ -15,6 +15,7 @@ use Friendica\Database\DBA; use Friendica\DI; use Friendica\Model\Item; use Friendica\Model\Post; +use Friendica\Model\User; use Friendica\Util\XML; function wppost_install() @@ -92,7 +93,7 @@ function wppost_settings_post(array &$b) DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'wppost', 'wp_blog', trim($_POST['wp_blog'])); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'wppost', 'backlink', intval($_POST['wp_backlink'])); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'wppost', 'shortcheck', intval($_POST['wp_shortcheck'])); - $wp_backlink_text = BBCode::convert(trim($_POST['wp_backlink_text']), false, BBCode::BACKLINK); + $wp_backlink_text = BBCode::convertForUriId(User::getSystemUriId(), trim($_POST['wp_backlink_text']), BBCode::BACKLINK); $wp_backlink_text = HTML::toPlaintext($wp_backlink_text, 0, true); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'wppost', 'wp_backlink_text', $wp_backlink_text); } From 3377ef3ba3e0fa4b7433df9691350c0c67ae95e2 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 22 Jul 2023 13:38:13 +0000 Subject: [PATCH 005/388] Bluesky: Fix "E_WARNING: Undefined property: stdClass::$cid" --- bluesky/bluesky.php | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index 3e3e2aaf5..252becc12 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -32,6 +32,7 @@ use Friendica\Core\Hook; use Friendica\Core\Logger; use Friendica\Core\Protocol; use Friendica\Core\Renderer; +use Friendica\Core\System; use Friendica\Core\Worker; use Friendica\Database\DBA; use Friendica\DI; @@ -760,8 +761,8 @@ function bluesky_add_embed(int $uid, array $msg, array $record): array '$type' => 'app.bsky.embed.external', 'external' => [ 'uri' => $msg['url'], - 'title' => $msg['title'], - 'description' => $msg['description'], + 'title' => $msg['title'] ?? '', + 'description' => $msg['description'] ?? '', ] ]; if (!empty($msg['image'])) { @@ -1126,6 +1127,10 @@ function bluesky_add_media(stdClass $embed, array $item, int $fetch_uid, int $le $uri = bluesky_get_uri($embed->record); $shared = Post::selectFirst(['uri-id'], ['uri' => $uri, 'uid' => $item['uid']]); if (empty($shared)) { + if (empty($embed->record->value)) { + Logger::info('Record has got no value', ['record' => $embed->record]); + break; + } $shared = bluesky_get_header($embed->record, $uri, 0, $fetch_uid); $shared = bluesky_get_content($shared, $embed->record->value, $uri, $item['uid'], $level); if (!empty($shared)) { @@ -1178,6 +1183,10 @@ function bluesky_add_media(stdClass $embed, array $item, int $fetch_uid, int $le function bluesky_get_uri(stdClass $post): string { + if (empty($post->cid)) { + Logger::info('Invalid URI', ['post' => $post, 'callstack' => System::callstack(10, 0, true)]); + return ''; + } return $post->uri . ':' . $post->cid; } From 745f9c1e5fec24d62e3631bd5c79a5673821b527 Mon Sep 17 00:00:00 2001 From: Philipp Date: Sun, 2 Jul 2023 23:57:24 +0200 Subject: [PATCH 006/388] Fix Monolog - Use new hook-loading --- monolog/composer.json | 4 +- monolog/composer.lock | 53 +-- monolog/monolog.php | 59 --- monolog/src/Factory/Monolog.php | 54 +++ monolog/src/{ => Monolog}/DevelopHandler.php | 2 +- .../{ => Monolog}/IntrospectionProcessor.php | 13 +- monolog/static/dependencies.config.php | 30 ++ monolog/static/hooks.config.php | 30 ++ monolog/vendor/composer/autoload_classmap.php | 21 +- monolog/vendor/composer/autoload_psr4.php | 2 +- monolog/vendor/composer/autoload_static.php | 23 +- monolog/vendor/composer/installed.json | 53 +-- monolog/vendor/monolog/monolog/CHANGELOG.md | 75 +--- monolog/vendor/monolog/monolog/README.md | 13 +- monolog/vendor/monolog/monolog/composer.json | 28 +- .../Monolog/Attribute/AsMonologProcessor.php | 28 +- .../monolog/src/Monolog/DateTimeImmutable.php | 5 +- .../monolog/src/Monolog/ErrorHandler.php | 139 ++++--- .../Monolog/Formatter/ChromePHPFormatter.php | 54 ++- .../Monolog/Formatter/ElasticaFormatter.php | 16 +- .../Formatter/ElasticsearchFormatter.php | 13 +- .../Monolog/Formatter/FlowdockFormatter.php | 35 +- .../Monolog/Formatter/FluentdFormatter.php | 21 +- .../Monolog/Formatter/FormatterInterface.php | 18 +- .../Formatter/GelfMessageFormatter.php | 116 +++--- .../Formatter/GoogleCloudLoggingFormatter.php | 15 +- .../src/Monolog/Formatter/HtmlFormatter.php | 54 +-- .../src/Monolog/Formatter/JsonFormatter.php | 63 +-- .../src/Monolog/Formatter/LineFormatter.php | 40 +- .../src/Monolog/Formatter/LogglyFormatter.php | 14 +- .../Monolog/Formatter/LogmaticFormatter.php | 28 +- .../Monolog/Formatter/LogstashFormatter.php | 49 +-- .../Monolog/Formatter/MongoDBFormatter.php | 20 +- .../Monolog/Formatter/NormalizerFormatter.php | 65 ++- .../src/Monolog/Formatter/ScalarFormatter.php | 18 +- .../src/Monolog/Formatter/SyslogFormatter.php | 66 --- .../Monolog/Formatter/WildfireFormatter.php | 86 ++-- .../src/Monolog/Handler/AbstractHandler.php | 50 ++- .../Handler/AbstractProcessingHandler.php | 27 +- .../Monolog/Handler/AbstractSyslogHandler.php | 75 ++-- .../src/Monolog/Handler/AmqpHandler.php | 89 ++-- .../Monolog/Handler/BrowserConsoleHandler.php | 74 ++-- .../src/Monolog/Handler/BufferHandler.php | 48 +-- .../src/Monolog/Handler/ChromePHPHandler.php | 51 ++- .../src/Monolog/Handler/CouchDBHandler.php | 38 +- .../src/Monolog/Handler/CubeHandler.php | 54 +-- .../monolog/src/Monolog/Handler/Curl/Util.php | 12 +- .../Monolog/Handler/DeduplicationHandler.php | 76 ++-- .../Handler/DoctrineCouchDBHandler.php | 14 +- .../src/Monolog/Handler/DynamoDbHandler.php | 50 ++- .../src/Monolog/Handler/ElasticaHandler.php | 39 +- .../Monolog/Handler/ElasticsearchHandler.php | 45 +- .../src/Monolog/Handler/ErrorLogHandler.php | 22 +- .../Monolog/Handler/FallbackGroupHandler.php | 15 +- .../src/Monolog/Handler/FilterHandler.php | 105 ++--- .../ActivationStrategyInterface.php | 8 +- .../ChannelLevelActivationStrategy.php | 42 +- .../ErrorLevelActivationStrategy.php | 20 +- .../Monolog/Handler/FingersCrossedHandler.php | 108 ++--- .../src/Monolog/Handler/FirePHPHandler.php | 24 +- .../src/Monolog/Handler/FleepHookHandler.php | 23 +- .../src/Monolog/Handler/FlowdockHandler.php | 29 +- .../Handler/FormattableHandlerInterface.php | 5 +- .../Handler/FormattableHandlerTrait.php | 11 +- .../src/Monolog/Handler/GelfHandler.php | 15 +- .../src/Monolog/Handler/GroupHandler.php | 28 +- .../monolog/src/Monolog/Handler/Handler.php | 4 +- .../src/Monolog/Handler/HandlerInterface.php | 27 +- .../src/Monolog/Handler/HandlerWrapper.php | 30 +- .../src/Monolog/Handler/IFTTTHandler.php | 19 +- .../src/Monolog/Handler/InsightOpsHandler.php | 22 +- .../src/Monolog/Handler/LogEntriesHandler.php | 22 +- .../src/Monolog/Handler/LogglyHandler.php | 49 ++- .../src/Monolog/Handler/LogmaticHandler.php | 50 ++- .../src/Monolog/Handler/MailHandler.php | 28 +- .../src/Monolog/Handler/MandrillHandler.php | 16 +- .../src/Monolog/Handler/MongoDBHandler.php | 28 +- .../Monolog/Handler/NativeMailerHandler.php | 33 +- .../src/Monolog/Handler/NewRelicHandler.php | 91 ++-- .../src/Monolog/Handler/NoopHandler.php | 10 +- .../src/Monolog/Handler/NullHandler.php | 30 +- .../src/Monolog/Handler/OverflowHandler.php | 40 +- .../src/Monolog/Handler/PHPConsoleHandler.php | 142 +++---- .../src/Monolog/Handler/ProcessHandler.php | 27 +- .../Handler/ProcessableHandlerInterface.php | 7 +- .../Handler/ProcessableHandlerTrait.php | 21 +- .../src/Monolog/Handler/PsrHandler.php | 30 +- .../src/Monolog/Handler/PushoverHandler.php | 126 +++--- .../src/Monolog/Handler/RedisHandler.php | 51 ++- .../Monolog/Handler/RedisPubSubHandler.php | 32 +- .../src/Monolog/Handler/RollbarHandler.php | 74 ++-- .../Monolog/Handler/RotatingFileHandler.php | 44 +- .../src/Monolog/Handler/SamplingHandler.php | 59 +-- .../src/Monolog/Handler/SendGridHandler.php | 20 +- .../src/Monolog/Handler/Slack/SlackRecord.php | 140 ++++--- .../src/Monolog/Handler/SlackHandler.php | 32 +- .../Monolog/Handler/SlackWebhookHandler.php | 23 +- .../src/Monolog/Handler/SocketHandler.php | 73 ++-- .../src/Monolog/Handler/SqsHandler.php | 19 +- .../src/Monolog/Handler/StreamHandler.php | 53 ++- .../Monolog/Handler/SymfonyMailerHandler.php | 28 +- .../src/Monolog/Handler/SyslogHandler.php | 20 +- .../Monolog/Handler/SyslogUdp/UdpSocket.php | 31 +- .../src/Monolog/Handler/SyslogUdpHandler.php | 42 +- .../Monolog/Handler/TelegramBotHandler.php | 59 ++- .../src/Monolog/Handler/TestHandler.php | 120 ++++-- .../Handler/WebRequestRecognizerTrait.php | 1 + .../Handler/WhatFailureGroupHandler.php | 37 +- .../Monolog/Handler/ZendMonitorHandler.php | 75 ++-- .../monolog/monolog/src/Monolog/Level.php | 209 ---------- .../monolog/monolog/src/Monolog/LogRecord.php | 112 +---- .../monolog/monolog/src/Monolog/Logger.php | 387 +++++++++++------- .../src/Monolog/Processor/GitProcessor.php | 28 +- .../Monolog/Processor/HostnameProcessor.php | 11 +- .../Processor/IntrospectionProcessor.php | 43 +- .../Processor/MemoryPeakUsageProcessor.php | 8 +- .../src/Monolog/Processor/MemoryProcessor.php | 5 +- .../Processor/MemoryUsageProcessor.php | 8 +- .../Monolog/Processor/MercurialProcessor.php | 26 +- .../Monolog/Processor/ProcessIdProcessor.php | 8 +- .../Monolog/Processor/ProcessorInterface.php | 11 +- .../Processor/PsrLogMessageProcessor.php | 33 +- .../src/Monolog/Processor/TagProcessor.php | 10 +- .../src/Monolog/Processor/UidProcessor.php | 20 +- .../src/Monolog/Processor/WebProcessor.php | 27 +- .../monolog/monolog/src/Monolog/Registry.php | 11 +- .../src/Monolog/ResettableInterface.php | 5 +- .../monolog/src/Monolog/SignalHandler.php | 28 +- .../monolog/src/Monolog/Test/TestCase.php | 51 +-- .../monolog/monolog/src/Monolog/Utils.php | 56 +-- monolog/vendor/psr/log/composer.json | 6 +- monolog/vendor/psr/log/src/AbstractLogger.php | 15 - .../psr/log/src/InvalidArgumentException.php | 7 - monolog/vendor/psr/log/src/LogLevel.php | 18 - .../psr/log/src/LoggerAwareInterface.php | 18 - .../vendor/psr/log/src/LoggerAwareTrait.php | 26 -- .../vendor/psr/log/src/LoggerInterface.php | 125 ------ monolog/vendor/psr/log/src/LoggerTrait.php | 142 ------- monolog/vendor/psr/log/src/NullLogger.php | 30 -- 139 files changed, 2906 insertions(+), 3083 deletions(-) create mode 100644 monolog/src/Factory/Monolog.php rename monolog/src/{ => Monolog}/DevelopHandler.php (98%) rename monolog/src/{ => Monolog}/IntrospectionProcessor.php (86%) create mode 100644 monolog/static/dependencies.config.php create mode 100644 monolog/static/hooks.config.php delete mode 100644 monolog/vendor/monolog/monolog/src/Monolog/Formatter/SyslogFormatter.php delete mode 100644 monolog/vendor/monolog/monolog/src/Monolog/Level.php delete mode 100644 monolog/vendor/psr/log/src/AbstractLogger.php delete mode 100644 monolog/vendor/psr/log/src/InvalidArgumentException.php delete mode 100644 monolog/vendor/psr/log/src/LogLevel.php delete mode 100644 monolog/vendor/psr/log/src/LoggerAwareInterface.php delete mode 100644 monolog/vendor/psr/log/src/LoggerAwareTrait.php delete mode 100644 monolog/vendor/psr/log/src/LoggerInterface.php delete mode 100644 monolog/vendor/psr/log/src/LoggerTrait.php delete mode 100644 monolog/vendor/psr/log/src/NullLogger.php diff --git a/monolog/composer.json b/monolog/composer.json index 9c7f32c3e..7bcb4995d 100644 --- a/monolog/composer.json +++ b/monolog/composer.json @@ -11,8 +11,8 @@ } ], "require": { - "php": ">=7.0", - "monolog/monolog": "^3.2" + "php": ">=7.3", + "monolog/monolog": "^2.9" }, "license": "3-clause BSD license", "config": { diff --git a/monolog/composer.lock b/monolog/composer.lock index 0566f7212..f73b2ef03 100644 --- a/monolog/composer.lock +++ b/monolog/composer.lock @@ -4,45 +4,46 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "e812bcd051a73d1c9b19c91ec88a6a21", + "content-hash": "6fd294bd163b37ac6cc400e0f8785222", "packages": [ { "name": "monolog/monolog", - "version": "3.2.0", + "version": "2.9.1", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "305444bc6fb6c89e490f4b34fa6e979584d7fa81" + "reference": "f259e2b15fb95494c83f52d3caad003bbf5ffaa1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/305444bc6fb6c89e490f4b34fa6e979584d7fa81", - "reference": "305444bc6fb6c89e490f4b34fa6e979584d7fa81", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/f259e2b15fb95494c83f52d3caad003bbf5ffaa1", + "reference": "f259e2b15fb95494c83f52d3caad003bbf5ffaa1", "shasum": "" }, "require": { - "php": ">=8.1", - "psr/log": "^2.0 || ^3.0" + "php": ">=7.2", + "psr/log": "^1.0.1 || ^2.0 || ^3.0" }, "provide": { - "psr/log-implementation": "3.0.0" + "psr/log-implementation": "1.0.0 || 2.0.0 || 3.0.0" }, "require-dev": { - "aws/aws-sdk-php": "^3.0", + "aws/aws-sdk-php": "^2.4.9 || ^3.0", "doctrine/couchdb": "~1.0@dev", "elasticsearch/elasticsearch": "^7 || ^8", "ext-json": "*", - "graylog2/gelf-php": "^1.4.2", + "graylog2/gelf-php": "^1.4.2 || ^2@dev", "guzzlehttp/guzzle": "^7.4", "guzzlehttp/psr7": "^2.2", "mongodb/mongodb": "^1.8", "php-amqplib/php-amqplib": "~2.4 || ^3", - "phpstan/phpstan": "^1.4", - "phpstan/phpstan-deprecation-rules": "^1.0", - "phpstan/phpstan-strict-rules": "^1.1", - "phpunit/phpunit": "^9.5.16", - "predis/predis": "^1.1", + "phpspec/prophecy": "^1.15", + "phpstan/phpstan": "^0.12.91", + "phpunit/phpunit": "^8.5.14", + "predis/predis": "^1.1 || ^2.0", + "rollbar/rollbar": "^1.3 || ^2 || ^3", "ruflin/elastica": "^7", + "swiftmailer/swiftmailer": "^5.3|^6.0", "symfony/mailer": "^5.4 || ^6", "symfony/mime": "^5.4 || ^6" }, @@ -65,7 +66,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.x-dev" + "dev-main": "2.x-dev" } }, "autoload": { @@ -101,34 +102,34 @@ "type": "tidelift" } ], - "time": "2022-07-24T12:00:55+00:00" + "time": "2023-02-06T13:44:46+00:00" }, { "name": "psr/log", - "version": "3.0.0", + "version": "1.1.4", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001" + "reference": "d49695b909c3b7628b6289db5479a1c204601f11" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001", - "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", + "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11", "shasum": "" }, "require": { - "php": ">=8.0.0" + "php": ">=5.3.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.x-dev" + "dev-master": "1.1.x-dev" } }, "autoload": { "psr-4": { - "Psr\\Log\\": "src" + "Psr\\Log\\": "Psr/Log/" } }, "notification-url": "https://packagist.org/downloads/", @@ -148,7 +149,7 @@ "psr", "psr-3" ], - "time": "2021-07-14T16:46:02+00:00" + "time": "2021-05-03T11:20:27+00:00" } ], "packages-dev": [], @@ -158,7 +159,7 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": ">=7.0" + "php": ">=7.3" }, "platform-dev": [], "plugin-api-version": "1.1.0" diff --git a/monolog/monolog.php b/monolog/monolog.php index efdcb3feb..b13efff94 100644 --- a/monolog/monolog.php +++ b/monolog/monolog.php @@ -5,62 +5,3 @@ * Version: 1.0 * Author: Philipp Holzer */ - -use Friendica\App; -use Friendica\Core\Hook; -use Friendica\Addon\monolog\src\IntrospectionProcessor; -use Friendica\DI; -use Psr\Log\LogLevel; - -require_once __DIR__ . '/vendor/autoload.php'; - -function monolog_install() -{ - Hook::register('logger_instance' , __FILE__, 'monolog_instance'); -} - -function monolog_uninstall() -{ - Hook::unregister('logger_instance', __FILE__, 'monolog_instance'); -} - -function monolog_instance(array &$data) -{ - if ($data['name'] !== 'monolog') { - return; - } - - $loggerTimeZone = new \DateTimeZone('UTC'); - - $logger = new Monolog\Logger($data['channel']); - $logger->setTimezone($loggerTimeZone); - $logger->pushProcessor(new Monolog\Processor\PsrLogMessageProcessor()); - $logger->pushProcessor(new Monolog\Processor\ProcessIdProcessor()); - $logger->pushProcessor(new Monolog\Processor\UidProcessor()); - $logger->pushProcessor(new IntrospectionProcessor($data['introspection'], LogLevel::DEBUG)); - - $stream = DI::config()->get('system', 'logfile'); - - // just add a stream in case it's either writable or not file - if (!is_file($stream) || is_writable($stream)) { - try { - $loglevel = Monolog\Logger::toMonologLevel($data['loglevel']); - - // fallback to notice if an invalid loglevel is set - if (!is_int($loglevel)) { - $loglevel = LogLevel::NOTICE; - } - - $fileHandler = new Monolog\Handler\StreamHandler($stream, $loglevel); - - $formatter = new Monolog\Formatter\LineFormatter("%datetime% %channel% [%level_name%]: %message% %context% %extra%\n"); - $fileHandler->setFormatter($formatter); - - $logger->pushHandler($fileHandler); - } catch (\Throwable $e) { - return; - } - } - - $data['storage'] = $logger; -} diff --git a/monolog/src/Factory/Monolog.php b/monolog/src/Factory/Monolog.php new file mode 100644 index 000000000..c5c698249 --- /dev/null +++ b/monolog/src/Factory/Monolog.php @@ -0,0 +1,54 @@ +channel); + $logger->setTimezone($loggerTimeZone); + $logger->pushProcessor(new PsrLogMessageProcessor()); + $logger->pushProcessor(new ProcessIdProcessor()); + $logger->pushProcessor(new UidProcessor()); + $logger->pushProcessor(new IntrospectionProcessor($this->introspection, LogLevel::DEBUG)); + + $logfile = $config->get('system', 'logfile'); + + // just add a stream in case it's either writable or not file + if (is_writable($logfile)) { + $loglevel = $loglevel ?? static::mapLegacyConfigDebugLevel($config->get('system', 'loglevel')); + $loglevel = Logger::toMonologLevel($loglevel); + + // fallback to notice if an invalid loglevel is set + if (!is_int($loglevel)) { + $loglevel = LogLevel::NOTICE; + } + + $fileHandler = new StreamHandler($logfile, $loglevel); + + $formatter = new LineFormatter("%datetime% %channel% [%level_name%]: %message% %context% %extra%\n"); + $fileHandler->setFormatter($formatter); + + $logger->pushHandler($fileHandler); + } + + return $logger; + } +} diff --git a/monolog/src/DevelopHandler.php b/monolog/src/Monolog/DevelopHandler.php similarity index 98% rename from monolog/src/DevelopHandler.php rename to monolog/src/Monolog/DevelopHandler.php index e3d31e64f..735ebac7d 100644 --- a/monolog/src/DevelopHandler.php +++ b/monolog/src/Monolog/DevelopHandler.php @@ -19,7 +19,7 @@ * */ -namespace Friendica\Addon\monolog\src; +namespace Friendica\Addon\monolog\src\Monolog; use Friendica\App\Request; use Monolog\Handler; diff --git a/monolog/src/IntrospectionProcessor.php b/monolog/src/Monolog/IntrospectionProcessor.php similarity index 86% rename from monolog/src/IntrospectionProcessor.php rename to monolog/src/Monolog/IntrospectionProcessor.php index 8ba6023ec..2df0e21a5 100644 --- a/monolog/src/IntrospectionProcessor.php +++ b/monolog/src/Monolog/IntrospectionProcessor.php @@ -19,11 +19,10 @@ * */ -namespace Friendica\Addon\monolog\src; +namespace Friendica\Addon\monolog\src\Monolog; use Friendica\Core\Logger\Util\Introspection; use Monolog\Logger; -use Monolog\LogRecord; use Monolog\Processor\ProcessorInterface; /** @@ -42,19 +41,19 @@ class IntrospectionProcessor implements ProcessorInterface public function __construct(Introspection $introspection, $level = Logger::DEBUG) { $this->level = Logger::toMonologLevel($level); - $introspection->addClasses(['Monolog\\']); + $introspection->addClasses(['Monolog\\', static::class]); $this->introspection = $introspection; } - public function __invoke(LogRecord $record): LogRecord + public function __invoke(array $record): array { // return if the level is not high enough - if ($record->level < $this->level) { + if ($record['level'] < $this->level) { return $record; } // we should have the call source now - $record->extra = array_merge( - $record->extra, + $record['extra'] = array_merge( + $record['extra'], $this->introspection->getRecord() ); diff --git a/monolog/static/dependencies.config.php b/monolog/static/dependencies.config.php new file mode 100644 index 000000000..365f38254 --- /dev/null +++ b/monolog/static/dependencies.config.php @@ -0,0 +1,30 @@ + +. + * + */ + +return [ + \Monolog\Logger::class => [ + 'instanceOf' => \Friendica\Addon\monolog\src\Factory\Monolog::class, + 'call' => [ + ['create', [], \Dice\Dice::CHAIN_CALL], + ], + ], +]; diff --git a/monolog/static/hooks.config.php b/monolog/static/hooks.config.php new file mode 100644 index 000000000..cb3c7efaf --- /dev/null +++ b/monolog/static/hooks.config.php @@ -0,0 +1,30 @@ +. + * + */ + +use Friendica\Core\Hooks\Capabilities\HookType as H; + +return [ + H::STRATEGY => [ + \Psr\Log\LoggerInterface::class => [ + \Monolog\Logger::class => ['monolog'], + ], + ], +]; diff --git a/monolog/vendor/composer/autoload_classmap.php b/monolog/vendor/composer/autoload_classmap.php index 706092031..3c89f22cb 100644 --- a/monolog/vendor/composer/autoload_classmap.php +++ b/monolog/vendor/composer/autoload_classmap.php @@ -26,7 +26,6 @@ return array( 'Monolog\\Formatter\\MongoDBFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php', 'Monolog\\Formatter\\NormalizerFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php', 'Monolog\\Formatter\\ScalarFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/ScalarFormatter.php', - 'Monolog\\Formatter\\SyslogFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/SyslogFormatter.php', 'Monolog\\Formatter\\WildfireFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php', 'Monolog\\Handler\\AbstractHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/AbstractHandler.php', 'Monolog\\Handler\\AbstractProcessingHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php', @@ -92,6 +91,7 @@ return array( 'Monolog\\Handler\\SocketHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SocketHandler.php', 'Monolog\\Handler\\SqsHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SqsHandler.php', 'Monolog\\Handler\\StreamHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/StreamHandler.php', + 'Monolog\\Handler\\SwiftMailerHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.php', 'Monolog\\Handler\\SymfonyMailerHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SymfonyMailerHandler.php', 'Monolog\\Handler\\SyslogHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SyslogHandler.php', 'Monolog\\Handler\\SyslogUdpHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php', @@ -121,12 +121,15 @@ return array( 'Monolog\\SignalHandler' => $vendorDir . '/monolog/monolog/src/Monolog/SignalHandler.php', 'Monolog\\Test\\TestCase' => $vendorDir . '/monolog/monolog/src/Monolog/Test/TestCase.php', 'Monolog\\Utils' => $vendorDir . '/monolog/monolog/src/Monolog/Utils.php', - 'Psr\\Log\\AbstractLogger' => $vendorDir . '/psr/log/src/AbstractLogger.php', - 'Psr\\Log\\InvalidArgumentException' => $vendorDir . '/psr/log/src/InvalidArgumentException.php', - 'Psr\\Log\\LogLevel' => $vendorDir . '/psr/log/src/LogLevel.php', - 'Psr\\Log\\LoggerAwareInterface' => $vendorDir . '/psr/log/src/LoggerAwareInterface.php', - 'Psr\\Log\\LoggerAwareTrait' => $vendorDir . '/psr/log/src/LoggerAwareTrait.php', - 'Psr\\Log\\LoggerInterface' => $vendorDir . '/psr/log/src/LoggerInterface.php', - 'Psr\\Log\\LoggerTrait' => $vendorDir . '/psr/log/src/LoggerTrait.php', - 'Psr\\Log\\NullLogger' => $vendorDir . '/psr/log/src/NullLogger.php', + 'Psr\\Log\\AbstractLogger' => $vendorDir . '/psr/log/Psr/Log/AbstractLogger.php', + 'Psr\\Log\\InvalidArgumentException' => $vendorDir . '/psr/log/Psr/Log/InvalidArgumentException.php', + 'Psr\\Log\\LogLevel' => $vendorDir . '/psr/log/Psr/Log/LogLevel.php', + 'Psr\\Log\\LoggerAwareInterface' => $vendorDir . '/psr/log/Psr/Log/LoggerAwareInterface.php', + 'Psr\\Log\\LoggerAwareTrait' => $vendorDir . '/psr/log/Psr/Log/LoggerAwareTrait.php', + 'Psr\\Log\\LoggerInterface' => $vendorDir . '/psr/log/Psr/Log/LoggerInterface.php', + 'Psr\\Log\\LoggerTrait' => $vendorDir . '/psr/log/Psr/Log/LoggerTrait.php', + 'Psr\\Log\\NullLogger' => $vendorDir . '/psr/log/Psr/Log/NullLogger.php', + 'Psr\\Log\\Test\\DummyTest' => $vendorDir . '/psr/log/Psr/Log/Test/DummyTest.php', + 'Psr\\Log\\Test\\LoggerInterfaceTest' => $vendorDir . '/psr/log/Psr/Log/Test/LoggerInterfaceTest.php', + 'Psr\\Log\\Test\\TestLogger' => $vendorDir . '/psr/log/Psr/Log/Test/TestLogger.php', ); diff --git a/monolog/vendor/composer/autoload_psr4.php b/monolog/vendor/composer/autoload_psr4.php index afcfb31e1..9cb5b63df 100644 --- a/monolog/vendor/composer/autoload_psr4.php +++ b/monolog/vendor/composer/autoload_psr4.php @@ -6,6 +6,6 @@ $vendorDir = dirname(dirname(__FILE__)); $baseDir = dirname($vendorDir); return array( - 'Psr\\Log\\' => array($vendorDir . '/psr/log/src'), + 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'), 'Monolog\\' => array($vendorDir . '/monolog/monolog/src/Monolog'), ); diff --git a/monolog/vendor/composer/autoload_static.php b/monolog/vendor/composer/autoload_static.php index 85bd86fde..95ed9e754 100644 --- a/monolog/vendor/composer/autoload_static.php +++ b/monolog/vendor/composer/autoload_static.php @@ -20,7 +20,7 @@ class ComposerStaticInitMonologAddon public static $prefixDirsPsr4 = array ( 'Psr\\Log\\' => array ( - 0 => __DIR__ . '/..' . '/psr/log/src', + 0 => __DIR__ . '/..' . '/psr/log/Psr/Log', ), 'Monolog\\' => array ( @@ -49,7 +49,6 @@ class ComposerStaticInitMonologAddon 'Monolog\\Formatter\\MongoDBFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php', 'Monolog\\Formatter\\NormalizerFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php', 'Monolog\\Formatter\\ScalarFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/ScalarFormatter.php', - 'Monolog\\Formatter\\SyslogFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/SyslogFormatter.php', 'Monolog\\Formatter\\WildfireFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php', 'Monolog\\Handler\\AbstractHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/AbstractHandler.php', 'Monolog\\Handler\\AbstractProcessingHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php', @@ -115,6 +114,7 @@ class ComposerStaticInitMonologAddon 'Monolog\\Handler\\SocketHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SocketHandler.php', 'Monolog\\Handler\\SqsHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SqsHandler.php', 'Monolog\\Handler\\StreamHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/StreamHandler.php', + 'Monolog\\Handler\\SwiftMailerHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.php', 'Monolog\\Handler\\SymfonyMailerHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SymfonyMailerHandler.php', 'Monolog\\Handler\\SyslogHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SyslogHandler.php', 'Monolog\\Handler\\SyslogUdpHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php', @@ -144,14 +144,17 @@ class ComposerStaticInitMonologAddon 'Monolog\\SignalHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/SignalHandler.php', 'Monolog\\Test\\TestCase' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Test/TestCase.php', 'Monolog\\Utils' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Utils.php', - 'Psr\\Log\\AbstractLogger' => __DIR__ . '/..' . '/psr/log/src/AbstractLogger.php', - 'Psr\\Log\\InvalidArgumentException' => __DIR__ . '/..' . '/psr/log/src/InvalidArgumentException.php', - 'Psr\\Log\\LogLevel' => __DIR__ . '/..' . '/psr/log/src/LogLevel.php', - 'Psr\\Log\\LoggerAwareInterface' => __DIR__ . '/..' . '/psr/log/src/LoggerAwareInterface.php', - 'Psr\\Log\\LoggerAwareTrait' => __DIR__ . '/..' . '/psr/log/src/LoggerAwareTrait.php', - 'Psr\\Log\\LoggerInterface' => __DIR__ . '/..' . '/psr/log/src/LoggerInterface.php', - 'Psr\\Log\\LoggerTrait' => __DIR__ . '/..' . '/psr/log/src/LoggerTrait.php', - 'Psr\\Log\\NullLogger' => __DIR__ . '/..' . '/psr/log/src/NullLogger.php', + 'Psr\\Log\\AbstractLogger' => __DIR__ . '/..' . '/psr/log/Psr/Log/AbstractLogger.php', + 'Psr\\Log\\InvalidArgumentException' => __DIR__ . '/..' . '/psr/log/Psr/Log/InvalidArgumentException.php', + 'Psr\\Log\\LogLevel' => __DIR__ . '/..' . '/psr/log/Psr/Log/LogLevel.php', + 'Psr\\Log\\LoggerAwareInterface' => __DIR__ . '/..' . '/psr/log/Psr/Log/LoggerAwareInterface.php', + 'Psr\\Log\\LoggerAwareTrait' => __DIR__ . '/..' . '/psr/log/Psr/Log/LoggerAwareTrait.php', + 'Psr\\Log\\LoggerInterface' => __DIR__ . '/..' . '/psr/log/Psr/Log/LoggerInterface.php', + 'Psr\\Log\\LoggerTrait' => __DIR__ . '/..' . '/psr/log/Psr/Log/LoggerTrait.php', + 'Psr\\Log\\NullLogger' => __DIR__ . '/..' . '/psr/log/Psr/Log/NullLogger.php', + 'Psr\\Log\\Test\\DummyTest' => __DIR__ . '/..' . '/psr/log/Psr/Log/Test/DummyTest.php', + 'Psr\\Log\\Test\\LoggerInterfaceTest' => __DIR__ . '/..' . '/psr/log/Psr/Log/Test/LoggerInterfaceTest.php', + 'Psr\\Log\\Test\\TestLogger' => __DIR__ . '/..' . '/psr/log/Psr/Log/Test/TestLogger.php', ); public static function getInitializer(ClassLoader $loader) diff --git a/monolog/vendor/composer/installed.json b/monolog/vendor/composer/installed.json index c01706ed1..ea2bb1784 100644 --- a/monolog/vendor/composer/installed.json +++ b/monolog/vendor/composer/installed.json @@ -1,42 +1,43 @@ [ { "name": "monolog/monolog", - "version": "3.2.0", - "version_normalized": "3.2.0.0", + "version": "2.9.1", + "version_normalized": "2.9.1.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "305444bc6fb6c89e490f4b34fa6e979584d7fa81" + "reference": "f259e2b15fb95494c83f52d3caad003bbf5ffaa1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/305444bc6fb6c89e490f4b34fa6e979584d7fa81", - "reference": "305444bc6fb6c89e490f4b34fa6e979584d7fa81", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/f259e2b15fb95494c83f52d3caad003bbf5ffaa1", + "reference": "f259e2b15fb95494c83f52d3caad003bbf5ffaa1", "shasum": "" }, "require": { - "php": ">=8.1", - "psr/log": "^2.0 || ^3.0" + "php": ">=7.2", + "psr/log": "^1.0.1 || ^2.0 || ^3.0" }, "provide": { - "psr/log-implementation": "3.0.0" + "psr/log-implementation": "1.0.0 || 2.0.0 || 3.0.0" }, "require-dev": { - "aws/aws-sdk-php": "^3.0", + "aws/aws-sdk-php": "^2.4.9 || ^3.0", "doctrine/couchdb": "~1.0@dev", "elasticsearch/elasticsearch": "^7 || ^8", "ext-json": "*", - "graylog2/gelf-php": "^1.4.2", + "graylog2/gelf-php": "^1.4.2 || ^2@dev", "guzzlehttp/guzzle": "^7.4", "guzzlehttp/psr7": "^2.2", "mongodb/mongodb": "^1.8", "php-amqplib/php-amqplib": "~2.4 || ^3", - "phpstan/phpstan": "^1.4", - "phpstan/phpstan-deprecation-rules": "^1.0", - "phpstan/phpstan-strict-rules": "^1.1", - "phpunit/phpunit": "^9.5.16", - "predis/predis": "^1.1", + "phpspec/prophecy": "^1.15", + "phpstan/phpstan": "^0.12.91", + "phpunit/phpunit": "^8.5.14", + "predis/predis": "^1.1 || ^2.0", + "rollbar/rollbar": "^1.3 || ^2 || ^3", "ruflin/elastica": "^7", + "swiftmailer/swiftmailer": "^5.3|^6.0", "symfony/mailer": "^5.4 || ^6", "symfony/mime": "^5.4 || ^6" }, @@ -56,11 +57,11 @@ "rollbar/rollbar": "Allow sending log messages to Rollbar", "ruflin/elastica": "Allow sending log messages to an Elastic Search server" }, - "time": "2022-07-24T12:00:55+00:00", + "time": "2023-02-06T13:44:46+00:00", "type": "library", "extra": { "branch-alias": { - "dev-main": "3.x-dev" + "dev-main": "2.x-dev" } }, "installation-source": "dist", @@ -100,33 +101,33 @@ }, { "name": "psr/log", - "version": "3.0.0", - "version_normalized": "3.0.0.0", + "version": "1.1.4", + "version_normalized": "1.1.4.0", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001" + "reference": "d49695b909c3b7628b6289db5479a1c204601f11" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001", - "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", + "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11", "shasum": "" }, "require": { - "php": ">=8.0.0" + "php": ">=5.3.0" }, - "time": "2021-07-14T16:46:02+00:00", + "time": "2021-05-03T11:20:27+00:00", "type": "library", "extra": { "branch-alias": { - "dev-master": "3.x-dev" + "dev-master": "1.1.x-dev" } }, "installation-source": "dist", "autoload": { "psr-4": { - "Psr\\Log\\": "src" + "Psr\\Log\\": "Psr/Log/" } }, "notification-url": "https://packagist.org/downloads/", diff --git a/monolog/vendor/monolog/monolog/CHANGELOG.md b/monolog/vendor/monolog/monolog/CHANGELOG.md index fa0acea36..8a8c65124 100644 --- a/monolog/vendor/monolog/monolog/CHANGELOG.md +++ b/monolog/vendor/monolog/monolog/CHANGELOG.md @@ -1,70 +1,17 @@ -### 3.2.0 (2022-07-24) +### 2.9.1 (2023-02-06) - * Deprecated `CubeHandler` and `PHPConsoleHandler` as both projects are abandoned and those should not be used anymore (#1734) - * Marked `Logger` `@final` as it should not be extended, prefer composition or talk to us if you are missing something - * Added RFC 5424 level (`7` to `0`) support to `Logger::log` and `Logger::addRecord` to increase interoperability (#1723) - * Added `SyslogFormatter` to output syslog-like files which can be consumed by tools like [lnav](https://lnav.org/) (#1689) - * Added support for `__toString` for objects which are not json serializable in `JsonFormatter` (#1733) - * Added `GoogleCloudLoggingFormatter` (#1719) - * Added support for Predis 2.x (#1732) - * Added `AmqpHandler->setExtraAttributes` to allow configuring attributes when using an AMQPExchange (#1724) - * Fixed serialization/unserialization of handlers to make sure private properties are included (#1727) - * Fixed allowInlineLineBreaks in LineFormatter causing issues with windows paths containing `\n` or `\r` sequences (#1720) - * Fixed max normalization depth not being taken into account when formatting exceptions with a deep chain of previous exceptions (#1726) - * Fixed PHP 8.2 deprecation warnings (#1722) - * Fixed rare race condition or filesystem issue where StreamHandler is unable to create the directory the log should go into yet it exists already (#1678) + * Fixed Logger not being serializable anymore (#1792) -### 3.1.0 (2022-06-09) +### 2.9.0 (2023-02-05) - * Added `$datetime` parameter to `Logger::addRecord` as low level API to allow logging into the past or future (#1682) - * Added `Logger::useLoggingLoopDetection` to allow disabling cyclic logging detection in concurrent frameworks (#1681) - * Fixed handling of fatal errors if callPrevious is disabled in ErrorHandler (#1670) - * Fixed interop issue by removing the need for a return type in ProcessorInterface (#1680) - * Marked the reusable `Monolog\Test\TestCase` class as `@internal` to make sure PHPStorm does not show it above PHPUnit, you may still use it to test your own handlers/etc though (#1677) - * Fixed RotatingFileHandler issue when the date format contained slashes (#1671) - -### 3.0.0 (2022-05-10) - -Changes from RC1 - -- The `Monolog\LevelName` enum does not exist anymore, use `Monolog\Level->getName()` instead. - -### 3.0.0-RC1 (2022-05-08) - -This is mostly a cleanup release offering stronger type guarantees for integrators with the -array->object/enum changes, but there is no big new feature for end users. - -See [UPGRADE notes](UPGRADE.md#300) for details on all breaking changes especially if you are extending/implementing Monolog classes/interfaces. - -Noteworthy BC Breaks: - -- The minimum supported PHP version is now `8.1.0`. -- Log records have been converted from an array to a [`Monolog\LogRecord` object](src/Monolog/LogRecord.php) - with public (and mostly readonly) properties. e.g. instead of doing - `$record['context']` use `$record->context`. - In formatters or handlers if you rather need an array to work with you can use `$record->toArray()` - to get back a Monolog 1/2 style record array. This will contain the enum values instead of enum cases - in the `level` and `level_name` keys to be more backwards compatible and use simpler data types. -- `FormatterInterface`, `HandlerInterface`, `ProcessorInterface`, etc. changed to contain `LogRecord $record` - instead of `array $record` parameter types. If you want to support multiple Monolog versions this should - be possible by type-hinting nothing, or `array|LogRecord` if you support PHP 8.0+. You can then code - against the $record using Monolog 2 style as LogRecord implements ArrayAccess for BC. - The interfaces do not require a `LogRecord` return type even where it would be applicable, but if you only - support Monolog 3 in integration code I would recommend you use `LogRecord` return types wherever fitting - to ensure forward compatibility as it may be added in Monolog 4. -- Log levels are now enums [`Monolog\Level`](src/Monolog/Level.php) and [`Monolog\LevelName`](src/Monolog/LevelName.php) -- Removed deprecated SwiftMailerHandler, migrate to SymfonyMailerHandler instead. -- `ResettableInterface::reset()` now requires a void return type. -- All properties have had types added, which may require you to do so as well if you extended - a Monolog class and declared the same property. - -New deprecations: - -- `Logger::DEBUG`, `Logger::ERROR`, etc. are now deprecated in favor of the `Monolog\Level` enum. - e.g. instead of `Logger::WARNING` use `Level::Warning` if you need to pass the enum case - to Monolog or one of its handlers, or `Level::Warning->value` if you need the integer - value equal to what `Logger::WARNING` was giving you. -- `Logger::getLevelName()` is now deprecated. + * Deprecated FlowdockHandler & Formatter as the flowdock service was shutdown (#1748) + * Added support for enum context values in PsrLogMessageProcessor (#1773) + * Added graylog2/gelf-php 2.x support (#1747) + * Improved `BrowserConsoleHandler` logging to use more appropriate methods than just console.log in the browser (#1739) + * Fixed `WhatFailureGroupHandler` not catching errors happening inside `close()` (#1791) + * Fixed datetime field in `GoogleCloudLoggingFormatter` (#1758) + * Fixed infinite loop detection within Fibers (#1753) + * Fixed `AmqpHandler->setExtraAttributes` not working with buffering handler wrappers (#1781) ### 2.8.0 (2022-07-24) diff --git a/monolog/vendor/monolog/monolog/README.md b/monolog/vendor/monolog/monolog/README.md index 87c7f664d..bfcae0c00 100644 --- a/monolog/vendor/monolog/monolog/README.md +++ b/monolog/vendor/monolog/monolog/README.md @@ -3,8 +3,6 @@ [![Total Downloads](https://img.shields.io/packagist/dt/monolog/monolog.svg)](https://packagist.org/packages/monolog/monolog) [![Latest Stable Version](https://img.shields.io/packagist/v/monolog/monolog.svg)](https://packagist.org/packages/monolog/monolog) -> ⚠ This is the **documentation for Monolog 3.x**, if you are using older releases -> see the documentation for [Monolog 2.x](https://github.com/Seldaek/monolog/blob/2.x/README.md) or [Monolog 1.x](https://github.com/Seldaek/monolog/blob/1.x/README.md) ⚠ Monolog sends your logs to files, sockets, inboxes, databases and various web services. See the complete list of handlers below. Special handlers @@ -30,13 +28,12 @@ $ composer require monolog/monolog ```php pushHandler(new StreamHandler('path/to/your.log', Level::Warning)); +$log->pushHandler(new StreamHandler('path/to/your.log', Logger::WARNING)); // add records to the log $log->warning('Foo'); @@ -53,7 +50,7 @@ $log->error('Bar'); ## Support Monolog Financially -Get supported Monolog and help fund the project with the [Tidelift Subscription](https://tidelift.com/subscription/pkg/packagist-monolog-monolog?utm_source=packagist-monolog-monolog&utm_medium=referral&utm_campaign=enterprise) or via [GitHub sponsorship](https://github.com/sponsors/Seldaek). +Get supported Monolog and help fund the project with the [Tidelift Subscription](https://tidelift.com/subscription/pkg/packagist-monolog-monolog?utm_source=packagist-monolog-monolog&utm_medium=referral&utm_campaign=enterprise) or via [GitHub sponsorship](https://github.com/sponsors/Seldaek). Tidelift delivers commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. @@ -67,13 +64,11 @@ can also add your own there if you publish one. ### Requirements -- Monolog `^3.0` works with PHP 8.1 or above. -- Monolog `^2.5` works with PHP 7.2 or above. -- Monolog `^1.25` works with PHP 5.3 up to 8.1, but is not very maintained anymore and will not receive PHP support fixes anymore. +- Monolog `^2.0` works with PHP 7.2 or above, use Monolog `^1.25` for PHP 5.3+ support. ### Support -Monolog 1.x support is somewhat limited at this point and only important fixes will be done. You should migrate to Monolog 2 or 3 where possible to benefit from all the latest features and fixes. +Monolog 1.x support is somewhat limited at this point and only important fixes will be done. You should migrate to Monolog 2 where possible to benefit from all the latest features and fixes. ### Submitting bugs and feature requests diff --git a/monolog/vendor/monolog/monolog/composer.json b/monolog/vendor/monolog/monolog/composer.json index 3a48e6db4..b9437d6d5 100644 --- a/monolog/vendor/monolog/monolog/composer.json +++ b/monolog/vendor/monolog/monolog/composer.json @@ -13,25 +13,26 @@ } ], "require": { - "php": ">=8.1", - "psr/log": "^2.0 || ^3.0" + "php": ">=7.2", + "psr/log": "^1.0.1 || ^2.0 || ^3.0" }, "require-dev": { "ext-json": "*", - "aws/aws-sdk-php": "^3.0", + "aws/aws-sdk-php": "^2.4.9 || ^3.0", "doctrine/couchdb": "~1.0@dev", "elasticsearch/elasticsearch": "^7 || ^8", - "graylog2/gelf-php": "^1.4.2", + "graylog2/gelf-php": "^1.4.2 || ^2@dev", "guzzlehttp/guzzle": "^7.4", "guzzlehttp/psr7": "^2.2", "mongodb/mongodb": "^1.8", "php-amqplib/php-amqplib": "~2.4 || ^3", - "phpstan/phpstan": "^1.4", - "phpstan/phpstan-deprecation-rules": "^1.0", - "phpstan/phpstan-strict-rules": "^1.1", - "phpunit/phpunit": "^9.5.16", - "predis/predis": "^1.1", + "phpspec/prophecy": "^1.15", + "phpstan/phpstan": "^0.12.91", + "phpunit/phpunit": "^8.5.14", + "predis/predis": "^1.1 || ^2.0", + "rollbar/rollbar": "^1.3 || ^2 || ^3", "ruflin/elastica": "^7", + "swiftmailer/swiftmailer": "^5.3|^6.0", "symfony/mailer": "^5.4 || ^6", "symfony/mime": "^5.4 || ^6" }, @@ -58,11 +59,11 @@ "psr-4": {"Monolog\\": "tests/Monolog"} }, "provide": { - "psr/log-implementation": "3.0.0" + "psr/log-implementation": "1.0.0 || 2.0.0 || 3.0.0" }, "extra": { "branch-alias": { - "dev-main": "3.x-dev" + "dev-main": "2.x-dev" } }, "scripts": { @@ -72,6 +73,9 @@ "config": { "lock": false, "sort-packages": true, - "platform-check": false + "platform-check": false, + "allow-plugins": { + "composer/package-versions-deprecated": true + } } } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Attribute/AsMonologProcessor.php b/monolog/vendor/monolog/monolog/src/Monolog/Attribute/AsMonologProcessor.php index f8b250217..188bbb0d8 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Attribute/AsMonologProcessor.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Attribute/AsMonologProcessor.php @@ -13,24 +13,34 @@ namespace Monolog\Attribute; /** * A reusable attribute to help configure a class or a method as a processor. - * + * * Using it offers no guarantee: it needs to be leveraged by a Monolog third-party consumer. - * + * * Using it with the Monolog library only has no effect at all: processors should still be turned into a callable if * needed and manually pushed to the loggers and to the processable handlers. */ #[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)] class AsMonologProcessor { + /** @var string|null */ + public $channel = null; + /** @var string|null */ + public $handler = null; + /** @var string|null */ + public $method = null; + /** - * @param string|null $channel The logging channel the processor should be pushed to. - * @param string|null $handler The handler the processor should be pushed to. - * @param string|null $method The method that processes the records (if the attribute is used at the class level). + * @param string|null $channel The logging channel the processor should be pushed to. + * @param string|null $handler The handler the processor should be pushed to. + * @param string|null $method The method that processes the records (if the attribute is used at the class level). */ public function __construct( - public readonly ?string $channel = null, - public readonly ?string $handler = null, - public readonly ?string $method = null + ?string $channel = null, + ?string $handler = null, + ?string $method = null ) { + $this->channel = $channel; + $this->handler = $handler; + $this->method = $method; } -} +} diff --git a/monolog/vendor/monolog/monolog/src/Monolog/DateTimeImmutable.php b/monolog/vendor/monolog/monolog/src/Monolog/DateTimeImmutable.php index 274b73ea1..6a1ba9b25 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/DateTimeImmutable.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/DateTimeImmutable.php @@ -21,7 +21,10 @@ use DateTimeZone; */ class DateTimeImmutable extends \DateTimeImmutable implements \JsonSerializable { - private bool $useMicroseconds; + /** + * @var bool + */ + private $useMicroseconds; public function __construct(bool $useMicroseconds, ?DateTimeZone $timezone = null) { diff --git a/monolog/vendor/monolog/monolog/src/Monolog/ErrorHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/ErrorHandler.php index 2ed460357..576f1713f 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/ErrorHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/ErrorHandler.php @@ -11,7 +11,6 @@ namespace Monolog; -use Closure; use Psr\Log\LoggerInterface; use Psr\Log\LogLevel; @@ -26,33 +25,35 @@ use Psr\Log\LogLevel; */ class ErrorHandler { - private Closure|null $previousExceptionHandler = null; + /** @var LoggerInterface */ + private $logger; + /** @var ?callable */ + private $previousExceptionHandler = null; /** @var array an array of class name to LogLevel::* constant mapping */ - private array $uncaughtExceptionLevelMap = []; - - /** @var Closure|true|null */ - private Closure|bool|null $previousErrorHandler = null; + private $uncaughtExceptionLevelMap = []; + /** @var callable|true|null */ + private $previousErrorHandler = null; /** @var array an array of E_* constant to LogLevel::* constant mapping */ - private array $errorLevelMap = []; - - private bool $handleOnlyReportedErrors = true; - - private bool $hasFatalErrorHandler = false; - - private string $fatalLevel = LogLevel::ALERT; - - private string|null $reservedMemory = null; + private $errorLevelMap = []; + /** @var bool */ + private $handleOnlyReportedErrors = true; + /** @var bool */ + private $hasFatalErrorHandler = false; + /** @var LogLevel::* */ + private $fatalLevel = LogLevel::ALERT; + /** @var ?string */ + private $reservedMemory = null; /** @var ?array{type: int, message: string, file: string, line: int, trace: mixed} */ - private array|null $lastFatalData = null; + private $lastFatalData = null; + /** @var int[] */ + private static $fatalErrors = [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR]; - private const FATAL_ERRORS = [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR]; - - public function __construct( - private LoggerInterface $logger - ) { + public function __construct(LoggerInterface $logger) + { + $this->logger = $logger; } /** @@ -60,6 +61,7 @@ class ErrorHandler * * By default it will handle errors, exceptions and fatal errors * + * @param LoggerInterface $logger * @param array|false $errorLevelMap an array of E_* constant to LogLevel::* constant mapping, or false to disable error handling * @param array|false $exceptionLevelMap an array of class name to LogLevel::* constant mapping, or false to disable exception handling * @param LogLevel::*|null|false $fatalLevel a LogLevel::* constant, null to use the default LogLevel::ALERT or false to disable fatal error handling @@ -97,8 +99,8 @@ class ErrorHandler $this->uncaughtExceptionLevelMap[$class] = $level; } } - if ($callPrevious && null !== $prev) { - $this->previousExceptionHandler = $prev(...); + if ($callPrevious && $prev) { + $this->previousExceptionHandler = $prev; } return $this; @@ -110,10 +112,10 @@ class ErrorHandler */ public function registerErrorHandler(array $levelMap = [], bool $callPrevious = true, int $errorTypes = -1, bool $handleOnlyReportedErrors = true): self { - $prev = set_error_handler($this->handleError(...), $errorTypes); + $prev = set_error_handler([$this, 'handleError'], $errorTypes); $this->errorLevelMap = array_replace($this->defaultErrorLevelMap(), $levelMap); if ($callPrevious) { - $this->previousErrorHandler = $prev !== null ? $prev(...) : true; + $this->previousErrorHandler = $prev ?: true; } else { $this->previousErrorHandler = null; } @@ -129,7 +131,7 @@ class ErrorHandler */ public function registerFatalHandler($level = null, int $reservedMemorySize = 20): self { - register_shutdown_function($this->handleFatalError(...)); + register_shutdown_function([$this, 'handleFatalError']); $this->reservedMemory = str_repeat(' ', 1024 * $reservedMemorySize); $this->fatalLevel = null === $level ? LogLevel::ALERT : $level; @@ -173,7 +175,10 @@ class ErrorHandler ]; } - private function handleException(\Throwable $e): never + /** + * @phpstan-return never + */ + private function handleException(\Throwable $e): void { $level = LogLevel::ERROR; foreach ($this->uncaughtExceptionLevelMap as $class => $candidate) { @@ -189,25 +194,30 @@ class ErrorHandler ['exception' => $e] ); - if (null !== $this->previousExceptionHandler) { + if ($this->previousExceptionHandler) { ($this->previousExceptionHandler)($e); } - if (!headers_sent() && !(bool) ini_get('display_errors')) { + if (!headers_sent() && !ini_get('display_errors')) { http_response_code(500); } exit(255); } - private function handleError(int $code, string $message, string $file = '', int $line = 0): bool + /** + * @private + * + * @param mixed[] $context + */ + public function handleError(int $code, string $message, string $file = '', int $line = 0, ?array $context = []): bool { - if ($this->handleOnlyReportedErrors && 0 === (error_reporting() & $code)) { + if ($this->handleOnlyReportedErrors && !(error_reporting() & $code)) { return false; } // fatal error codes are ignored if a fatal error handler is present as well to avoid duplicate log entries - if (!$this->hasFatalErrorHandler || !in_array($code, self::FATAL_ERRORS, true)) { + if (!$this->hasFatalErrorHandler || !in_array($code, self::$fatalErrors, true)) { $level = $this->errorLevelMap[$code] ?? LogLevel::CRITICAL; $this->logger->log($level, self::codeToString($code).': '.$message, ['code' => $code, 'message' => $message, 'file' => $file, 'line' => $line]); } else { @@ -218,9 +228,8 @@ class ErrorHandler if ($this->previousErrorHandler === true) { return false; - } - if ($this->previousErrorHandler instanceof Closure) { - return (bool) ($this->previousErrorHandler)($code, $message, $file, $line); + } elseif ($this->previousErrorHandler) { + return (bool) ($this->previousErrorHandler)($code, $message, $file, $line, $context); } return true; @@ -238,7 +247,8 @@ class ErrorHandler } else { $lastError = error_get_last(); } - if (is_array($lastError) && in_array($lastError['type'], self::FATAL_ERRORS, true)) { + + if ($lastError && in_array($lastError['type'], self::$fatalErrors, true)) { $trace = $lastError['trace'] ?? null; $this->logger->log( $this->fatalLevel, @@ -254,25 +264,44 @@ class ErrorHandler } } - private static function codeToString(int $code): string + /** + * @param int $code + */ + private static function codeToString($code): string { - return match ($code) { - E_ERROR => 'E_ERROR', - E_WARNING => 'E_WARNING', - E_PARSE => 'E_PARSE', - E_NOTICE => 'E_NOTICE', - E_CORE_ERROR => 'E_CORE_ERROR', - E_CORE_WARNING => 'E_CORE_WARNING', - E_COMPILE_ERROR => 'E_COMPILE_ERROR', - E_COMPILE_WARNING => 'E_COMPILE_WARNING', - E_USER_ERROR => 'E_USER_ERROR', - E_USER_WARNING => 'E_USER_WARNING', - E_USER_NOTICE => 'E_USER_NOTICE', - E_STRICT => 'E_STRICT', - E_RECOVERABLE_ERROR => 'E_RECOVERABLE_ERROR', - E_DEPRECATED => 'E_DEPRECATED', - E_USER_DEPRECATED => 'E_USER_DEPRECATED', - default => 'Unknown PHP error', - }; + switch ($code) { + case E_ERROR: + return 'E_ERROR'; + case E_WARNING: + return 'E_WARNING'; + case E_PARSE: + return 'E_PARSE'; + case E_NOTICE: + return 'E_NOTICE'; + case E_CORE_ERROR: + return 'E_CORE_ERROR'; + case E_CORE_WARNING: + return 'E_CORE_WARNING'; + case E_COMPILE_ERROR: + return 'E_COMPILE_ERROR'; + case E_COMPILE_WARNING: + return 'E_COMPILE_WARNING'; + case E_USER_ERROR: + return 'E_USER_ERROR'; + case E_USER_WARNING: + return 'E_USER_WARNING'; + case E_USER_NOTICE: + return 'E_USER_NOTICE'; + case E_STRICT: + return 'E_STRICT'; + case E_RECOVERABLE_ERROR: + return 'E_RECOVERABLE_ERROR'; + case E_DEPRECATED: + return 'E_DEPRECATED'; + case E_USER_DEPRECATED: + return 'E_USER_DEPRECATED'; + } + + return 'Unknown PHP error'; } } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/ChromePHPFormatter.php b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/ChromePHPFormatter.php index 3f1d45829..aa1884b9c 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/ChromePHPFormatter.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/ChromePHPFormatter.php @@ -11,8 +11,7 @@ namespace Monolog\Formatter; -use Monolog\Level; -use Monolog\LogRecord; +use Monolog\Logger; /** * Formats a log message according to the ChromePHP array format @@ -24,55 +23,52 @@ class ChromePHPFormatter implements FormatterInterface /** * Translates Monolog log levels to Wildfire levels. * - * @return 'log'|'info'|'warn'|'error' + * @var array */ - private function toWildfireLevel(Level $level): string - { - return match ($level) { - Level::Debug => 'log', - Level::Info => 'info', - Level::Notice => 'info', - Level::Warning => 'warn', - Level::Error => 'error', - Level::Critical => 'error', - Level::Alert => 'error', - Level::Emergency => 'error', - }; - } + private $logLevels = [ + Logger::DEBUG => 'log', + Logger::INFO => 'info', + Logger::NOTICE => 'info', + Logger::WARNING => 'warn', + Logger::ERROR => 'error', + Logger::CRITICAL => 'error', + Logger::ALERT => 'error', + Logger::EMERGENCY => 'error', + ]; /** - * @inheritDoc + * {@inheritDoc} */ - public function format(LogRecord $record) + public function format(array $record) { // Retrieve the line and file if set and remove them from the formatted extra $backtrace = 'unknown'; - if (isset($record->extra['file'], $record->extra['line'])) { - $backtrace = $record->extra['file'].' : '.$record->extra['line']; - unset($record->extra['file'], $record->extra['line']); + if (isset($record['extra']['file'], $record['extra']['line'])) { + $backtrace = $record['extra']['file'].' : '.$record['extra']['line']; + unset($record['extra']['file'], $record['extra']['line']); } - $message = ['message' => $record->message]; - if (\count($record->context) > 0) { - $message['context'] = $record->context; + $message = ['message' => $record['message']]; + if ($record['context']) { + $message['context'] = $record['context']; } - if (\count($record->extra) > 0) { - $message['extra'] = $record->extra; + if ($record['extra']) { + $message['extra'] = $record['extra']; } if (count($message) === 1) { $message = reset($message); } return [ - $record->channel, + $record['channel'], $message, $backtrace, - $this->toWildfireLevel($record->level), + $this->logLevels[$record['level']], ]; } /** - * @inheritDoc + * {@inheritDoc} */ public function formatBatch(array $records) { diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/ElasticaFormatter.php b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/ElasticaFormatter.php index 160510ad8..6c8a9ab5e 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/ElasticaFormatter.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/ElasticaFormatter.php @@ -12,24 +12,25 @@ namespace Monolog\Formatter; use Elastica\Document; -use Monolog\LogRecord; /** * Format a log message into an Elastica Document * * @author Jelle Vink + * + * @phpstan-import-type Record from \Monolog\Logger */ class ElasticaFormatter extends NormalizerFormatter { /** * @var string Elastic search index name */ - protected string $index; + protected $index; /** - * @var string|null Elastic search document type + * @var ?string Elastic search document type */ - protected string|null $type; + protected $type; /** * @param string $index Elastic Search index name @@ -45,9 +46,9 @@ class ElasticaFormatter extends NormalizerFormatter } /** - * @inheritDoc + * {@inheritDoc} */ - public function format(LogRecord $record) + public function format(array $record) { $record = parent::format($record); @@ -71,13 +72,14 @@ class ElasticaFormatter extends NormalizerFormatter /** * Convert a log message into an Elastica Document * - * @param mixed[] $record + * @phpstan-param Record $record */ protected function getDocument(array $record): Document { $document = new Document(); $document->setData($record); if (method_exists($document, 'setType')) { + /** @phpstan-ignore-next-line */ $document->setType($this->type); } $document->setIndex($this->index); diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/ElasticsearchFormatter.php b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/ElasticsearchFormatter.php index 6c3eb9b2a..b792b819c 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/ElasticsearchFormatter.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/ElasticsearchFormatter.php @@ -12,7 +12,6 @@ namespace Monolog\Formatter; use DateTimeInterface; -use Monolog\LogRecord; /** * Format a log message into an Elasticsearch record @@ -24,12 +23,12 @@ class ElasticsearchFormatter extends NormalizerFormatter /** * @var string Elasticsearch index name */ - protected string $index; + protected $index; /** * @var string Elasticsearch record type */ - protected string $type; + protected $type; /** * @param string $index Elasticsearch index name @@ -45,9 +44,9 @@ class ElasticsearchFormatter extends NormalizerFormatter } /** - * @inheritDoc + * {@inheritDoc} */ - public function format(LogRecord $record) + public function format(array $record) { $record = parent::format($record); @@ -56,6 +55,8 @@ class ElasticsearchFormatter extends NormalizerFormatter /** * Getter index + * + * @return string */ public function getIndex(): string { @@ -64,6 +65,8 @@ class ElasticsearchFormatter extends NormalizerFormatter /** * Getter type + * + * @return string */ public function getType(): string { diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.php b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.php index b8f7be522..867ae586b 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.php @@ -11,18 +11,23 @@ namespace Monolog\Formatter; -use Monolog\LogRecord; - /** * formats the record to be used in the FlowdockHandler * * @author Dominik Liebler + * @deprecated Since 2.9.0 and 3.3.0, Flowdock was shutdown we will thus drop this handler in Monolog 4 */ class FlowdockFormatter implements FormatterInterface { - private string $source; + /** + * @var string + */ + private $source; - private string $sourceEmail; + /** + * @var string + */ + private $sourceEmail; public function __construct(string $source, string $sourceEmail) { @@ -31,41 +36,43 @@ class FlowdockFormatter implements FormatterInterface } /** - * @inheritDoc + * {@inheritDoc} * * @return mixed[] */ - public function format(LogRecord $record): array + public function format(array $record): array { $tags = [ '#logs', - '#' . $record->level->toPsrLogLevel(), - '#' . $record->channel, + '#' . strtolower($record['level_name']), + '#' . $record['channel'], ]; - foreach ($record->extra as $value) { + foreach ($record['extra'] as $value) { $tags[] = '#' . $value; } $subject = sprintf( 'in %s: %s - %s', $this->source, - $record->level->getName(), - $this->getShortMessage($record->message) + $record['level_name'], + $this->getShortMessage($record['message']) ); - return [ + $record['flowdock'] = [ 'source' => $this->source, 'from_address' => $this->sourceEmail, 'subject' => $subject, - 'content' => $record->message, + 'content' => $record['message'], 'tags' => $tags, 'project' => $this->source, ]; + + return $record; } /** - * @inheritDoc + * {@inheritDoc} * * @return mixed[][] */ diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/FluentdFormatter.php b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/FluentdFormatter.php index 9bd2c1604..29b14d30d 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/FluentdFormatter.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/FluentdFormatter.php @@ -12,7 +12,6 @@ namespace Monolog\Formatter; use Monolog\Utils; -use Monolog\LogRecord; /** * Class FluentdFormatter @@ -40,7 +39,7 @@ class FluentdFormatter implements FormatterInterface /** * @var bool $levelTag should message level be a part of the fluentd tag */ - protected bool $levelTag = false; + protected $levelTag = false; public function __construct(bool $levelTag = false) { @@ -56,25 +55,25 @@ class FluentdFormatter implements FormatterInterface return $this->levelTag; } - public function format(LogRecord $record): string + public function format(array $record): string { - $tag = $record->channel; + $tag = $record['channel']; if ($this->levelTag) { - $tag .= '.' . $record->level->toPsrLogLevel(); + $tag .= '.' . strtolower($record['level_name']); } $message = [ - 'message' => $record->message, - 'context' => $record->context, - 'extra' => $record->extra, + 'message' => $record['message'], + 'context' => $record['context'], + 'extra' => $record['extra'], ]; if (!$this->levelTag) { - $message['level'] = $record->level->value; - $message['level_name'] = $record->level->getName(); + $message['level'] = $record['level']; + $message['level_name'] = $record['level_name']; } - return Utils::jsonEncode([$tag, $record->datetime->getTimestamp(), $message]); + return Utils::jsonEncode([$tag, $record['datetime']->getTimestamp(), $message]); } public function formatBatch(array $records): string diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/FormatterInterface.php b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/FormatterInterface.php index 3413a4b05..19617ec5f 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/FormatterInterface.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/FormatterInterface.php @@ -11,28 +11,32 @@ namespace Monolog\Formatter; -use Monolog\LogRecord; - /** * Interface for formatters * * @author Jordi Boggiano + * + * @phpstan-import-type Record from \Monolog\Logger */ interface FormatterInterface { /** * Formats a log record. * - * @param LogRecord $record A record to format - * @return mixed The formatted record + * @param array $record A record to format + * @return mixed The formatted record + * + * @phpstan-param Record $record */ - public function format(LogRecord $record); + public function format(array $record); /** * Formats a set of log records. * - * @param array $records A set of records to format - * @return mixed The formatted set of records + * @param array $records A set of records to format + * @return mixed The formatted set of records + * + * @phpstan-param Record[] $records */ public function formatBatch(array $records); } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php index 33116a261..3b3e1e7f6 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php @@ -11,16 +11,17 @@ namespace Monolog\Formatter; -use Monolog\Level; +use Monolog\Logger; use Gelf\Message; use Monolog\Utils; -use Monolog\LogRecord; /** * Serializes a log message to GELF * @see http://docs.graylog.org/en/latest/pages/gelf.html * * @author Matt Lehner + * + * @phpstan-import-type Level from \Monolog\Logger */ class GelfMessageFormatter extends NormalizerFormatter { @@ -29,39 +30,45 @@ class GelfMessageFormatter extends NormalizerFormatter /** * @var string the name of the system for the Gelf log message */ - protected string $systemName; + protected $systemName; /** * @var string a prefix for 'extra' fields from the Monolog record (optional) */ - protected string $extraPrefix; + protected $extraPrefix; /** * @var string a prefix for 'context' fields from the Monolog record (optional) */ - protected string $contextPrefix; + protected $contextPrefix; /** * @var int max length per field */ - protected int $maxLength; + protected $maxLength; + + /** + * @var int + */ + private $gelfVersion = 2; /** * Translates Monolog log levels to Graylog2 log priorities. + * + * @var array + * + * @phpstan-var array */ - private function getGraylog2Priority(Level $level): int - { - return match ($level) { - Level::Debug => 7, - Level::Info => 6, - Level::Notice => 5, - Level::Warning => 4, - Level::Error => 3, - Level::Critical => 2, - Level::Alert => 1, - Level::Emergency => 0, - }; - } + private $logLevels = [ + Logger::DEBUG => 7, + Logger::INFO => 6, + Logger::NOTICE => 5, + Logger::WARNING => 4, + Logger::ERROR => 3, + Logger::CRITICAL => 2, + Logger::ALERT => 1, + Logger::EMERGENCY => 0, + ]; public function __construct(?string $systemName = null, ?string $extraPrefix = null, string $contextPrefix = 'ctxt_', ?int $maxLength = null) { @@ -71,52 +78,64 @@ class GelfMessageFormatter extends NormalizerFormatter parent::__construct('U.u'); - $this->systemName = (null === $systemName || $systemName === '') ? (string) gethostname() : $systemName; + $this->systemName = (is_null($systemName) || $systemName === '') ? (string) gethostname() : $systemName; - $this->extraPrefix = null === $extraPrefix ? '' : $extraPrefix; + $this->extraPrefix = is_null($extraPrefix) ? '' : $extraPrefix; $this->contextPrefix = $contextPrefix; - $this->maxLength = null === $maxLength ? self::DEFAULT_MAX_LENGTH : $maxLength; + $this->maxLength = is_null($maxLength) ? self::DEFAULT_MAX_LENGTH : $maxLength; + + if (method_exists(Message::class, 'setFacility')) { + $this->gelfVersion = 1; + } } /** - * @inheritDoc + * {@inheritDoc} */ - public function format(LogRecord $record): Message + public function format(array $record): Message { $context = $extra = []; - if (isset($record->context)) { + if (isset($record['context'])) { /** @var mixed[] $context */ - $context = parent::normalize($record->context); + $context = parent::normalize($record['context']); } - if (isset($record->extra)) { + if (isset($record['extra'])) { /** @var mixed[] $extra */ - $extra = parent::normalize($record->extra); + $extra = parent::normalize($record['extra']); + } + + if (!isset($record['datetime'], $record['message'], $record['level'])) { + throw new \InvalidArgumentException('The record should at least contain datetime, message and level keys, '.var_export($record, true).' given'); } $message = new Message(); $message - ->setTimestamp($record->datetime) - ->setShortMessage($record->message) + ->setTimestamp($record['datetime']) + ->setShortMessage((string) $record['message']) ->setHost($this->systemName) - ->setLevel($this->getGraylog2Priority($record->level)); + ->setLevel($this->logLevels[$record['level']]); // message length + system name length + 200 for padding / metadata - $len = 200 + strlen($record->message) + strlen($this->systemName); + $len = 200 + strlen((string) $record['message']) + strlen($this->systemName); if ($len > $this->maxLength) { - $message->setShortMessage(Utils::substr($record->message, 0, $this->maxLength)); + $message->setShortMessage(Utils::substr($record['message'], 0, $this->maxLength)); } - if (isset($record->channel)) { - $message->setAdditional('facility', $record->channel); - } - if (isset($extra['line'])) { - $message->setAdditional('line', $extra['line']); - unset($extra['line']); - } - if (isset($extra['file'])) { - $message->setAdditional('file', $extra['file']); - unset($extra['file']); + if ($this->gelfVersion === 1) { + if (isset($record['channel'])) { + $message->setFacility($record['channel']); + } + if (isset($extra['line'])) { + $message->setLine($extra['line']); + unset($extra['line']); + } + if (isset($extra['file'])) { + $message->setFile($extra['file']); + unset($extra['file']); + } + } else { + $message->setAdditional('facility', $record['channel']); } foreach ($extra as $key => $val) { @@ -141,10 +160,13 @@ class GelfMessageFormatter extends NormalizerFormatter $message->setAdditional($this->contextPrefix . $key, $val); } - if (!$message->hasAdditional('file') && isset($context['exception']['file'])) { - if (1 === preg_match("/^(.+):([0-9]+)$/", $context['exception']['file'], $matches)) { - $message->setAdditional('file', $matches[1]); - $message->setAdditional('line', $matches[2]); + if ($this->gelfVersion === 1) { + /** @phpstan-ignore-next-line */ + if (null === $message->getFile() && isset($context['exception']['file'])) { + if (preg_match("/^(.+):([0-9]+)$/", $context['exception']['file'], $matches)) { + $message->setFile($matches[1]); + $message->setLine($matches[2]); + } } } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/GoogleCloudLoggingFormatter.php b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/GoogleCloudLoggingFormatter.php index d37d1e0cc..ca52ebf4e 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/GoogleCloudLoggingFormatter.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/GoogleCloudLoggingFormatter.php @@ -17,23 +17,24 @@ use Monolog\LogRecord; /** * Encodes message information into JSON in a format compatible with Cloud logging. * + * @see https://cloud.google.com/logging/docs/structured-logging * @see https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry * * @author Luís Cobucci */ final class GoogleCloudLoggingFormatter extends JsonFormatter { - protected function normalizeRecord(LogRecord $record): array + /** {@inheritdoc} **/ + public function format(array $record): string { - $normalized = parent::normalizeRecord($record); - // Re-key level for GCP logging - $normalized['severity'] = $normalized['level_name']; - $normalized['timestamp'] = $record->datetime->format(DateTimeInterface::RFC3339_EXTENDED); + $record['severity'] = $record['level_name']; + $record['time'] = $record['datetime']->format(DateTimeInterface::RFC3339_EXTENDED); // Remove keys that are not used by GCP - unset($normalized['level'], $normalized['level_name'], $normalized['datetime']); + unset($record['level'], $record['level_name'], $record['datetime']); - return $normalized; + return parent::format($record); } } + diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php index bf1c61da3..10a4311cb 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php @@ -11,9 +11,8 @@ namespace Monolog\Formatter; -use Monolog\Level; +use Monolog\Logger; use Monolog\Utils; -use Monolog\LogRecord; /** * Formats incoming records into an HTML table @@ -26,20 +25,19 @@ class HtmlFormatter extends NormalizerFormatter { /** * Translates Monolog log levels to html color priorities. + * + * @var array */ - protected function getLevelColor(Level $level): string - { - return match ($level) { - Level::Debug => '#CCCCCC', - Level::Info => '#28A745', - Level::Notice => '#17A2B8', - Level::Warning => '#FFC107', - Level::Error => '#FD7E14', - Level::Critical => '#DC3545', - Level::Alert => '#821722', - Level::Emergency => '#000000', - }; - } + protected $logLevels = [ + Logger::DEBUG => '#CCCCCC', + Logger::INFO => '#28A745', + Logger::NOTICE => '#17A2B8', + Logger::WARNING => '#FFC107', + Logger::ERROR => '#FD7E14', + Logger::CRITICAL => '#DC3545', + Logger::ALERT => '#821722', + Logger::EMERGENCY => '#000000', + ]; /** * @param string|null $dateFormat The format of the timestamp: one supported by DateTime::format @@ -69,13 +67,15 @@ class HtmlFormatter extends NormalizerFormatter /** * Create a HTML h1 tag * - * @param string $title Text to be in the h1 + * @param string $title Text to be in the h1 + * @param int $level Error level + * @return string */ - protected function addTitle(string $title, Level $level): string + protected function addTitle(string $title, int $level): string { $title = htmlspecialchars($title, ENT_NOQUOTES, 'UTF-8'); - return '

'.$title.'

'; + return '

'.$title.'

'; } /** @@ -83,25 +83,25 @@ class HtmlFormatter extends NormalizerFormatter * * @return string The formatted record */ - public function format(LogRecord $record): string + public function format(array $record): string { - $output = $this->addTitle($record->level->getName(), $record->level); + $output = $this->addTitle($record['level_name'], $record['level']); $output .= ''; - $output .= $this->addRow('Message', $record->message); - $output .= $this->addRow('Time', $this->formatDate($record->datetime)); - $output .= $this->addRow('Channel', $record->channel); - if (\count($record->context) > 0) { + $output .= $this->addRow('Message', (string) $record['message']); + $output .= $this->addRow('Time', $this->formatDate($record['datetime'])); + $output .= $this->addRow('Channel', $record['channel']); + if ($record['context']) { $embeddedTable = '
'; - foreach ($record->context as $key => $value) { + foreach ($record['context'] as $key => $value) { $embeddedTable .= $this->addRow((string) $key, $this->convertToString($value)); } $embeddedTable .= '
'; $output .= $this->addRow('Context', $embeddedTable, false); } - if (\count($record->extra) > 0) { + if ($record['extra']) { $embeddedTable = ''; - foreach ($record->extra as $key => $value) { + foreach ($record['extra'] as $key => $value) { $embeddedTable .= $this->addRow((string) $key, $this->convertToString($value)); } $embeddedTable .= '
'; diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php index b2fc5bcbc..b737d82e3 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php @@ -11,9 +11,7 @@ namespace Monolog\Formatter; -use Stringable; use Throwable; -use Monolog\LogRecord; /** * Encodes whatever record data is passed to it as json @@ -21,6 +19,8 @@ use Monolog\LogRecord; * This can be useful to log to databases or remote APIs * * @author Jordi Boggiano + * + * @phpstan-import-type Record from \Monolog\Logger */ class JsonFormatter extends NormalizerFormatter { @@ -28,13 +28,13 @@ class JsonFormatter extends NormalizerFormatter public const BATCH_MODE_NEWLINES = 2; /** @var self::BATCH_MODE_* */ - protected int $batchMode; - - protected bool $appendNewline; - - protected bool $ignoreEmptyContextAndExtra; - - protected bool $includeStacktraces = false; + protected $batchMode; + /** @var bool */ + protected $appendNewline; + /** @var bool */ + protected $ignoreEmptyContextAndExtra; + /** @var bool */ + protected $includeStacktraces = false; /** * @param self::BATCH_MODE_* $batchMode @@ -70,11 +70,11 @@ class JsonFormatter extends NormalizerFormatter } /** - * @inheritDoc + * {@inheritDoc} */ - public function format(LogRecord $record): string + public function format(array $record): string { - $normalized = parent::format($record); + $normalized = $this->normalize($record); if (isset($normalized['context']) && $normalized['context'] === []) { if ($this->ignoreEmptyContextAndExtra) { @@ -95,16 +95,23 @@ class JsonFormatter extends NormalizerFormatter } /** - * @inheritDoc + * {@inheritDoc} */ public function formatBatch(array $records): string { - return match ($this->batchMode) { - static::BATCH_MODE_NEWLINES => $this->formatBatchNewlines($records), - default => $this->formatBatchJson($records), - }; + switch ($this->batchMode) { + case static::BATCH_MODE_NEWLINES: + return $this->formatBatchNewlines($records); + + case static::BATCH_MODE_JSON: + default: + return $this->formatBatchJson($records); + } } + /** + * @return self + */ public function includeStacktraces(bool $include = true): self { $this->includeStacktraces = $include; @@ -115,7 +122,7 @@ class JsonFormatter extends NormalizerFormatter /** * Return a JSON-encoded array of records. * - * @phpstan-param LogRecord[] $records + * @phpstan-param Record[] $records */ protected function formatBatchJson(array $records): string { @@ -126,24 +133,30 @@ class JsonFormatter extends NormalizerFormatter * Use new lines to separate records instead of a * JSON-encoded array. * - * @phpstan-param LogRecord[] $records + * @phpstan-param Record[] $records */ protected function formatBatchNewlines(array $records): string { + $instance = $this; + $oldNewline = $this->appendNewline; $this->appendNewline = false; - $formatted = array_map(fn (LogRecord $record) => $this->format($record), $records); + array_walk($records, function (&$value, $key) use ($instance) { + $value = $instance->format($value); + }); $this->appendNewline = $oldNewline; - return implode("\n", $formatted); + return implode("\n", $records); } /** * Normalizes given $data. * - * @return null|scalar|array|object + * @param mixed $data + * + * @return mixed */ - protected function normalize(mixed $data, int $depth = 0): mixed + protected function normalize($data, int $depth = 0) { if ($depth > $this->maxNormalizeDepth) { return 'Over '.$this->maxNormalizeDepth.' levels deep, aborting normalization'; @@ -179,7 +192,7 @@ class JsonFormatter extends NormalizerFormatter return $data; } - if ($data instanceof Stringable) { + if (method_exists($data, '__toString')) { return $data->__toString(); } @@ -197,7 +210,7 @@ class JsonFormatter extends NormalizerFormatter * Normalizes given exception with or without its own stack trace based on * `includeStacktraces` property. * - * @inheritDoc + * {@inheritDoc} */ protected function normalizeException(Throwable $e, int $depth = 0): array { diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php index 19fb72c53..b31b2971a 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php @@ -11,9 +11,7 @@ namespace Monolog\Formatter; -use Closure; use Monolog\Utils; -use Monolog\LogRecord; /** * Formats incoming records into a one-line string @@ -27,16 +25,22 @@ class LineFormatter extends NormalizerFormatter { public const SIMPLE_FORMAT = "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n"; - protected string $format; - protected bool $allowInlineLineBreaks; - protected bool $ignoreEmptyContextAndExtra; - protected bool $includeStacktraces; - protected Closure|null $stacktracesParser = null; + /** @var string */ + protected $format; + /** @var bool */ + protected $allowInlineLineBreaks; + /** @var bool */ + protected $ignoreEmptyContextAndExtra; + /** @var bool */ + protected $includeStacktraces; + /** @var ?callable */ + protected $stacktracesParser; /** - * @param string|null $format The format of the message - * @param string|null $dateFormat The format of the timestamp: one supported by DateTime::format - * @param bool $allowInlineLineBreaks Whether to allow inline line breaks in log entries + * @param string|null $format The format of the message + * @param string|null $dateFormat The format of the timestamp: one supported by DateTime::format + * @param bool $allowInlineLineBreaks Whether to allow inline line breaks in log entries + * @param bool $ignoreEmptyContextAndExtra */ public function __construct(?string $format = null, ?string $dateFormat = null, bool $allowInlineLineBreaks = false, bool $ignoreEmptyContextAndExtra = false, bool $includeStacktraces = false) { @@ -47,7 +51,7 @@ class LineFormatter extends NormalizerFormatter parent::__construct($dateFormat); } - public function includeStacktraces(bool $include = true, ?Closure $parser = null): self + public function includeStacktraces(bool $include = true, ?callable $parser = null): self { $this->includeStacktraces = $include; if ($this->includeStacktraces) { @@ -73,13 +77,14 @@ class LineFormatter extends NormalizerFormatter } /** - * @inheritDoc + * {@inheritDoc} */ - public function format(LogRecord $record): string + public function format(array $record): string { $vars = parent::format($record); $output = $this->format; + foreach ($vars['extra'] as $var => $val) { if (false !== strpos($output, '%extra.'.$var.'%')) { $output = str_replace('%extra.'.$var.'%', $this->stringify($val), $output); @@ -95,12 +100,12 @@ class LineFormatter extends NormalizerFormatter } if ($this->ignoreEmptyContextAndExtra) { - if (\count($vars['context']) === 0) { + if (empty($vars['context'])) { unset($vars['context']); $output = str_replace('%context%', '', $output); } - if (\count($vars['extra']) === 0) { + if (empty($vars['extra'])) { unset($vars['extra']); $output = str_replace('%extra%', '', $output); } @@ -117,7 +122,6 @@ class LineFormatter extends NormalizerFormatter $output = preg_replace('/%(?:extra|context)\..+?%/', '', $output); if (null === $output) { $pcreErrorCode = preg_last_error(); - throw new \RuntimeException('Failed to run preg_replace: ' . $pcreErrorCode . ' / ' . Utils::pcreLastErrorMessage($pcreErrorCode)); } } @@ -147,7 +151,7 @@ class LineFormatter extends NormalizerFormatter { $str = $this->formatException($e); - if (($previous = $e->getPrevious()) instanceof \Throwable) { + if ($previous = $e->getPrevious()) { do { $depth++; if ($depth > $this->maxNormalizeDepth) { @@ -228,7 +232,7 @@ class LineFormatter extends NormalizerFormatter { $trace = $e->getTraceAsString(); - if ($this->stacktracesParser !== null) { + if ($this->stacktracesParser) { $trace = $this->stacktracesParserCustom($trace); } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/LogglyFormatter.php b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/LogglyFormatter.php index 5f0b6a453..29841aa38 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/LogglyFormatter.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/LogglyFormatter.php @@ -11,8 +11,6 @@ namespace Monolog\Formatter; -use Monolog\LogRecord; - /** * Encodes message information into JSON in a format compatible with Loggly. * @@ -35,13 +33,13 @@ class LogglyFormatter extends JsonFormatter * @see https://www.loggly.com/docs/automated-parsing/#json * @see \Monolog\Formatter\JsonFormatter::format() */ - protected function normalizeRecord(LogRecord $record): array + public function format(array $record): string { - $recordData = parent::normalizeRecord($record); + if (isset($record["datetime"]) && ($record["datetime"] instanceof \DateTimeInterface)) { + $record["timestamp"] = $record["datetime"]->format("Y-m-d\TH:i:s.uO"); + unset($record["datetime"]); + } - $recordData["timestamp"] = $record->datetime->format("Y-m-d\TH:i:s.uO"); - unset($recordData["datetime"]); - - return $recordData; + return parent::format($record); } } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/LogmaticFormatter.php b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/LogmaticFormatter.php index 10ad0d9c0..b0451aba7 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/LogmaticFormatter.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/LogmaticFormatter.php @@ -11,8 +11,6 @@ namespace Monolog\Formatter; -use Monolog\LogRecord; - /** * Encodes message information into JSON in a format compatible with Logmatic. * @@ -22,9 +20,15 @@ class LogmaticFormatter extends JsonFormatter { protected const MARKERS = ["sourcecode", "php"]; - protected string $hostname = ''; + /** + * @var string + */ + protected $hostname = ''; - protected string $appName = ''; + /** + * @var string + */ + protected $appname = ''; public function setHostname(string $hostname): self { @@ -33,9 +37,9 @@ class LogmaticFormatter extends JsonFormatter return $this; } - public function setAppName(string $appName): self + public function setAppname(string $appname): self { - $this->appName = $appName; + $this->appname = $appname; return $this; } @@ -46,19 +50,17 @@ class LogmaticFormatter extends JsonFormatter * @see http://doc.logmatic.io/docs/basics-to-send-data * @see \Monolog\Formatter\JsonFormatter::format() */ - public function normalizeRecord(LogRecord $record): array + public function format(array $record): string { - $record = parent::normalizeRecord($record); - - if ($this->hostname !== '') { + if (!empty($this->hostname)) { $record["hostname"] = $this->hostname; } - if ($this->appName !== '') { - $record["appname"] = $this->appName; + if (!empty($this->appname)) { + $record["appname"] = $this->appname; } $record["@marker"] = static::MARKERS; - return $record; + return parent::format($record); } } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/LogstashFormatter.php b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/LogstashFormatter.php index d0e8749e3..f8de0d333 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/LogstashFormatter.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/LogstashFormatter.php @@ -11,8 +11,6 @@ namespace Monolog\Formatter; -use Monolog\LogRecord; - /** * Serializes a log message to Logstash Event Format * @@ -26,22 +24,22 @@ class LogstashFormatter extends NormalizerFormatter /** * @var string the name of the system for the Logstash log message, used to fill the @source field */ - protected string $systemName; + protected $systemName; /** * @var string an application name for the Logstash log message, used to fill the @type field */ - protected string $applicationName; + protected $applicationName; /** * @var string the key for 'extra' fields from the Monolog record */ - protected string $extraKey; + protected $extraKey; /** * @var string the key for 'context' fields from the Monolog record */ - protected string $contextKey; + protected $contextKey; /** * @param string $applicationName The application that sends the data, used as the "type" field of logstash @@ -61,38 +59,41 @@ class LogstashFormatter extends NormalizerFormatter } /** - * @inheritDoc + * {@inheritDoc} */ - public function format(LogRecord $record): string + public function format(array $record): string { - $recordData = parent::format($record); + $record = parent::format($record); + if (empty($record['datetime'])) { + $record['datetime'] = gmdate('c'); + } $message = [ - '@timestamp' => $recordData['datetime'], + '@timestamp' => $record['datetime'], '@version' => 1, 'host' => $this->systemName, ]; - if (isset($recordData['message'])) { - $message['message'] = $recordData['message']; + if (isset($record['message'])) { + $message['message'] = $record['message']; } - if (isset($recordData['channel'])) { - $message['type'] = $recordData['channel']; - $message['channel'] = $recordData['channel']; + if (isset($record['channel'])) { + $message['type'] = $record['channel']; + $message['channel'] = $record['channel']; } - if (isset($recordData['level_name'])) { - $message['level'] = $recordData['level_name']; + if (isset($record['level_name'])) { + $message['level'] = $record['level_name']; } - if (isset($recordData['level'])) { - $message['monolog_level'] = $recordData['level']; + if (isset($record['level'])) { + $message['monolog_level'] = $record['level']; } - if ('' !== $this->applicationName) { + if ($this->applicationName) { $message['type'] = $this->applicationName; } - if (\count($recordData['extra']) > 0) { - $message[$this->extraKey] = $recordData['extra']; + if (!empty($record['extra'])) { + $message[$this->extraKey] = $record['extra']; } - if (\count($recordData['context']) > 0) { - $message[$this->contextKey] = $recordData['context']; + if (!empty($record['context'])) { + $message[$this->contextKey] = $record['context']; } return $this->toJson($message) . "\n"; diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php index a3bdd4f87..fca69a899 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php @@ -14,7 +14,6 @@ namespace Monolog\Formatter; use MongoDB\BSON\Type; use MongoDB\BSON\UTCDateTime; use Monolog\Utils; -use Monolog\LogRecord; /** * Formats a record for use with the MongoDBHandler. @@ -23,12 +22,15 @@ use Monolog\LogRecord; */ class MongoDBFormatter implements FormatterInterface { - private bool $exceptionTraceAsString; - private int $maxNestingLevel; - private bool $isLegacyMongoExt; + /** @var bool */ + private $exceptionTraceAsString; + /** @var int */ + private $maxNestingLevel; + /** @var bool */ + private $isLegacyMongoExt; /** - * @param int $maxNestingLevel 0 means infinite nesting, the $record itself is level 1, $record->context is 2 + * @param int $maxNestingLevel 0 means infinite nesting, the $record itself is level 1, $record['context'] is 2 * @param bool $exceptionTraceAsString set to false to log exception traces as a sub documents instead of strings */ public function __construct(int $maxNestingLevel = 3, bool $exceptionTraceAsString = true) @@ -40,20 +42,20 @@ class MongoDBFormatter implements FormatterInterface } /** - * @inheritDoc + * {@inheritDoc} * * @return mixed[] */ - public function format(LogRecord $record): array + public function format(array $record): array { /** @var mixed[] $res */ - $res = $this->formatArray($record->toArray()); + $res = $this->formatArray($record); return $res; } /** - * @inheritDoc + * {@inheritDoc} * * @return array */ diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php index 1323587b5..5441bc0aa 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php @@ -14,7 +14,6 @@ namespace Monolog\Formatter; use Monolog\DateTimeImmutable; use Monolog\Utils; use Throwable; -use Monolog\LogRecord; /** * Normalizes incoming records to remove objects/resources so it's easier to dump to various targets @@ -25,11 +24,15 @@ class NormalizerFormatter implements FormatterInterface { public const SIMPLE_DATE = "Y-m-d\TH:i:sP"; - protected string $dateFormat; - protected int $maxNormalizeDepth = 9; - protected int $maxNormalizeItemCount = 1000; + /** @var string */ + protected $dateFormat; + /** @var int */ + protected $maxNormalizeDepth = 9; + /** @var int */ + protected $maxNormalizeItemCount = 1000; - private int $jsonEncodeOptions = Utils::DEFAULT_JSON_FLAGS; + /** @var int */ + private $jsonEncodeOptions = Utils::DEFAULT_JSON_FLAGS; /** * @param string|null $dateFormat The format of the timestamp: one supported by DateTime::format @@ -43,25 +46,17 @@ class NormalizerFormatter implements FormatterInterface } /** - * @inheritDoc - */ - public function format(LogRecord $record) - { - return $this->normalizeRecord($record); - } - - /** - * Normalize an arbitrary value to a scalar|array|null + * {@inheritDoc} * - * @return null|scalar|array + * @param mixed[] $record */ - public function normalizeValue(mixed $data): mixed + public function format(array $record) { - return $this->normalize($data); + return $this->normalize($record); } /** - * @inheritDoc + * {@inheritDoc} */ public function formatBatch(array $records) { @@ -129,25 +124,10 @@ class NormalizerFormatter implements FormatterInterface } /** - * Provided as extension point - * - * Because normalize is called with sub-values of context data etc, normalizeRecord can be - * extended when data needs to be appended on the record array but not to other normalized data. - * - * @return array + * @param mixed $data + * @return null|scalar|array */ - protected function normalizeRecord(LogRecord $record): array - { - /** @var array $normalized */ - $normalized = $this->normalize($record->toArray()); - - return $normalized; - } - - /** - * @return null|scalar|array - */ - protected function normalize(mixed $data, int $depth = 0): mixed + protected function normalize($data, int $depth = 0) { if ($depth > $this->maxNormalizeDepth) { return 'Over ' . $this->maxNormalizeDepth . ' levels deep, aborting normalization'; @@ -192,14 +172,14 @@ class NormalizerFormatter implements FormatterInterface } if ($data instanceof \JsonSerializable) { - /** @var null|scalar|array $value */ + /** @var null|scalar|array $value */ $value = $data->jsonSerialize(); } elseif (method_exists($data, '__toString')) { /** @var string $value */ $value = $data->__toString(); } else { // the rest is normalized by json encoding and decoding it - /** @var null|scalar|array $value */ + /** @var null|scalar|array $value */ $value = json_decode($this->toJson($data, true), true); } @@ -253,12 +233,12 @@ class NormalizerFormatter implements FormatterInterface $trace = $e->getTrace(); foreach ($trace as $frame) { - if (isset($frame['file'], $frame['line'])) { + if (isset($frame['file'])) { $data['trace'][] = $frame['file'].':'.$frame['line']; } } - if (($previous = $e->getPrevious()) instanceof \Throwable) { + if ($previous = $e->getPrevious()) { $data['previous'] = $this->normalizeException($previous, $depth + 1); } @@ -277,7 +257,10 @@ class NormalizerFormatter implements FormatterInterface return Utils::jsonEncode($data, $this->jsonEncodeOptions, $ignoreErrors); } - protected function formatDate(\DateTimeInterface $date): string + /** + * @return string + */ + protected function formatDate(\DateTimeInterface $date) { // in case the date format isn't custom then we defer to the custom DateTimeImmutable // formatting logic, which will pick the right format based on whether useMicroseconds is on diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/ScalarFormatter.php b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/ScalarFormatter.php index 4bc20a08c..187bc550d 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/ScalarFormatter.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/ScalarFormatter.php @@ -11,10 +11,8 @@ namespace Monolog\Formatter; -use Monolog\LogRecord; - /** - * Formats data into an associative array of scalar (+ null) values. + * Formats data into an associative array of scalar values. * Objects and arrays will be JSON encoded. * * @author Andrew Lawson @@ -22,21 +20,25 @@ use Monolog\LogRecord; class ScalarFormatter extends NormalizerFormatter { /** - * @inheritDoc + * {@inheritDoc} * * @phpstan-return array $record */ - public function format(LogRecord $record): array + public function format(array $record): array { $result = []; - foreach ($record->toArray() as $key => $value) { - $result[$key] = $this->toScalar($value); + foreach ($record as $key => $value) { + $result[$key] = $this->normalizeValue($value); } return $result; } - protected function toScalar(mixed $value): string|int|float|bool|null + /** + * @param mixed $value + * @return scalar|null + */ + protected function normalizeValue($value) { $normalized = $this->normalize($value); diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/SyslogFormatter.php b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/SyslogFormatter.php deleted file mode 100644 index 6ed7e92ef..000000000 --- a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/SyslogFormatter.php +++ /dev/null @@ -1,66 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Monolog\Formatter; - -use Monolog\Level; -use Monolog\LogRecord; - -/** - * Serializes a log message according to RFC 5424 - * - * @author Dalibor Karlović - * @author Renat Gabdullin - */ -class SyslogFormatter extends LineFormatter -{ - private const SYSLOG_FACILITY_USER = 1; - private const FORMAT = "<%extra.priority%>1 %datetime% %extra.hostname% %extra.app-name% %extra.procid% %channel% %extra.structured-data% %level_name%: %message% %context% %extra%\n"; - private const NILVALUE = '-'; - - private string $hostname; - private int $procid; - - public function __construct(private string $applicationName = self::NILVALUE) - { - parent::__construct(self::FORMAT, 'Y-m-d\TH:i:s.uP', true, true); - $this->hostname = (string) gethostname(); - $this->procid = (int) getmypid(); - } - - public function format(LogRecord $record): string - { - $record->extra = $this->formatExtra($record); - - return parent::format($record); - } - - /** - * @param LogRecord $record - * @return array - */ - private function formatExtra(LogRecord $record): array - { - $extra = $record->extra; - $extra['app-name'] = $this->applicationName; - $extra['hostname'] = $this->hostname; - $extra['procid'] = $this->procid; - $extra['priority'] = self::calculatePriority($record->level); - $extra['structured-data'] = self::NILVALUE; - - return $extra; - } - - private static function calculatePriority(Level $level): int - { - return (self::SYSLOG_FACILITY_USER * 8) + $level->toRFC5424Level(); - } -} diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php index 8ef7b7d14..6539b3473 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php @@ -11,8 +11,7 @@ namespace Monolog\Formatter; -use Monolog\Level; -use Monolog\LogRecord; +use Monolog\Logger; /** * Serializes a log message according to Wildfire's header requirements @@ -20,9 +19,27 @@ use Monolog\LogRecord; * @author Eric Clemmons (@ericclemmons) * @author Christophe Coevoet * @author Kirill chEbba Chebunin + * + * @phpstan-import-type Level from \Monolog\Logger */ class WildfireFormatter extends NormalizerFormatter { + /** + * Translates Monolog log levels to Wildfire levels. + * + * @var array + */ + private $logLevels = [ + Logger::DEBUG => 'LOG', + Logger::INFO => 'INFO', + Logger::NOTICE => 'INFO', + Logger::WARNING => 'WARN', + Logger::ERROR => 'ERROR', + Logger::CRITICAL => 'ERROR', + Logger::ALERT => 'ERROR', + Logger::EMERGENCY => 'ERROR', + ]; + /** * @param string|null $dateFormat The format of the timestamp: one supported by DateTime::format */ @@ -35,61 +52,46 @@ class WildfireFormatter extends NormalizerFormatter } /** - * Translates Monolog log levels to Wildfire levels. + * {@inheritDoc} * - * @return 'LOG'|'INFO'|'WARN'|'ERROR' + * @return string */ - private function toWildfireLevel(Level $level): string - { - return match ($level) { - Level::Debug => 'LOG', - Level::Info => 'INFO', - Level::Notice => 'INFO', - Level::Warning => 'WARN', - Level::Error => 'ERROR', - Level::Critical => 'ERROR', - Level::Alert => 'ERROR', - Level::Emergency => 'ERROR', - }; - } - - /** - * @inheritDoc - */ - public function format(LogRecord $record): string + public function format(array $record): string { // Retrieve the line and file if set and remove them from the formatted extra $file = $line = ''; - if (isset($record->extra['file'])) { - $file = $record->extra['file']; - unset($record->extra['file']); + if (isset($record['extra']['file'])) { + $file = $record['extra']['file']; + unset($record['extra']['file']); } - if (isset($record->extra['line'])) { - $line = $record->extra['line']; - unset($record->extra['line']); + if (isset($record['extra']['line'])) { + $line = $record['extra']['line']; + unset($record['extra']['line']); } - $message = ['message' => $record->message]; + /** @var mixed[] $record */ + $record = $this->normalize($record); + $message = ['message' => $record['message']]; $handleError = false; - if (count($record->context) > 0) { - $message['context'] = $this->normalize($record->context); + if ($record['context']) { + $message['context'] = $record['context']; $handleError = true; } - if (count($record->extra) > 0) { - $message['extra'] = $this->normalize($record->extra); + if ($record['extra']) { + $message['extra'] = $record['extra']; $handleError = true; } if (count($message) === 1) { $message = reset($message); } - if (is_array($message) && isset($message['context']['table'])) { + if (isset($record['context']['table'])) { $type = 'TABLE'; - $label = $record->channel .': '. $record->message; - $message = $message['context']['table']; + $label = $record['channel'] .': '. $record['message']; + $message = $record['context']['table']; } else { - $type = $this->toWildfireLevel($record->level); - $label = $record->channel; + $type = $this->logLevels[$record['level']]; + $label = $record['channel']; } // Create JSON object describing the appearance of the message in the console @@ -112,7 +114,7 @@ class WildfireFormatter extends NormalizerFormatter } /** - * @inheritDoc + * {@inheritDoc} * * @phpstan-return never */ @@ -122,11 +124,11 @@ class WildfireFormatter extends NormalizerFormatter } /** - * @inheritDoc + * {@inheritDoc} * - * @return null|scalar|array|object + * @return null|scalar|array|object */ - protected function normalize(mixed $data, int $depth = 0): mixed + protected function normalize($data, int $depth = 0) { if (is_object($data) && !$data instanceof \DateTimeInterface) { return $data; diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/AbstractHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/AbstractHandler.php index 3399a54e2..a5cdaa71f 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/AbstractHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/AbstractHandler.php @@ -11,50 +11,55 @@ namespace Monolog\Handler; -use Monolog\Level; use Monolog\Logger; use Monolog\ResettableInterface; use Psr\Log\LogLevel; -use Monolog\LogRecord; /** * Base Handler class providing basic level/bubble support * * @author Jordi Boggiano + * + * @phpstan-import-type Level from \Monolog\Logger + * @phpstan-import-type LevelName from \Monolog\Logger */ abstract class AbstractHandler extends Handler implements ResettableInterface { - protected Level $level = Level::Debug; - protected bool $bubble = true; + /** + * @var int + * @phpstan-var Level + */ + protected $level = Logger::DEBUG; + /** @var bool */ + protected $bubble = true; /** - * @param int|string|Level|LogLevel::* $level The minimum logging level at which this handler will be triggered - * @param bool $bubble Whether the messages that are handled can bubble up the stack or not + * @param int|string $level The minimum logging level at which this handler will be triggered + * @param bool $bubble Whether the messages that are handled can bubble up the stack or not * - * @phpstan-param value-of|value-of|Level|LogLevel::* $level + * @phpstan-param Level|LevelName|LogLevel::* $level */ - public function __construct(int|string|Level $level = Level::Debug, bool $bubble = true) + public function __construct($level = Logger::DEBUG, bool $bubble = true) { $this->setLevel($level); $this->bubble = $bubble; } /** - * @inheritDoc + * {@inheritDoc} */ - public function isHandling(LogRecord $record): bool + public function isHandling(array $record): bool { - return $record->level->value >= $this->level->value; + return $record['level'] >= $this->level; } /** * Sets minimum logging level at which this handler will be triggered. * - * @param Level|LogLevel::* $level Level or level name - * - * @phpstan-param value-of|value-of|Level|LogLevel::* $level + * @param Level|LevelName|LogLevel::* $level Level or level name + * @return self */ - public function setLevel(int|string|Level $level): self + public function setLevel($level): self { $this->level = Logger::toMonologLevel($level); @@ -63,8 +68,12 @@ abstract class AbstractHandler extends Handler implements ResettableInterface /** * Gets minimum logging level at which this handler will be triggered. + * + * @return int + * + * @phpstan-return Level */ - public function getLevel(): Level + public function getLevel(): int { return $this->level; } @@ -72,8 +81,9 @@ abstract class AbstractHandler extends Handler implements ResettableInterface /** * Sets the bubbling behavior. * - * @param bool $bubble true means that this handler allows bubbling. - * false means that bubbling is not permitted. + * @param bool $bubble true means that this handler allows bubbling. + * false means that bubbling is not permitted. + * @return self */ public function setBubble(bool $bubble): self { @@ -94,9 +104,9 @@ abstract class AbstractHandler extends Handler implements ResettableInterface } /** - * @inheritDoc + * {@inheritDoc} */ - public function reset(): void + public function reset() { } } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php index de13a76be..77e533fca 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php @@ -11,8 +11,6 @@ namespace Monolog\Handler; -use Monolog\LogRecord; - /** * Base Handler class providing the Handler structure, including processors and formatters * @@ -20,6 +18,11 @@ use Monolog\LogRecord; * * @author Jordi Boggiano * @author Christophe Coevoet + * + * @phpstan-import-type LevelName from \Monolog\Logger + * @phpstan-import-type Level from \Monolog\Logger + * @phpstan-import-type Record from \Monolog\Logger + * @phpstan-type FormattedRecord array{message: string, context: mixed[], level: Level, level_name: LevelName, channel: string, datetime: \DateTimeImmutable, extra: mixed[], formatted: mixed} */ abstract class AbstractProcessingHandler extends AbstractHandler implements ProcessableHandlerInterface, FormattableHandlerInterface { @@ -27,19 +30,20 @@ abstract class AbstractProcessingHandler extends AbstractHandler implements Proc use FormattableHandlerTrait; /** - * @inheritDoc + * {@inheritDoc} */ - public function handle(LogRecord $record): bool + public function handle(array $record): bool { if (!$this->isHandling($record)) { return false; } - if (\count($this->processors) > 0) { + if ($this->processors) { + /** @var Record $record */ $record = $this->processRecord($record); } - $record->formatted = $this->getFormatter()->format($record); + $record['formatted'] = $this->getFormatter()->format($record); $this->write($record); @@ -47,11 +51,16 @@ abstract class AbstractProcessingHandler extends AbstractHandler implements Proc } /** - * Writes the (already formatted) record down to the log of the implementing handler + * Writes the record down to the log of the implementing handler + * + * @phpstan-param FormattedRecord $record */ - abstract protected function write(LogRecord $record): void; + abstract protected function write(array $record): void; - public function reset(): void + /** + * @return void + */ + public function reset() { parent::reset(); diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/AbstractSyslogHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/AbstractSyslogHandler.php index 695a1c07f..5e5ad1c1f 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/AbstractSyslogHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/AbstractSyslogHandler.php @@ -11,59 +11,70 @@ namespace Monolog\Handler; -use Monolog\Level; +use Monolog\Logger; use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\LineFormatter; /** * Common syslog functionality + * + * @phpstan-import-type Level from \Monolog\Logger */ abstract class AbstractSyslogHandler extends AbstractProcessingHandler { - protected int $facility; + /** @var int */ + protected $facility; + + /** + * Translates Monolog log levels to syslog log priorities. + * @var array + * @phpstan-var array + */ + protected $logLevels = [ + Logger::DEBUG => LOG_DEBUG, + Logger::INFO => LOG_INFO, + Logger::NOTICE => LOG_NOTICE, + Logger::WARNING => LOG_WARNING, + Logger::ERROR => LOG_ERR, + Logger::CRITICAL => LOG_CRIT, + Logger::ALERT => LOG_ALERT, + Logger::EMERGENCY => LOG_EMERG, + ]; /** * List of valid log facility names. * @var array */ - protected array $facilities = [ - 'auth' => \LOG_AUTH, - 'authpriv' => \LOG_AUTHPRIV, - 'cron' => \LOG_CRON, - 'daemon' => \LOG_DAEMON, - 'kern' => \LOG_KERN, - 'lpr' => \LOG_LPR, - 'mail' => \LOG_MAIL, - 'news' => \LOG_NEWS, - 'syslog' => \LOG_SYSLOG, - 'user' => \LOG_USER, - 'uucp' => \LOG_UUCP, + protected $facilities = [ + 'auth' => LOG_AUTH, + 'authpriv' => LOG_AUTHPRIV, + 'cron' => LOG_CRON, + 'daemon' => LOG_DAEMON, + 'kern' => LOG_KERN, + 'lpr' => LOG_LPR, + 'mail' => LOG_MAIL, + 'news' => LOG_NEWS, + 'syslog' => LOG_SYSLOG, + 'user' => LOG_USER, + 'uucp' => LOG_UUCP, ]; - /** - * Translates Monolog log levels to syslog log priorities. - */ - protected function toSyslogPriority(Level $level): int - { - return $level->toRFC5424Level(); - } - /** * @param string|int $facility Either one of the names of the keys in $this->facilities, or a LOG_* facility constant */ - public function __construct(string|int $facility = \LOG_USER, int|string|Level $level = Level::Debug, bool $bubble = true) + public function __construct($facility = LOG_USER, $level = Logger::DEBUG, bool $bubble = true) { parent::__construct($level, $bubble); if (!defined('PHP_WINDOWS_VERSION_BUILD')) { - $this->facilities['local0'] = \LOG_LOCAL0; - $this->facilities['local1'] = \LOG_LOCAL1; - $this->facilities['local2'] = \LOG_LOCAL2; - $this->facilities['local3'] = \LOG_LOCAL3; - $this->facilities['local4'] = \LOG_LOCAL4; - $this->facilities['local5'] = \LOG_LOCAL5; - $this->facilities['local6'] = \LOG_LOCAL6; - $this->facilities['local7'] = \LOG_LOCAL7; + $this->facilities['local0'] = LOG_LOCAL0; + $this->facilities['local1'] = LOG_LOCAL1; + $this->facilities['local2'] = LOG_LOCAL2; + $this->facilities['local3'] = LOG_LOCAL3; + $this->facilities['local4'] = LOG_LOCAL4; + $this->facilities['local5'] = LOG_LOCAL5; + $this->facilities['local6'] = LOG_LOCAL6; + $this->facilities['local7'] = LOG_LOCAL7; } else { $this->facilities['local0'] = 128; // LOG_LOCAL0 $this->facilities['local1'] = 136; // LOG_LOCAL1 @@ -86,7 +97,7 @@ abstract class AbstractSyslogHandler extends AbstractProcessingHandler } /** - * @inheritDoc + * {@inheritDoc} */ protected function getDefaultFormatter(): FormatterInterface { diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/AmqpHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/AmqpHandler.php index b25e4f139..994872ce8 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/AmqpHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/AmqpHandler.php @@ -11,38 +11,24 @@ namespace Monolog\Handler; -use Monolog\Level; +use Monolog\Logger; use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\JsonFormatter; use PhpAmqpLib\Message\AMQPMessage; use PhpAmqpLib\Channel\AMQPChannel; use AMQPExchange; -use Monolog\LogRecord; +/** + * @phpstan-import-type Record from \Monolog\Logger + */ class AmqpHandler extends AbstractProcessingHandler { - protected AMQPExchange|AMQPChannel $exchange; - - /** @var array */ - private array $extraAttributes = []; - - protected string $exchangeName; - /** - * @param AMQPExchange|AMQPChannel $exchange AMQPExchange (php AMQP ext) or PHP AMQP lib channel, ready for use - * @param string|null $exchangeName Optional exchange name, for AMQPChannel (PhpAmqpLib) only + * @var AMQPExchange|AMQPChannel $exchange */ - public function __construct(AMQPExchange|AMQPChannel $exchange, ?string $exchangeName = null, int|string|Level $level = Level::Debug, bool $bubble = true) - { - if ($exchange instanceof AMQPChannel) { - $this->exchangeName = (string) $exchangeName; - } elseif ($exchangeName !== null) { - @trigger_error('The $exchangeName parameter can only be passed when using PhpAmqpLib, if using an AMQPExchange instance configure it beforehand', E_USER_DEPRECATED); - } - $this->exchange = $exchange; - - parent::__construct($level, $bubble); - } + protected $exchange; + /** @var array */ + private $extraAttributes = []; /** * @return array @@ -59,7 +45,7 @@ class AmqpHandler extends AbstractProcessingHandler * message_id, user_id, app_id, delivery_mode, * priority, timestamp, expiration, type * or reply_to, headers. - * @return $this + * @return AmqpHandler */ public function setExtraAttributes(array $extraAttributes): self { @@ -68,11 +54,34 @@ class AmqpHandler extends AbstractProcessingHandler } /** - * @inheritDoc + * @var string */ - protected function write(LogRecord $record): void + protected $exchangeName; + + /** + * @param AMQPExchange|AMQPChannel $exchange AMQPExchange (php AMQP ext) or PHP AMQP lib channel, ready for use + * @param string|null $exchangeName Optional exchange name, for AMQPChannel (PhpAmqpLib) only + */ + public function __construct($exchange, ?string $exchangeName = null, $level = Logger::DEBUG, bool $bubble = true) { - $data = $record->formatted; + if ($exchange instanceof AMQPChannel) { + $this->exchangeName = (string) $exchangeName; + } elseif (!$exchange instanceof AMQPExchange) { + throw new \InvalidArgumentException('PhpAmqpLib\Channel\AMQPChannel or AMQPExchange instance required'); + } elseif ($exchangeName) { + @trigger_error('The $exchangeName parameter can only be passed when using PhpAmqpLib, if using an AMQPExchange instance configure it beforehand', E_USER_DEPRECATED); + } + $this->exchange = $exchange; + + parent::__construct($level, $bubble); + } + + /** + * {@inheritDoc} + */ + protected function write(array $record): void + { + $data = $record["formatted"]; $routingKey = $this->getRoutingKey($record); if ($this->exchange instanceof AMQPExchange) { @@ -80,7 +89,7 @@ class AmqpHandler extends AbstractProcessingHandler 'delivery_mode' => 2, 'content_type' => 'application/json', ]; - if (\count($this->extraAttributes) > 0) { + if ($this->extraAttributes) { $attributes = array_merge($attributes, $this->extraAttributes); } $this->exchange->publish( @@ -99,7 +108,7 @@ class AmqpHandler extends AbstractProcessingHandler } /** - * @inheritDoc + * {@inheritDoc} */ public function handleBatch(array $records): void { @@ -114,6 +123,7 @@ class AmqpHandler extends AbstractProcessingHandler continue; } + /** @var Record $record */ $record = $this->processRecord($record); $data = $this->getFormatter()->format($record); @@ -129,27 +139,30 @@ class AmqpHandler extends AbstractProcessingHandler /** * Gets the routing key for the AMQP exchange + * + * @phpstan-param Record $record */ - protected function getRoutingKey(LogRecord $record): string + protected function getRoutingKey(array $record): string { - $routingKey = sprintf('%s.%s', $record->level->name, $record->channel); + $routingKey = sprintf('%s.%s', $record['level_name'], $record['channel']); return strtolower($routingKey); } private function createAmqpMessage(string $data): AMQPMessage { - return new AMQPMessage( - $data, - [ - 'delivery_mode' => 2, - 'content_type' => 'application/json', - ] - ); + $attributes = [ + 'delivery_mode' => 2, + 'content_type' => 'application/json', + ]; + if ($this->extraAttributes) { + $attributes = array_merge($attributes, $this->extraAttributes); + } + return new AMQPMessage($data, $attributes); } /** - * @inheritDoc + * {@inheritDoc} */ protected function getDefaultFormatter(): FormatterInterface { diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php index 28564b3fc..95bbfed42 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php @@ -14,30 +14,35 @@ namespace Monolog\Handler; use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\LineFormatter; use Monolog\Utils; -use Monolog\LogRecord; +use Monolog\Logger; use function count; use function headers_list; use function stripos; +use function trigger_error; + +use const E_USER_DEPRECATED; /** * Handler sending logs to browser's javascript console with no browser extension required * * @author Olivier Poitrey + * + * @phpstan-import-type FormattedRecord from AbstractProcessingHandler */ class BrowserConsoleHandler extends AbstractProcessingHandler { - protected static bool $initialized = false; - - /** @var LogRecord[] */ - protected static array $records = []; + /** @var bool */ + protected static $initialized = false; + /** @var FormattedRecord[] */ + protected static $records = []; protected const FORMAT_HTML = 'html'; protected const FORMAT_JS = 'js'; protected const FORMAT_UNKNOWN = 'unknown'; /** - * @inheritDoc + * {@inheritDoc} * * Formatted output may contain some formatting markers to be transferred to `console.log` using the %c format. * @@ -51,9 +56,9 @@ class BrowserConsoleHandler extends AbstractProcessingHandler } /** - * @inheritDoc + * {@inheritDoc} */ - protected function write(LogRecord $record): void + protected function write(array $record): void { // Accumulate records static::$records[] = $record; @@ -76,11 +81,11 @@ class BrowserConsoleHandler extends AbstractProcessingHandler return; } - if (count(static::$records) > 0) { + if (count(static::$records)) { if ($format === self::FORMAT_HTML) { - static::writeOutput(''); - } else { // js format - static::writeOutput(self::generateScript()); + static::writeOutput(''); + } elseif ($format === self::FORMAT_JS) { + static::writeOutput(static::generateScript()); } static::resetStatic(); } @@ -91,7 +96,7 @@ class BrowserConsoleHandler extends AbstractProcessingHandler self::resetStatic(); } - public function reset(): void + public function reset() { parent::reset(); @@ -169,18 +174,18 @@ class BrowserConsoleHandler extends AbstractProcessingHandler { $script = []; foreach (static::$records as $record) { - $context = self::dump('Context', $record->context); - $extra = self::dump('Extra', $record->extra); + $context = static::dump('Context', $record['context']); + $extra = static::dump('Extra', $record['extra']); - if (\count($context) === 0 && \count($extra) === 0) { - $script[] = self::call_array('log', self::handleStyles($record->formatted)); + if (empty($context) && empty($extra)) { + $script[] = static::call_array(static::getConsoleMethodForLevel($record['level']), static::handleStyles($record['formatted'])); } else { $script = array_merge( $script, - [self::call_array('groupCollapsed', self::handleStyles($record->formatted))], + [static::call_array('groupCollapsed', static::handleStyles($record['formatted']))], $context, $extra, - [self::call('groupEnd')] + [static::call('groupEnd')] ); } } @@ -188,6 +193,20 @@ class BrowserConsoleHandler extends AbstractProcessingHandler return "(function (c) {if (c && c.groupCollapsed) {\n" . implode("\n", $script) . "\n}})(console);"; } + private static function getConsoleMethodForLevel(int $level): string + { + return [ + Logger::DEBUG => 'debug', + Logger::INFO => 'info', + Logger::NOTICE => 'info', + Logger::WARNING => 'warn', + Logger::ERROR => 'error', + Logger::CRITICAL => 'error', + Logger::ALERT => 'error', + Logger::EMERGENCY => 'error', + ][$level] ?? 'log'; + } + /** * @return string[] */ @@ -199,14 +218,14 @@ class BrowserConsoleHandler extends AbstractProcessingHandler foreach (array_reverse($matches) as $match) { $args[] = '"font-weight: normal"'; - $args[] = self::quote(self::handleCustomStyles($match[2][0], $match[1][0])); + $args[] = static::quote(static::handleCustomStyles($match[2][0], $match[1][0])); $pos = $match[0][1]; $format = Utils::substr($format, 0, $pos) . '%c' . $match[1][0] . '%c' . Utils::substr($format, $pos + strlen($match[0][0])); } - $args[] = self::quote('font-weight: normal'); - $args[] = self::quote($format); + $args[] = static::quote('font-weight: normal'); + $args[] = static::quote($format); return array_reverse($args); } @@ -232,7 +251,6 @@ class BrowserConsoleHandler extends AbstractProcessingHandler if (null === $style) { $pcreErrorCode = preg_last_error(); - throw new \RuntimeException('Failed to run preg_replace_callback: ' . $pcreErrorCode . ' / ' . Utils::pcreLastErrorMessage($pcreErrorCode)); } @@ -247,16 +265,16 @@ class BrowserConsoleHandler extends AbstractProcessingHandler { $script = []; $dict = array_filter($dict); - if (\count($dict) === 0) { + if (empty($dict)) { return $script; } - $script[] = self::call('log', self::quote('%c%s'), self::quote('font-weight: bold'), self::quote($title)); + $script[] = static::call('log', static::quote('%c%s'), static::quote('font-weight: bold'), static::quote($title)); foreach ($dict as $key => $value) { $value = json_encode($value); if (empty($value)) { - $value = self::quote(''); + $value = static::quote(''); } - $script[] = self::call('log', self::quote('%s: %o'), self::quote((string) $key), $value); + $script[] = static::call('log', static::quote('%s: %o'), static::quote((string) $key), $value); } return $script; @@ -277,7 +295,7 @@ class BrowserConsoleHandler extends AbstractProcessingHandler throw new \UnexpectedValueException('Expected the first arg to be a string, got: '.var_export($method, true)); } - return self::call_array($method, $args); + return static::call_array($method, $args); } /** diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/BufferHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/BufferHandler.php index ff89faa8a..fcce5d630 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/BufferHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/BufferHandler.php @@ -11,10 +11,9 @@ namespace Monolog\Handler; -use Monolog\Level; +use Monolog\Logger; use Monolog\ResettableInterface; use Monolog\Formatter\FormatterInterface; -use Monolog\LogRecord; /** * Buffers all records until closing the handler and then pass them as batch. @@ -23,30 +22,32 @@ use Monolog\LogRecord; * sending one per log message. * * @author Christophe Coevoet + * + * @phpstan-import-type Record from \Monolog\Logger */ class BufferHandler extends AbstractHandler implements ProcessableHandlerInterface, FormattableHandlerInterface { use ProcessableHandlerTrait; - protected HandlerInterface $handler; - - protected int $bufferSize = 0; - - protected int $bufferLimit; - - protected bool $flushOnOverflow; - - /** @var LogRecord[] */ - protected array $buffer = []; - - protected bool $initialized = false; + /** @var HandlerInterface */ + protected $handler; + /** @var int */ + protected $bufferSize = 0; + /** @var int */ + protected $bufferLimit; + /** @var bool */ + protected $flushOnOverflow; + /** @var Record[] */ + protected $buffer = []; + /** @var bool */ + protected $initialized = false; /** * @param HandlerInterface $handler Handler. * @param int $bufferLimit How many entries should be buffered at most, beyond that the oldest items are removed from the buffer. * @param bool $flushOnOverflow If true, the buffer is flushed when the max size has been reached, by default oldest entries are discarded */ - public function __construct(HandlerInterface $handler, int $bufferLimit = 0, int|string|Level $level = Level::Debug, bool $bubble = true, bool $flushOnOverflow = false) + public function __construct(HandlerInterface $handler, int $bufferLimit = 0, $level = Logger::DEBUG, bool $bubble = true, bool $flushOnOverflow = false) { parent::__construct($level, $bubble); $this->handler = $handler; @@ -55,11 +56,11 @@ class BufferHandler extends AbstractHandler implements ProcessableHandlerInterfa } /** - * @inheritDoc + * {@inheritDoc} */ - public function handle(LogRecord $record): bool + public function handle(array $record): bool { - if ($record->level->isLowerThan($this->level)) { + if ($record['level'] < $this->level) { return false; } @@ -78,7 +79,8 @@ class BufferHandler extends AbstractHandler implements ProcessableHandlerInterfa } } - if (\count($this->processors) > 0) { + if ($this->processors) { + /** @var Record $record */ $record = $this->processRecord($record); } @@ -106,7 +108,7 @@ class BufferHandler extends AbstractHandler implements ProcessableHandlerInterfa } /** - * @inheritDoc + * {@inheritDoc} */ public function close(): void { @@ -124,7 +126,7 @@ class BufferHandler extends AbstractHandler implements ProcessableHandlerInterfa $this->buffer = []; } - public function reset(): void + public function reset() { $this->flush(); @@ -138,7 +140,7 @@ class BufferHandler extends AbstractHandler implements ProcessableHandlerInterfa } /** - * @inheritDoc + * {@inheritDoc} */ public function setFormatter(FormatterInterface $formatter): HandlerInterface { @@ -152,7 +154,7 @@ class BufferHandler extends AbstractHandler implements ProcessableHandlerInterfa } /** - * @inheritDoc + * {@inheritDoc} */ public function getFormatter(): FormatterInterface { diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php index 3742d47d9..234ecf614 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php @@ -13,10 +13,8 @@ namespace Monolog\Handler; use Monolog\Formatter\ChromePHPFormatter; use Monolog\Formatter\FormatterInterface; -use Monolog\Level; +use Monolog\Logger; use Monolog\Utils; -use Monolog\LogRecord; -use Monolog\DateTimeImmutable; /** * Handler sending logs to the ChromePHP extension (http://www.chromephp.com/) @@ -24,6 +22,8 @@ use Monolog\DateTimeImmutable; * This also works out of the box with Firefox 43+ * * @author Christophe Coevoet + * + * @phpstan-import-type Record from \Monolog\Logger */ class ChromePHPHandler extends AbstractProcessingHandler { @@ -44,25 +44,29 @@ class ChromePHPHandler extends AbstractProcessingHandler */ protected const USER_AGENT_REGEX = '{\b(?:Chrome/\d+(?:\.\d+)*|HeadlessChrome|Firefox/(?:4[3-9]|[5-9]\d|\d{3,})(?:\.\d)*)\b}'; - protected static bool $initialized = false; + /** @var bool */ + protected static $initialized = false; /** * Tracks whether we sent too much data * * Chrome limits the headers to 4KB, so when we sent 3KB we stop sending + * + * @var bool */ - protected static bool $overflowed = false; + protected static $overflowed = false; /** @var mixed[] */ - protected static array $json = [ + protected static $json = [ 'version' => self::VERSION, 'columns' => ['label', 'log', 'backtrace', 'type'], 'rows' => [], ]; - protected static bool $sendHeaders = true; + /** @var bool */ + protected static $sendHeaders = true; - public function __construct(int|string|Level $level = Level::Debug, bool $bubble = true) + public function __construct($level = Logger::DEBUG, bool $bubble = true) { parent::__construct($level, $bubble); if (!function_exists('json_encode')) { @@ -71,7 +75,7 @@ class ChromePHPHandler extends AbstractProcessingHandler } /** - * @inheritDoc + * {@inheritDoc} */ public function handleBatch(array $records): void { @@ -82,15 +86,15 @@ class ChromePHPHandler extends AbstractProcessingHandler $messages = []; foreach ($records as $record) { - if ($record->level < $this->level) { + if ($record['level'] < $this->level) { continue; } - + /** @var Record $message */ $message = $this->processRecord($record); $messages[] = $message; } - if (\count($messages) > 0) { + if (!empty($messages)) { $messages = $this->getFormatter()->formatBatch($messages); self::$json['rows'] = array_merge(self::$json['rows'], $messages); $this->send(); @@ -98,7 +102,7 @@ class ChromePHPHandler extends AbstractProcessingHandler } /** - * @inheritDoc + * {@inheritDoc} */ protected function getDefaultFormatter(): FormatterInterface { @@ -111,13 +115,13 @@ class ChromePHPHandler extends AbstractProcessingHandler * @see sendHeader() * @see send() */ - protected function write(LogRecord $record): void + protected function write(array $record): void { if (!$this->isWebRequest()) { return; } - self::$json['rows'][] = $record->formatted; + self::$json['rows'][] = $record['formatted']; $this->send(); } @@ -149,12 +153,15 @@ class ChromePHPHandler extends AbstractProcessingHandler if (strlen($data) > 3 * 1024) { self::$overflowed = true; - $record = new LogRecord( - message: 'Incomplete logs, chrome header size limit reached', - level: Level::Warning, - channel: 'monolog', - datetime: new DateTimeImmutable(true), - ); + $record = [ + 'message' => 'Incomplete logs, chrome header size limit reached', + 'context' => [], + 'level' => Logger::WARNING, + 'level_name' => Logger::getLevelName(Logger::WARNING), + 'channel' => 'monolog', + 'datetime' => new \DateTimeImmutable(), + 'extra' => [], + ]; self::$json['rows'][count(self::$json['rows']) - 1] = $this->getFormatter()->format($record); $json = Utils::jsonEncode(self::$json, Utils::DEFAULT_JSON_FLAGS & ~JSON_UNESCAPED_UNICODE, true); $data = base64_encode($json); @@ -180,7 +187,7 @@ class ChromePHPHandler extends AbstractProcessingHandler */ protected function headersAccepted(): bool { - if (!isset($_SERVER['HTTP_USER_AGENT'])) { + if (empty($_SERVER['HTTP_USER_AGENT'])) { return false; } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/CouchDBHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/CouchDBHandler.php index 8d9c10e76..526576132 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/CouchDBHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/CouchDBHandler.php @@ -13,42 +13,22 @@ namespace Monolog\Handler; use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\JsonFormatter; -use Monolog\Level; -use Monolog\LogRecord; +use Monolog\Logger; /** * CouchDB handler * * @author Markus Bachmann - * @phpstan-type Options array{ - * host: string, - * port: int, - * dbname: string, - * username: string|null, - * password: string|null - * } - * @phpstan-type InputOptions array{ - * host?: string, - * port?: int, - * dbname?: string, - * username?: string|null, - * password?: string|null - * } */ class CouchDBHandler extends AbstractProcessingHandler { - /** - * @var mixed[] - * @phpstan-var Options - */ - private array $options; + /** @var mixed[] */ + private $options; /** * @param mixed[] $options - * - * @phpstan-param InputOptions $options */ - public function __construct(array $options = [], int|string|Level $level = Level::Debug, bool $bubble = true) + public function __construct(array $options = [], $level = Logger::DEBUG, bool $bubble = true) { $this->options = array_merge([ 'host' => 'localhost', @@ -62,12 +42,12 @@ class CouchDBHandler extends AbstractProcessingHandler } /** - * @inheritDoc + * {@inheritDoc} */ - protected function write(LogRecord $record): void + protected function write(array $record): void { $basicAuth = null; - if (null !== $this->options['username'] && null !== $this->options['password']) { + if ($this->options['username']) { $basicAuth = sprintf('%s:%s@', $this->options['username'], $this->options['password']); } @@ -75,7 +55,7 @@ class CouchDBHandler extends AbstractProcessingHandler $context = stream_context_create([ 'http' => [ 'method' => 'POST', - 'content' => $record->formatted, + 'content' => $record['formatted'], 'ignore_errors' => true, 'max_redirects' => 0, 'header' => 'Content-type: application/json', @@ -88,7 +68,7 @@ class CouchDBHandler extends AbstractProcessingHandler } /** - * @inheritDoc + * {@inheritDoc} */ protected function getDefaultFormatter(): FormatterInterface { diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/CubeHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/CubeHandler.php index 8388f5ade..3535a4fcd 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/CubeHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/CubeHandler.php @@ -11,9 +11,8 @@ namespace Monolog\Handler; -use Monolog\Level; +use Monolog\Logger; use Monolog\Utils; -use Monolog\LogRecord; /** * Logs to Cube. @@ -24,13 +23,18 @@ use Monolog\LogRecord; */ class CubeHandler extends AbstractProcessingHandler { - private ?\Socket $udpConnection = null; - private ?\CurlHandle $httpConnection = null; - private string $scheme; - private string $host; - private int $port; + /** @var resource|\Socket|null */ + private $udpConnection = null; + /** @var resource|\CurlHandle|null */ + private $httpConnection = null; + /** @var string */ + private $scheme; + /** @var string */ + private $host; + /** @var int */ + private $port; /** @var string[] */ - private array $acceptedSchemes = ['http', 'udp']; + private $acceptedSchemes = ['http', 'udp']; /** * Create a Cube handler @@ -39,7 +43,7 @@ class CubeHandler extends AbstractProcessingHandler * A valid url must consist of three parts : protocol://host:port * Only valid protocols used by Cube are http and udp */ - public function __construct(string $url, int|string|Level $level = Level::Debug, bool $bubble = true) + public function __construct(string $url, $level = Logger::DEBUG, bool $bubble = true) { $urlInfo = parse_url($url); @@ -47,7 +51,7 @@ class CubeHandler extends AbstractProcessingHandler throw new \UnexpectedValueException('URL "'.$url.'" is not valid'); } - if (!in_array($urlInfo['scheme'], $this->acceptedSchemes, true)) { + if (!in_array($urlInfo['scheme'], $this->acceptedSchemes)) { throw new \UnexpectedValueException( 'Invalid protocol (' . $urlInfo['scheme'] . ').' . ' Valid options are ' . implode(', ', $this->acceptedSchemes) @@ -56,7 +60,7 @@ class CubeHandler extends AbstractProcessingHandler $this->scheme = $urlInfo['scheme']; $this->host = $urlInfo['host']; - $this->port = $urlInfo['port']; + $this->port = (int) $urlInfo['port']; parent::__construct($level, $bubble); } @@ -107,24 +111,24 @@ class CubeHandler extends AbstractProcessingHandler } /** - * @inheritDoc + * {@inheritDoc} */ - protected function write(LogRecord $record): void + protected function write(array $record): void { - $date = $record->datetime; + $date = $record['datetime']; $data = ['time' => $date->format('Y-m-d\TH:i:s.uO')]; - $context = $record->context; + unset($record['datetime']); - if (isset($context['type'])) { - $data['type'] = $context['type']; - unset($context['type']); + if (isset($record['context']['type'])) { + $data['type'] = $record['context']['type']; + unset($record['context']['type']); } else { - $data['type'] = $record->channel; + $data['type'] = $record['channel']; } - $data['data'] = $context; - $data['data']['level'] = $record->level; + $data['data'] = $record['context']; + $data['data']['level'] = $record['level']; if ($this->scheme === 'http') { $this->writeHttp(Utils::jsonEncode($data)); @@ -135,20 +139,16 @@ class CubeHandler extends AbstractProcessingHandler private function writeUdp(string $data): void { - if (null === $this->udpConnection) { + if (!$this->udpConnection) { $this->connectUdp(); } - if (null === $this->udpConnection) { - throw new \LogicException('No UDP socket could be opened'); - } - socket_send($this->udpConnection, $data, strlen($data), 0); } private function writeHttp(string $data): void { - if (null === $this->httpConnection) { + if (!$this->httpConnection) { $this->connectHttp(); } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/Curl/Util.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/Curl/Util.php index 4decf0e62..7213e8ee2 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/Curl/Util.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/Curl/Util.php @@ -21,7 +21,7 @@ use CurlHandle; final class Util { /** @var array */ - private static array $retriableErrorCodes = [ + private static $retriableErrorCodes = [ CURLE_COULDNT_RESOLVE_HOST, CURLE_COULDNT_CONNECT, CURLE_HTTP_NOT_FOUND, @@ -34,17 +34,19 @@ final class Util /** * Executes a CURL request with optional retries and exception on failure * - * @param CurlHandle $ch curl handler - * @return bool|string @see curl_exec + * @param resource|CurlHandle $ch curl handler + * @param int $retries + * @param bool $closeAfterDone + * @return bool|string @see curl_exec */ - public static function execute(CurlHandle $ch, int $retries = 5, bool $closeAfterDone = true) + public static function execute($ch, int $retries = 5, bool $closeAfterDone = true) { while ($retries--) { $curlResponse = curl_exec($ch); if ($curlResponse === false) { $curlErrno = curl_errno($ch); - if (false === in_array($curlErrno, self::$retriableErrorCodes, true) || $retries === 0) { + if (false === in_array($curlErrno, self::$retriableErrorCodes, true) || !$retries) { $curlError = curl_error($ch); if ($closeAfterDone) { diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/DeduplicationHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/DeduplicationHandler.php index 355491219..9b85ae7ed 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/DeduplicationHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/DeduplicationHandler.php @@ -11,10 +11,8 @@ namespace Monolog\Handler; -use Monolog\Level; use Monolog\Logger; use Psr\Log\LogLevel; -use Monolog\LogRecord; /** * Simple handler wrapper that deduplicates log records across multiple requests @@ -35,29 +33,45 @@ use Monolog\LogRecord; * same way. * * @author Jordi Boggiano + * + * @phpstan-import-type Record from \Monolog\Logger + * @phpstan-import-type LevelName from \Monolog\Logger + * @phpstan-import-type Level from \Monolog\Logger */ class DeduplicationHandler extends BufferHandler { - protected string $deduplicationStore; - - protected Level $deduplicationLevel; - - protected int $time; - - private bool $gc = false; + /** + * @var string + */ + protected $deduplicationStore; /** - * @param HandlerInterface $handler Handler. - * @param string $deduplicationStore The file/path where the deduplication log should be kept - * @param int|string|Level|LogLevel::* $deduplicationLevel The minimum logging level for log records to be looked at for deduplication purposes - * @param int $time The period (in seconds) during which duplicate entries should be suppressed after a given log is sent through - * @param bool $bubble Whether the messages that are handled can bubble up the stack or not - * - * @phpstan-param value-of|value-of|Level|LogLevel::* $deduplicationLevel + * @var Level */ - public function __construct(HandlerInterface $handler, ?string $deduplicationStore = null, int|string|Level $deduplicationLevel = Level::Error, int $time = 60, bool $bubble = true) + protected $deduplicationLevel; + + /** + * @var int + */ + protected $time; + + /** + * @var bool + */ + private $gc = false; + + /** + * @param HandlerInterface $handler Handler. + * @param string $deduplicationStore The file/path where the deduplication log should be kept + * @param string|int $deduplicationLevel The minimum logging level for log records to be looked at for deduplication purposes + * @param int $time The period (in seconds) during which duplicate entries should be suppressed after a given log is sent through + * @param bool $bubble Whether the messages that are handled can bubble up the stack or not + * + * @phpstan-param Level|LevelName|LogLevel::* $deduplicationLevel + */ + public function __construct(HandlerInterface $handler, ?string $deduplicationStore = null, $deduplicationLevel = Logger::ERROR, int $time = 60, bool $bubble = true) { - parent::__construct($handler, 0, Level::Debug, $bubble, false); + parent::__construct($handler, 0, Logger::DEBUG, $bubble, false); $this->deduplicationStore = $deduplicationStore === null ? sys_get_temp_dir() . '/monolog-dedup-' . substr(md5(__FILE__), 0, 20) .'.log' : $deduplicationStore; $this->deduplicationLevel = Logger::toMonologLevel($deduplicationLevel); @@ -73,8 +87,8 @@ class DeduplicationHandler extends BufferHandler $passthru = null; foreach ($this->buffer as $record) { - if ($record->level->value >= $this->deduplicationLevel->value) { - $passthru = $passthru === true || !$this->isDuplicate($record); + if ($record['level'] >= $this->deduplicationLevel) { + $passthru = $passthru || !$this->isDuplicate($record); if ($passthru) { $this->appendRecord($record); } @@ -93,7 +107,10 @@ class DeduplicationHandler extends BufferHandler } } - private function isDuplicate(LogRecord $record): bool + /** + * @phpstan-param Record $record + */ + private function isDuplicate(array $record): bool { if (!file_exists($this->deduplicationStore)) { return false; @@ -105,13 +122,13 @@ class DeduplicationHandler extends BufferHandler } $yesterday = time() - 86400; - $timestampValidity = $record->datetime->getTimestamp() - $this->time; - $expectedMessage = preg_replace('{[\r\n].*}', '', $record->message); + $timestampValidity = $record['datetime']->getTimestamp() - $this->time; + $expectedMessage = preg_replace('{[\r\n].*}', '', $record['message']); for ($i = count($store) - 1; $i >= 0; $i--) { list($timestamp, $level, $message) = explode(':', $store[$i], 3); - if ($level === $record->level->getName() && $message === $expectedMessage && $timestamp > $timestampValidity) { + if ($level === $record['level_name'] && $message === $expectedMessage && $timestamp > $timestampValidity) { return true; } @@ -131,7 +148,7 @@ class DeduplicationHandler extends BufferHandler $handle = fopen($this->deduplicationStore, 'rw+'); - if (false === $handle) { + if (!$handle) { throw new \RuntimeException('Failed to open file for reading and writing: ' . $this->deduplicationStore); } @@ -142,7 +159,7 @@ class DeduplicationHandler extends BufferHandler while (!feof($handle)) { $log = fgets($handle); - if (is_string($log) && '' !== $log && substr($log, 0, 10) >= $timestampValidity) { + if ($log && substr($log, 0, 10) >= $timestampValidity) { $validLogs[] = $log; } } @@ -159,8 +176,11 @@ class DeduplicationHandler extends BufferHandler $this->gc = false; } - private function appendRecord(LogRecord $record): void + /** + * @phpstan-param Record $record + */ + private function appendRecord(array $record): void { - file_put_contents($this->deduplicationStore, $record->datetime->getTimestamp() . ':' . $record->level->getName() . ':' . preg_replace('{[\r\n].*}', '', $record->message) . "\n", FILE_APPEND); + file_put_contents($this->deduplicationStore, $record['datetime']->getTimestamp() . ':' . $record['level_name'] . ':' . preg_replace('{[\r\n].*}', '', $record['message']) . "\n", FILE_APPEND); } } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/DoctrineCouchDBHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/DoctrineCouchDBHandler.php index eab9f1089..ebd52c3a0 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/DoctrineCouchDBHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/DoctrineCouchDBHandler.php @@ -11,11 +11,10 @@ namespace Monolog\Handler; -use Monolog\Level; +use Monolog\Logger; use Monolog\Formatter\NormalizerFormatter; use Monolog\Formatter\FormatterInterface; use Doctrine\CouchDB\CouchDBClient; -use Monolog\LogRecord; /** * CouchDB handler for Doctrine CouchDB ODM @@ -24,20 +23,21 @@ use Monolog\LogRecord; */ class DoctrineCouchDBHandler extends AbstractProcessingHandler { - private CouchDBClient $client; + /** @var CouchDBClient */ + private $client; - public function __construct(CouchDBClient $client, int|string|Level $level = Level::Debug, bool $bubble = true) + public function __construct(CouchDBClient $client, $level = Logger::DEBUG, bool $bubble = true) { $this->client = $client; parent::__construct($level, $bubble); } /** - * @inheritDoc + * {@inheritDoc} */ - protected function write(LogRecord $record): void + protected function write(array $record): void { - $this->client->postDocument($record->formatted); + $this->client->postDocument($record['formatted']); } protected function getDefaultFormatter(): FormatterInterface diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/DynamoDbHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/DynamoDbHandler.php index f1c5a9590..21840bf60 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/DynamoDbHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/DynamoDbHandler.php @@ -16,8 +16,7 @@ use Aws\DynamoDb\DynamoDbClient; use Monolog\Formatter\FormatterInterface; use Aws\DynamoDb\Marshaler; use Monolog\Formatter\ScalarFormatter; -use Monolog\Level; -use Monolog\LogRecord; +use Monolog\Logger; /** * Amazon DynamoDB handler (http://aws.amazon.com/dynamodb/) @@ -29,15 +28,35 @@ class DynamoDbHandler extends AbstractProcessingHandler { public const DATE_FORMAT = 'Y-m-d\TH:i:s.uO'; - protected DynamoDbClient $client; + /** + * @var DynamoDbClient + */ + protected $client; - protected string $table; + /** + * @var string + */ + protected $table; - protected Marshaler $marshaler; + /** + * @var int + */ + protected $version; - public function __construct(DynamoDbClient $client, string $table, int|string|Level $level = Level::Debug, bool $bubble = true) + /** + * @var Marshaler + */ + protected $marshaler; + + public function __construct(DynamoDbClient $client, string $table, $level = Logger::DEBUG, bool $bubble = true) { - $this->marshaler = new Marshaler; + /** @phpstan-ignore-next-line */ + if (defined('Aws\Sdk::VERSION') && version_compare(Sdk::VERSION, '3.0', '>=')) { + $this->version = 3; + $this->marshaler = new Marshaler; + } else { + $this->version = 2; + } $this->client = $client; $this->table = $table; @@ -46,12 +65,17 @@ class DynamoDbHandler extends AbstractProcessingHandler } /** - * @inheritDoc + * {@inheritDoc} */ - protected function write(LogRecord $record): void + protected function write(array $record): void { - $filtered = $this->filterEmptyFields($record->formatted); - $formatted = $this->marshaler->marshalItem($filtered); + $filtered = $this->filterEmptyFields($record['formatted']); + if ($this->version === 3) { + $formatted = $this->marshaler->marshalItem($filtered); + } else { + /** @phpstan-ignore-next-line */ + $formatted = $this->client->formatAttributes($filtered); + } $this->client->putItem([ 'TableName' => $this->table, @@ -66,12 +90,12 @@ class DynamoDbHandler extends AbstractProcessingHandler protected function filterEmptyFields(array $record): array { return array_filter($record, function ($value) { - return [] !== $value; + return !empty($value) || false === $value || 0 === $value; }); } /** - * @inheritDoc + * {@inheritDoc} */ protected function getDefaultFormatter(): FormatterInterface { diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/ElasticaHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/ElasticaHandler.php index d9b85b4d0..fc92ca42d 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/ElasticaHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/ElasticaHandler.php @@ -14,10 +14,9 @@ namespace Monolog\Handler; use Elastica\Document; use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\ElasticaFormatter; -use Monolog\Level; +use Monolog\Logger; use Elastica\Client; use Elastica\Exception\ExceptionInterface; -use Monolog\LogRecord; /** * Elastic Search handler @@ -34,34 +33,24 @@ use Monolog\LogRecord; * $log->pushHandler($handler); * * @author Jelle Vink - * @phpstan-type Options array{ - * index: string, - * type: string, - * ignore_error: bool - * } - * @phpstan-type InputOptions array{ - * index?: string, - * type?: string, - * ignore_error?: bool - * } */ class ElasticaHandler extends AbstractProcessingHandler { - protected Client $client; + /** + * @var Client + */ + protected $client; /** * @var mixed[] Handler config options - * @phpstan-var Options */ - protected array $options; + protected $options = []; /** * @param Client $client Elastica Client object * @param mixed[] $options Handler configuration - * - * @phpstan-param InputOptions $options */ - public function __construct(Client $client, array $options = [], int|string|Level $level = Level::Debug, bool $bubble = true) + public function __construct(Client $client, array $options = [], $level = Logger::DEBUG, bool $bubble = true) { parent::__construct($level, $bubble); $this->client = $client; @@ -76,15 +65,15 @@ class ElasticaHandler extends AbstractProcessingHandler } /** - * @inheritDoc + * {@inheritDoc} */ - protected function write(LogRecord $record): void + protected function write(array $record): void { - $this->bulkSend([$record->formatted]); + $this->bulkSend([$record['formatted']]); } /** - * @inheritDoc + * {@inheritDoc} */ public function setFormatter(FormatterInterface $formatter): HandlerInterface { @@ -97,8 +86,6 @@ class ElasticaHandler extends AbstractProcessingHandler /** * @return mixed[] - * - * @phpstan-return Options */ public function getOptions(): array { @@ -106,7 +93,7 @@ class ElasticaHandler extends AbstractProcessingHandler } /** - * @inheritDoc + * {@inheritDoc} */ protected function getDefaultFormatter(): FormatterInterface { @@ -114,7 +101,7 @@ class ElasticaHandler extends AbstractProcessingHandler } /** - * @inheritDoc + * {@inheritDoc} */ public function handleBatch(array $records): void { diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/ElasticsearchHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/ElasticsearchHandler.php index c288824aa..e88375c0e 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/ElasticsearchHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/ElasticsearchHandler.php @@ -14,13 +14,12 @@ namespace Monolog\Handler; use Elastic\Elasticsearch\Response\Elasticsearch; use Throwable; use RuntimeException; -use Monolog\Level; +use Monolog\Logger; use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\ElasticsearchFormatter; use InvalidArgumentException; use Elasticsearch\Common\Exceptions\RuntimeException as ElasticsearchRuntimeException; use Elasticsearch\Client; -use Monolog\LogRecord; use Elastic\Elasticsearch\Exception\InvalidArgumentException as ElasticInvalidArgumentException; use Elastic\Elasticsearch\Client as Client8; @@ -44,26 +43,18 @@ use Elastic\Elasticsearch\Client as Client8; * $log->pushHandler($handler); * * @author Avtandil Kikabidze - * @phpstan-type Options array{ - * index: string, - * type: string, - * ignore_error: bool - * } - * @phpstan-type InputOptions array{ - * index?: string, - * type?: string, - * ignore_error?: bool - * } */ class ElasticsearchHandler extends AbstractProcessingHandler { - protected Client|Client8 $client; + /** + * @var Client|Client8 + */ + protected $client; /** * @var mixed[] Handler config options - * @phpstan-var Options */ - protected array $options; + protected $options = []; /** * @var bool @@ -73,11 +64,13 @@ class ElasticsearchHandler extends AbstractProcessingHandler /** * @param Client|Client8 $client Elasticsearch Client object * @param mixed[] $options Handler configuration - * - * @phpstan-param InputOptions $options */ - public function __construct(Client|Client8 $client, array $options = [], int|string|Level $level = Level::Debug, bool $bubble = true) + public function __construct($client, array $options = [], $level = Logger::DEBUG, bool $bubble = true) { + if (!$client instanceof Client && !$client instanceof Client8) { + throw new \TypeError('Elasticsearch\Client or Elastic\Elasticsearch\Client instance required'); + } + parent::__construct($level, $bubble); $this->client = $client; $this->options = array_merge( @@ -99,15 +92,15 @@ class ElasticsearchHandler extends AbstractProcessingHandler } /** - * @inheritDoc + * {@inheritDoc} */ - protected function write(LogRecord $record): void + protected function write(array $record): void { - $this->bulkSend([$record->formatted]); + $this->bulkSend([$record['formatted']]); } /** - * @inheritDoc + * {@inheritDoc} */ public function setFormatter(FormatterInterface $formatter): HandlerInterface { @@ -122,8 +115,6 @@ class ElasticsearchHandler extends AbstractProcessingHandler * Getter options * * @return mixed[] - * - * @phpstan-return Options */ public function getOptions(): array { @@ -131,7 +122,7 @@ class ElasticsearchHandler extends AbstractProcessingHandler } /** - * @inheritDoc + * {@inheritDoc} */ protected function getDefaultFormatter(): FormatterInterface { @@ -139,7 +130,7 @@ class ElasticsearchHandler extends AbstractProcessingHandler } /** - * @inheritDoc + * {@inheritDoc} */ public function handleBatch(array $records): void { @@ -150,7 +141,7 @@ class ElasticsearchHandler extends AbstractProcessingHandler /** * Use Elasticsearch bulk API to send list of documents * - * @param array> $records Records + _index/_type keys + * @param array[] $records Records + _index/_type keys * @throws \RuntimeException */ protected function bulkSend(array $records): void diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/ErrorLogHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/ErrorLogHandler.php index 477d7e45a..f2e22036b 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/ErrorLogHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/ErrorLogHandler.php @@ -13,9 +13,8 @@ namespace Monolog\Handler; use Monolog\Formatter\LineFormatter; use Monolog\Formatter\FormatterInterface; -use Monolog\Level; +use Monolog\Logger; use Monolog\Utils; -use Monolog\LogRecord; /** * Stores to PHP error_log() handler. @@ -27,14 +26,16 @@ class ErrorLogHandler extends AbstractProcessingHandler public const OPERATING_SYSTEM = 0; public const SAPI = 4; - protected int $messageType; - protected bool $expandNewlines; + /** @var int */ + protected $messageType; + /** @var bool */ + protected $expandNewlines; /** * @param int $messageType Says where the error should go. * @param bool $expandNewlines If set to true, newlines in the message will be expanded to be take multiple log entries */ - public function __construct(int $messageType = self::OPERATING_SYSTEM, int|string|Level $level = Level::Debug, bool $bubble = true, bool $expandNewlines = false) + public function __construct(int $messageType = self::OPERATING_SYSTEM, $level = Logger::DEBUG, bool $bubble = true, bool $expandNewlines = false) { parent::__construct($level, $bubble); @@ -60,7 +61,7 @@ class ErrorLogHandler extends AbstractProcessingHandler } /** - * @inheritDoc + * {@inheritDoc} */ protected function getDefaultFormatter(): FormatterInterface { @@ -68,20 +69,19 @@ class ErrorLogHandler extends AbstractProcessingHandler } /** - * @inheritDoc + * {@inheritDoc} */ - protected function write(LogRecord $record): void + protected function write(array $record): void { if (!$this->expandNewlines) { - error_log((string) $record->formatted, $this->messageType); + error_log((string) $record['formatted'], $this->messageType); return; } - $lines = preg_split('{[\r\n]+}', (string) $record->formatted); + $lines = preg_split('{[\r\n]+}', (string) $record['formatted']); if ($lines === false) { $pcreErrorCode = preg_last_error(); - throw new \RuntimeException('Failed to preg_split formatted string: ' . $pcreErrorCode . ' / '. Utils::pcreLastErrorMessage($pcreErrorCode)); } foreach ($lines as $line) { diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FallbackGroupHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FallbackGroupHandler.php index 1776eb517..d4e234ce0 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FallbackGroupHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FallbackGroupHandler.php @@ -12,7 +12,6 @@ namespace Monolog\Handler; use Throwable; -use Monolog\LogRecord; /** * Forwards records to at most one handler @@ -20,15 +19,18 @@ use Monolog\LogRecord; * If a handler fails, the exception is suppressed and the record is forwarded to the next handler. * * As soon as one handler handles a record successfully, the handling stops there. + * + * @phpstan-import-type Record from \Monolog\Logger */ class FallbackGroupHandler extends GroupHandler { /** - * @inheritDoc + * {@inheritDoc} */ - public function handle(LogRecord $record): bool + public function handle(array $record): bool { - if (\count($this->processors) > 0) { + if ($this->processors) { + /** @var Record $record */ $record = $this->processRecord($record); } foreach ($this->handlers as $handler) { @@ -44,15 +46,16 @@ class FallbackGroupHandler extends GroupHandler } /** - * @inheritDoc + * {@inheritDoc} */ public function handleBatch(array $records): void { - if (\count($this->processors) > 0) { + if ($this->processors) { $processed = []; foreach ($records as $record) { $processed[] = $this->processRecord($record); } + /** @var Record[] $records */ $records = $processed; } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FilterHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FilterHandler.php index 00381ab4d..718f17ef1 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FilterHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FilterHandler.php @@ -11,13 +11,10 @@ namespace Monolog\Handler; -use Closure; -use Monolog\Level; use Monolog\Logger; use Monolog\ResettableInterface; use Monolog\Formatter\FormatterInterface; use Psr\Log\LogLevel; -use Monolog\LogRecord; /** * Simple handler wrapper that filters records based on a list of levels @@ -26,99 +23,110 @@ use Monolog\LogRecord; * * @author Hennadiy Verkh * @author Jordi Boggiano + * + * @phpstan-import-type Record from \Monolog\Logger + * @phpstan-import-type Level from \Monolog\Logger + * @phpstan-import-type LevelName from \Monolog\Logger */ class FilterHandler extends Handler implements ProcessableHandlerInterface, ResettableInterface, FormattableHandlerInterface { use ProcessableHandlerTrait; /** - * Handler or factory Closure($record, $this) + * Handler or factory callable($record, $this) * - * @phpstan-var (Closure(LogRecord|null, HandlerInterface): HandlerInterface)|HandlerInterface + * @var callable|HandlerInterface + * @phpstan-var callable(?Record, HandlerInterface): HandlerInterface|HandlerInterface */ - protected Closure|HandlerInterface $handler; + protected $handler; /** * Minimum level for logs that are passed to handler * - * @var bool[] Map of Level value => true - * @phpstan-var array, true> + * @var int[] + * @phpstan-var array */ - protected array $acceptedLevels; + protected $acceptedLevels; /** * Whether the messages that are handled can bubble up the stack or not + * + * @var bool */ - protected bool $bubble; + protected $bubble; /** - * @phpstan-param (Closure(LogRecord|null, HandlerInterface): HandlerInterface)|HandlerInterface $handler + * @psalm-param HandlerInterface|callable(?Record, HandlerInterface): HandlerInterface $handler * - * @param Closure|HandlerInterface $handler Handler or factory Closure($record|null, $filterHandler). - * @param int|string|Level|array $minLevelOrList A list of levels to accept or a minimum level if maxLevel is provided - * @param int|string|Level|LogLevel::* $maxLevel Maximum level to accept, only used if $minLevelOrList is not an array - * @param bool $bubble Whether the messages that are handled can bubble up the stack or not + * @param callable|HandlerInterface $handler Handler or factory callable($record|null, $filterHandler). + * @param int|array $minLevelOrList A list of levels to accept or a minimum level if maxLevel is provided + * @param int|string $maxLevel Maximum level to accept, only used if $minLevelOrList is not an array + * @param bool $bubble Whether the messages that are handled can bubble up the stack or not * - * @phpstan-param value-of|value-of|Level|LogLevel::*|array|value-of|Level|LogLevel::*> $minLevelOrList - * @phpstan-param value-of|value-of|Level|LogLevel::* $maxLevel + * @phpstan-param Level|LevelName|LogLevel::*|array $minLevelOrList + * @phpstan-param Level|LevelName|LogLevel::* $maxLevel */ - public function __construct(Closure|HandlerInterface $handler, int|string|Level|array $minLevelOrList = Level::Debug, int|string|Level $maxLevel = Level::Emergency, bool $bubble = true) + public function __construct($handler, $minLevelOrList = Logger::DEBUG, $maxLevel = Logger::EMERGENCY, bool $bubble = true) { $this->handler = $handler; $this->bubble = $bubble; $this->setAcceptedLevels($minLevelOrList, $maxLevel); + + if (!$this->handler instanceof HandlerInterface && !is_callable($this->handler)) { + throw new \RuntimeException("The given handler (".json_encode($this->handler).") is not a callable nor a Monolog\Handler\HandlerInterface object"); + } } /** - * @phpstan-return list List of levels + * @phpstan-return array */ public function getAcceptedLevels(): array { - return array_map(fn (int $level) => Level::from($level), array_keys($this->acceptedLevels)); + return array_flip($this->acceptedLevels); } /** - * @param int|string|Level|LogLevel::*|array $minLevelOrList A list of levels to accept or a minimum level or level name if maxLevel is provided - * @param int|string|Level|LogLevel::* $maxLevel Maximum level or level name to accept, only used if $minLevelOrList is not an array + * @param int|string|array $minLevelOrList A list of levels to accept or a minimum level or level name if maxLevel is provided + * @param int|string $maxLevel Maximum level or level name to accept, only used if $minLevelOrList is not an array * - * @phpstan-param value-of|value-of|Level|LogLevel::*|array|value-of|Level|LogLevel::*> $minLevelOrList - * @phpstan-param value-of|value-of|Level|LogLevel::* $maxLevel + * @phpstan-param Level|LevelName|LogLevel::*|array $minLevelOrList + * @phpstan-param Level|LevelName|LogLevel::* $maxLevel */ - public function setAcceptedLevels(int|string|Level|array $minLevelOrList = Level::Debug, int|string|Level $maxLevel = Level::Emergency): self + public function setAcceptedLevels($minLevelOrList = Logger::DEBUG, $maxLevel = Logger::EMERGENCY): self { if (is_array($minLevelOrList)) { - $acceptedLevels = array_map(Logger::toMonologLevel(...), $minLevelOrList); + $acceptedLevels = array_map('Monolog\Logger::toMonologLevel', $minLevelOrList); } else { $minLevelOrList = Logger::toMonologLevel($minLevelOrList); $maxLevel = Logger::toMonologLevel($maxLevel); - $acceptedLevels = array_values(array_filter(Level::cases(), fn (Level $level) => $level->value >= $minLevelOrList->value && $level->value <= $maxLevel->value)); - } - $this->acceptedLevels = []; - foreach ($acceptedLevels as $level) { - $this->acceptedLevels[$level->value] = true; + $acceptedLevels = array_values(array_filter(Logger::getLevels(), function ($level) use ($minLevelOrList, $maxLevel) { + return $level >= $minLevelOrList && $level <= $maxLevel; + })); } + $this->acceptedLevels = array_flip($acceptedLevels); return $this; } /** - * @inheritDoc + * {@inheritDoc} */ - public function isHandling(LogRecord $record): bool + public function isHandling(array $record): bool { - return isset($this->acceptedLevels[$record->level->value]); + return isset($this->acceptedLevels[$record['level']]); } /** - * @inheritDoc + * {@inheritDoc} */ - public function handle(LogRecord $record): bool + public function handle(array $record): bool { if (!$this->isHandling($record)) { return false; } - if (\count($this->processors) > 0) { + if ($this->processors) { + /** @var Record $record */ $record = $this->processRecord($record); } @@ -128,7 +136,7 @@ class FilterHandler extends Handler implements ProcessableHandlerInterface, Rese } /** - * @inheritDoc + * {@inheritDoc} */ public function handleBatch(array $records): void { @@ -147,23 +155,26 @@ class FilterHandler extends Handler implements ProcessableHandlerInterface, Rese /** * Return the nested handler * - * If the handler was provided as a factory, this will trigger the handler's instantiation. + * If the handler was provided as a factory callable, this will trigger the handler's instantiation. + * + * @return HandlerInterface + * + * @phpstan-param Record $record */ - public function getHandler(LogRecord $record = null): HandlerInterface + public function getHandler(array $record = null) { if (!$this->handler instanceof HandlerInterface) { - $handler = ($this->handler)($record, $this); - if (!$handler instanceof HandlerInterface) { - throw new \RuntimeException("The factory Closure should return a HandlerInterface"); + $this->handler = ($this->handler)($record, $this); + if (!$this->handler instanceof HandlerInterface) { + throw new \RuntimeException("The factory callable should return a HandlerInterface"); } - $this->handler = $handler; } return $this->handler; } /** - * @inheritDoc + * {@inheritDoc} */ public function setFormatter(FormatterInterface $formatter): HandlerInterface { @@ -178,7 +189,7 @@ class FilterHandler extends Handler implements ProcessableHandlerInterface, Rese } /** - * @inheritDoc + * {@inheritDoc} */ public function getFormatter(): FormatterInterface { @@ -190,7 +201,7 @@ class FilterHandler extends Handler implements ProcessableHandlerInterface, Rese throw new \UnexpectedValueException('The nested handler of type '.get_class($handler).' does not support formatters.'); } - public function reset(): void + public function reset() { $this->resetProcessors(); diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php index e8a1b0b0d..0aa5607b1 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php @@ -11,17 +11,19 @@ namespace Monolog\Handler\FingersCrossed; -use Monolog\LogRecord; - /** * Interface for activation strategies for the FingersCrossedHandler. * * @author Johannes M. Schmitt + * + * @phpstan-import-type Record from \Monolog\Logger */ interface ActivationStrategyInterface { /** * Returns whether the given record activates the handler. + * + * @phpstan-param Record $record */ - public function isHandlerActivated(LogRecord $record): bool; + public function isHandlerActivated(array $record): bool; } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.php index 383e19af9..7b9abb582 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.php @@ -11,10 +11,8 @@ namespace Monolog\Handler\FingersCrossed; -use Monolog\Level; use Monolog\Logger; use Psr\Log\LogLevel; -use Monolog\LogRecord; /** * Channel and Error level based monolog activation strategy. Allows to trigger activation @@ -25,45 +23,55 @@ use Monolog\LogRecord; * * * $activationStrategy = new ChannelLevelActivationStrategy( - * Level::Critical, + * Logger::CRITICAL, * array( - * 'request' => Level::Alert, - * 'sensitive' => Level::Error, + * 'request' => Logger::ALERT, + * 'sensitive' => Logger::ERROR, * ) * ); * $handler = new FingersCrossedHandler(new StreamHandler('php://stderr'), $activationStrategy); * * * @author Mike Meessen + * + * @phpstan-import-type Record from \Monolog\Logger + * @phpstan-import-type Level from \Monolog\Logger + * @phpstan-import-type LevelName from \Monolog\Logger */ class ChannelLevelActivationStrategy implements ActivationStrategyInterface { - private Level $defaultActionLevel; + /** + * @var Level + */ + private $defaultActionLevel; /** * @var array */ - private array $channelToActionLevel; + private $channelToActionLevel; /** - * @param int|string|Level|LogLevel::* $defaultActionLevel The default action level to be used if the record's category doesn't match any - * @param array $channelToActionLevel An array that maps channel names to action levels. + * @param int|string $defaultActionLevel The default action level to be used if the record's category doesn't match any + * @param array $channelToActionLevel An array that maps channel names to action levels. * - * @phpstan-param value-of|value-of|Level|LogLevel::* $defaultActionLevel - * @phpstan-param array|value-of|Level|LogLevel::*> $channelToActionLevel + * @phpstan-param array $channelToActionLevel + * @phpstan-param Level|LevelName|LogLevel::* $defaultActionLevel */ - public function __construct(int|string|Level $defaultActionLevel, array $channelToActionLevel = []) + public function __construct($defaultActionLevel, array $channelToActionLevel = []) { $this->defaultActionLevel = Logger::toMonologLevel($defaultActionLevel); - $this->channelToActionLevel = array_map(Logger::toMonologLevel(...), $channelToActionLevel); + $this->channelToActionLevel = array_map('Monolog\Logger::toMonologLevel', $channelToActionLevel); } - public function isHandlerActivated(LogRecord $record): bool + /** + * @phpstan-param Record $record + */ + public function isHandlerActivated(array $record): bool { - if (isset($this->channelToActionLevel[$record->channel])) { - return $record->level->value >= $this->channelToActionLevel[$record->channel]->value; + if (isset($this->channelToActionLevel[$record['channel']])) { + return $record['level'] >= $this->channelToActionLevel[$record['channel']]; } - return $record->level->value >= $this->defaultActionLevel->value; + return $record['level'] >= $this->defaultActionLevel; } } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.php index c3ca2967a..5ec88eab6 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.php @@ -11,8 +11,6 @@ namespace Monolog\Handler\FingersCrossed; -use Monolog\Level; -use Monolog\LogRecord; use Monolog\Logger; use Psr\Log\LogLevel; @@ -20,23 +18,29 @@ use Psr\Log\LogLevel; * Error level based activation strategy. * * @author Johannes M. Schmitt + * + * @phpstan-import-type Level from \Monolog\Logger + * @phpstan-import-type LevelName from \Monolog\Logger */ class ErrorLevelActivationStrategy implements ActivationStrategyInterface { - private Level $actionLevel; + /** + * @var Level + */ + private $actionLevel; /** - * @param int|string|Level $actionLevel Level or name or value + * @param int|string $actionLevel Level or name or value * - * @phpstan-param value-of|value-of|Level|LogLevel::* $actionLevel + * @phpstan-param Level|LevelName|LogLevel::* $actionLevel */ - public function __construct(int|string|Level $actionLevel) + public function __construct($actionLevel) { $this->actionLevel = Logger::toMonologLevel($actionLevel); } - public function isHandlerActivated(LogRecord $record): bool + public function isHandlerActivated(array $record): bool { - return $record->level->value >= $this->actionLevel->value; + return $record['level'] >= $this->actionLevel; } } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php index ce2a3a8e1..0627b4451 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php @@ -11,15 +11,12 @@ namespace Monolog\Handler; -use Closure; use Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy; use Monolog\Handler\FingersCrossed\ActivationStrategyInterface; -use Monolog\Level; use Monolog\Logger; use Monolog\ResettableInterface; use Monolog\Formatter\FormatterInterface; use Psr\Log\LogLevel; -use Monolog\LogRecord; /** * Buffers all records until a certain level is reached @@ -36,50 +33,55 @@ use Monolog\LogRecord; * Monolog\Handler\FingersCrossed\ namespace. * * @author Jordi Boggiano + * + * @phpstan-import-type Record from \Monolog\Logger + * @phpstan-import-type Level from \Monolog\Logger + * @phpstan-import-type LevelName from \Monolog\Logger */ class FingersCrossedHandler extends Handler implements ProcessableHandlerInterface, ResettableInterface, FormattableHandlerInterface { use ProcessableHandlerTrait; /** - * Handler or factory Closure($record, $this) - * - * @phpstan-var (Closure(LogRecord|null, HandlerInterface): HandlerInterface)|HandlerInterface + * @var callable|HandlerInterface + * @phpstan-var callable(?Record, HandlerInterface): HandlerInterface|HandlerInterface */ - protected Closure|HandlerInterface $handler; - - protected ActivationStrategyInterface $activationStrategy; - - protected bool $buffering = true; - - protected int $bufferSize; - - /** @var LogRecord[] */ - protected array $buffer = []; - - protected bool $stopBuffering; - - protected Level|null $passthruLevel = null; - - protected bool $bubble; + protected $handler; + /** @var ActivationStrategyInterface */ + protected $activationStrategy; + /** @var bool */ + protected $buffering = true; + /** @var int */ + protected $bufferSize; + /** @var Record[] */ + protected $buffer = []; + /** @var bool */ + protected $stopBuffering; + /** + * @var ?int + * @phpstan-var ?Level + */ + protected $passthruLevel; + /** @var bool */ + protected $bubble; /** - * @phpstan-param (Closure(LogRecord|null, HandlerInterface): HandlerInterface)|HandlerInterface $handler + * @psalm-param HandlerInterface|callable(?Record, HandlerInterface): HandlerInterface $handler * - * @param Closure|HandlerInterface $handler Handler or factory Closure($record|null, $fingersCrossedHandler). - * @param int|string|Level|LogLevel::* $activationStrategy Strategy which determines when this handler takes action, or a level name/value at which the handler is activated - * @param int $bufferSize How many entries should be buffered at most, beyond that the oldest items are removed from the buffer. - * @param bool $bubble Whether the messages that are handled can bubble up the stack or not - * @param bool $stopBuffering Whether the handler should stop buffering after being triggered (default true) - * @param int|string|Level|LogLevel::*|null $passthruLevel Minimum level to always flush to handler on close, even if strategy not triggered + * @param callable|HandlerInterface $handler Handler or factory callable($record|null, $fingersCrossedHandler). + * @param int|string|ActivationStrategyInterface $activationStrategy Strategy which determines when this handler takes action, or a level name/value at which the handler is activated + * @param int $bufferSize How many entries should be buffered at most, beyond that the oldest items are removed from the buffer. + * @param bool $bubble Whether the messages that are handled can bubble up the stack or not + * @param bool $stopBuffering Whether the handler should stop buffering after being triggered (default true) + * @param int|string $passthruLevel Minimum level to always flush to handler on close, even if strategy not triggered * - * @phpstan-param value-of|value-of|Level|LogLevel::*|ActivationStrategyInterface $activationStrategy - * @phpstan-param value-of|value-of|Level|LogLevel::* $passthruLevel + * @phpstan-param Level|LevelName|LogLevel::* $passthruLevel + * @phpstan-param Level|LevelName|LogLevel::*|ActivationStrategyInterface $activationStrategy */ - public function __construct(Closure|HandlerInterface $handler, int|string|Level|ActivationStrategyInterface $activationStrategy = null, int $bufferSize = 0, bool $bubble = true, bool $stopBuffering = true, int|string|Level|null $passthruLevel = null) + public function __construct($handler, $activationStrategy = null, int $bufferSize = 0, bool $bubble = true, bool $stopBuffering = true, $passthruLevel = null) { if (null === $activationStrategy) { - $activationStrategy = new ErrorLevelActivationStrategy(Level::Warning); + $activationStrategy = new ErrorLevelActivationStrategy(Logger::WARNING); } // convert simple int activationStrategy to an object @@ -96,12 +98,16 @@ class FingersCrossedHandler extends Handler implements ProcessableHandlerInterfa if ($passthruLevel !== null) { $this->passthruLevel = Logger::toMonologLevel($passthruLevel); } + + if (!$this->handler instanceof HandlerInterface && !is_callable($this->handler)) { + throw new \RuntimeException("The given handler (".json_encode($this->handler).") is not a callable nor a Monolog\Handler\HandlerInterface object"); + } } /** - * @inheritDoc + * {@inheritDoc} */ - public function isHandling(LogRecord $record): bool + public function isHandling(array $record): bool { return true; } @@ -120,11 +126,12 @@ class FingersCrossedHandler extends Handler implements ProcessableHandlerInterfa } /** - * @inheritDoc + * {@inheritDoc} */ - public function handle(LogRecord $record): bool + public function handle(array $record): bool { - if (\count($this->processors) > 0) { + if ($this->processors) { + /** @var Record $record */ $record = $this->processRecord($record); } @@ -144,7 +151,7 @@ class FingersCrossedHandler extends Handler implements ProcessableHandlerInterfa } /** - * @inheritDoc + * {@inheritDoc} */ public function close(): void { @@ -153,7 +160,7 @@ class FingersCrossedHandler extends Handler implements ProcessableHandlerInterfa $this->getHandler()->close(); } - public function reset(): void + public function reset() { $this->flushBuffer(); @@ -183,7 +190,7 @@ class FingersCrossedHandler extends Handler implements ProcessableHandlerInterfa if (null !== $this->passthruLevel) { $level = $this->passthruLevel; $this->buffer = array_filter($this->buffer, function ($record) use ($level) { - return $record->level >= $level; + return $record['level'] >= $level; }); if (count($this->buffer) > 0) { $this->getHandler(end($this->buffer))->handleBatch($this->buffer); @@ -197,23 +204,26 @@ class FingersCrossedHandler extends Handler implements ProcessableHandlerInterfa /** * Return the nested handler * - * If the handler was provided as a factory, this will trigger the handler's instantiation. + * If the handler was provided as a factory callable, this will trigger the handler's instantiation. + * + * @return HandlerInterface + * + * @phpstan-param Record $record */ - public function getHandler(LogRecord $record = null): HandlerInterface + public function getHandler(array $record = null) { if (!$this->handler instanceof HandlerInterface) { - $handler = ($this->handler)($record, $this); - if (!$handler instanceof HandlerInterface) { - throw new \RuntimeException("The factory Closure should return a HandlerInterface"); + $this->handler = ($this->handler)($record, $this); + if (!$this->handler instanceof HandlerInterface) { + throw new \RuntimeException("The factory callable should return a HandlerInterface"); } - $this->handler = $handler; } return $this->handler; } /** - * @inheritDoc + * {@inheritDoc} */ public function setFormatter(FormatterInterface $formatter): HandlerInterface { @@ -228,7 +238,7 @@ class FingersCrossedHandler extends Handler implements ProcessableHandlerInterfa } /** - * @inheritDoc + * {@inheritDoc} */ public function getFormatter(): FormatterInterface { diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FirePHPHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FirePHPHandler.php index 6b9e5103a..72718de63 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FirePHPHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FirePHPHandler.php @@ -13,12 +13,13 @@ namespace Monolog\Handler; use Monolog\Formatter\WildfireFormatter; use Monolog\Formatter\FormatterInterface; -use Monolog\LogRecord; /** * Simple FirePHP Handler (http://www.firephp.org/), which uses the Wildfire protocol. * * @author Eric Clemmons (@ericclemmons) + * + * @phpstan-import-type FormattedRecord from AbstractProcessingHandler */ class FirePHPHandler extends AbstractProcessingHandler { @@ -46,15 +47,18 @@ class FirePHPHandler extends AbstractProcessingHandler /** * Whether or not Wildfire vendor-specific headers have been generated & sent yet + * @var bool */ - protected static bool $initialized = false; + protected static $initialized = false; /** * Shared static message index between potentially multiple handlers + * @var int */ - protected static int $messageIndex = 1; + protected static $messageIndex = 1; - protected static bool $sendHeaders = true; + /** @var bool */ + protected static $sendHeaders = true; /** * Base header creation function used by init headers & record headers @@ -81,19 +85,21 @@ class FirePHPHandler extends AbstractProcessingHandler * @phpstan-return non-empty-array * * @see createHeader() + * + * @phpstan-param FormattedRecord $record */ - protected function createRecordHeader(LogRecord $record): array + protected function createRecordHeader(array $record): array { // Wildfire is extensible to support multiple protocols & plugins in a single request, // but we're not taking advantage of that (yet), so we're using "1" for simplicity's sake. return $this->createHeader( [1, 1, 1, self::$messageIndex++], - $record->formatted + $record['formatted'] ); } /** - * @inheritDoc + * {@inheritDoc} */ protected function getDefaultFormatter(): FormatterInterface { @@ -134,7 +140,7 @@ class FirePHPHandler extends AbstractProcessingHandler * @see sendHeader() * @see sendInitHeaders() */ - protected function write(LogRecord $record): void + protected function write(array $record): void { if (!self::$sendHeaders || !$this->isWebRequest()) { return; @@ -165,7 +171,7 @@ class FirePHPHandler extends AbstractProcessingHandler */ protected function headersAccepted(): bool { - if (isset($_SERVER['HTTP_USER_AGENT']) && 1 === preg_match('{\bFirePHP/\d+\.\d+\b}', $_SERVER['HTTP_USER_AGENT'])) { + if (!empty($_SERVER['HTTP_USER_AGENT']) && preg_match('{\bFirePHP/\d+\.\d+\b}', $_SERVER['HTTP_USER_AGENT'])) { return true; } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FleepHookHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FleepHookHandler.php index 9f44ba719..85c95b9d7 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FleepHookHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FleepHookHandler.php @@ -13,8 +13,7 @@ namespace Monolog\Handler; use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\LineFormatter; -use Monolog\Level; -use Monolog\LogRecord; +use Monolog\Logger; /** * Sends logs to Fleep.io using Webhook integrations @@ -23,6 +22,8 @@ use Monolog\LogRecord; * * @see https://fleep.io/integrations/webhooks/ Fleep Webhooks Documentation * @author Ando Roots + * + * @phpstan-import-type FormattedRecord from AbstractProcessingHandler */ class FleepHookHandler extends SocketHandler { @@ -33,7 +34,7 @@ class FleepHookHandler extends SocketHandler /** * @var string Webhook token (specifies the conversation where logs are sent) */ - protected string $token; + protected $token; /** * Construct a new Fleep.io Handler. @@ -41,12 +42,12 @@ class FleepHookHandler extends SocketHandler * For instructions on how to create a new web hook in your conversations * see https://fleep.io/integrations/webhooks/ * - * @param string $token Webhook token + * @param string $token Webhook token * @throws MissingExtensionException */ public function __construct( string $token, - $level = Level::Debug, + $level = Logger::DEBUG, bool $bubble = true, bool $persistent = false, float $timeout = 0.0, @@ -88,16 +89,16 @@ class FleepHookHandler extends SocketHandler /** * Handles a log record */ - public function write(LogRecord $record): void + public function write(array $record): void { parent::write($record); $this->closeSocket(); } /** - * @inheritDoc + * {@inheritDoc} */ - protected function generateDataStream(LogRecord $record): string + protected function generateDataStream(array $record): string { $content = $this->buildContent($record); @@ -120,11 +121,13 @@ class FleepHookHandler extends SocketHandler /** * Builds the body of API call + * + * @phpstan-param FormattedRecord $record */ - private function buildContent(LogRecord $record): string + private function buildContent(array $record): string { $dataArray = [ - 'message' => $record->formatted, + 'message' => $record['formatted'], ]; return http_build_query($dataArray); diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php index 135815485..5715d5800 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php @@ -11,11 +11,10 @@ namespace Monolog\Handler; -use Monolog\Level; +use Monolog\Logger; use Monolog\Utils; use Monolog\Formatter\FlowdockFormatter; use Monolog\Formatter\FormatterInterface; -use Monolog\LogRecord; /** * Sends notifications through the Flowdock push API @@ -27,17 +26,23 @@ use Monolog\LogRecord; * * @author Dominik Liebler * @see https://www.flowdock.com/api/push + * + * @phpstan-import-type FormattedRecord from AbstractProcessingHandler + * @deprecated Since 2.9.0 and 3.3.0, Flowdock was shutdown we will thus drop this handler in Monolog 4 */ class FlowdockHandler extends SocketHandler { - protected string $apiToken; + /** + * @var string + */ + protected $apiToken; /** * @throws MissingExtensionException if OpenSSL is missing */ public function __construct( string $apiToken, - $level = Level::Debug, + $level = Logger::DEBUG, bool $bubble = true, bool $persistent = false, float $timeout = 0.0, @@ -63,7 +68,7 @@ class FlowdockHandler extends SocketHandler } /** - * @inheritDoc + * {@inheritDoc} */ public function setFormatter(FormatterInterface $formatter): HandlerInterface { @@ -83,9 +88,9 @@ class FlowdockHandler extends SocketHandler } /** - * @inheritDoc + * {@inheritDoc} */ - protected function write(LogRecord $record): void + protected function write(array $record): void { parent::write($record); @@ -93,9 +98,9 @@ class FlowdockHandler extends SocketHandler } /** - * @inheritDoc + * {@inheritDoc} */ - protected function generateDataStream(LogRecord $record): string + protected function generateDataStream(array $record): string { $content = $this->buildContent($record); @@ -104,10 +109,12 @@ class FlowdockHandler extends SocketHandler /** * Builds the body of API call + * + * @phpstan-param FormattedRecord $record */ - private function buildContent(LogRecord $record): string + private function buildContent(array $record): string { - return Utils::jsonEncode($record->formatted); + return Utils::jsonEncode($record['formatted']['flowdock']); } /** diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FormattableHandlerInterface.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FormattableHandlerInterface.php index 72da59e1c..fc1693cd0 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FormattableHandlerInterface.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FormattableHandlerInterface.php @@ -23,12 +23,15 @@ interface FormattableHandlerInterface /** * Sets the formatter. * - * @return HandlerInterface self + * @param FormatterInterface $formatter + * @return HandlerInterface self */ public function setFormatter(FormatterInterface $formatter): HandlerInterface; /** * Gets the formatter. + * + * @return FormatterInterface */ public function getFormatter(): FormatterInterface; } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FormattableHandlerTrait.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FormattableHandlerTrait.php index c044e0786..b60bdce0e 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/FormattableHandlerTrait.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/FormattableHandlerTrait.php @@ -21,10 +21,13 @@ use Monolog\Formatter\LineFormatter; */ trait FormattableHandlerTrait { - protected FormatterInterface|null $formatter = null; + /** + * @var ?FormatterInterface + */ + protected $formatter; /** - * @inheritDoc + * {@inheritDoc} */ public function setFormatter(FormatterInterface $formatter): HandlerInterface { @@ -34,11 +37,11 @@ trait FormattableHandlerTrait } /** - * @inheritDoc + * {@inheritDoc} */ public function getFormatter(): FormatterInterface { - if (null === $this->formatter) { + if (!$this->formatter) { $this->formatter = $this->getDefaultFormatter(); } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/GelfHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/GelfHandler.php index ba5bb975d..4ff26c4cd 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/GelfHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/GelfHandler.php @@ -12,10 +12,9 @@ namespace Monolog\Handler; use Gelf\PublisherInterface; -use Monolog\Level; +use Monolog\Logger; use Monolog\Formatter\GelfMessageFormatter; use Monolog\Formatter\FormatterInterface; -use Monolog\LogRecord; /** * Handler to send messages to a Graylog2 (http://www.graylog2.org) server @@ -28,12 +27,12 @@ class GelfHandler extends AbstractProcessingHandler /** * @var PublisherInterface the publisher object that sends the message to the server */ - protected PublisherInterface $publisher; + protected $publisher; /** * @param PublisherInterface $publisher a gelf publisher object */ - public function __construct(PublisherInterface $publisher, int|string|Level $level = Level::Debug, bool $bubble = true) + public function __construct(PublisherInterface $publisher, $level = Logger::DEBUG, bool $bubble = true) { parent::__construct($level, $bubble); @@ -41,15 +40,15 @@ class GelfHandler extends AbstractProcessingHandler } /** - * @inheritDoc + * {@inheritDoc} */ - protected function write(LogRecord $record): void + protected function write(array $record): void { - $this->publisher->publish($record->formatted); + $this->publisher->publish($record['formatted']); } /** - * @inheritDoc + * {@inheritDoc} */ protected function getDefaultFormatter(): FormatterInterface { diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/GroupHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/GroupHandler.php index 7ab8bd973..3c9dc4b3b 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/GroupHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/GroupHandler.php @@ -13,20 +13,22 @@ namespace Monolog\Handler; use Monolog\Formatter\FormatterInterface; use Monolog\ResettableInterface; -use Monolog\LogRecord; /** * Forwards records to multiple handlers * * @author Lenar Lõhmus + * + * @phpstan-import-type Record from \Monolog\Logger */ class GroupHandler extends Handler implements ProcessableHandlerInterface, ResettableInterface { use ProcessableHandlerTrait; /** @var HandlerInterface[] */ - protected array $handlers; - protected bool $bubble; + protected $handlers; + /** @var bool */ + protected $bubble; /** * @param HandlerInterface[] $handlers Array of Handlers. @@ -45,9 +47,9 @@ class GroupHandler extends Handler implements ProcessableHandlerInterface, Reset } /** - * @inheritDoc + * {@inheritDoc} */ - public function isHandling(LogRecord $record): bool + public function isHandling(array $record): bool { foreach ($this->handlers as $handler) { if ($handler->isHandling($record)) { @@ -59,11 +61,12 @@ class GroupHandler extends Handler implements ProcessableHandlerInterface, Reset } /** - * @inheritDoc + * {@inheritDoc} */ - public function handle(LogRecord $record): bool + public function handle(array $record): bool { - if (\count($this->processors) > 0) { + if ($this->processors) { + /** @var Record $record */ $record = $this->processRecord($record); } @@ -75,15 +78,16 @@ class GroupHandler extends Handler implements ProcessableHandlerInterface, Reset } /** - * @inheritDoc + * {@inheritDoc} */ public function handleBatch(array $records): void { - if (\count($this->processors) > 0) { + if ($this->processors) { $processed = []; foreach ($records as $record) { $processed[] = $this->processRecord($record); } + /** @var Record[] $records */ $records = $processed; } @@ -92,7 +96,7 @@ class GroupHandler extends Handler implements ProcessableHandlerInterface, Reset } } - public function reset(): void + public function reset() { $this->resetProcessors(); @@ -113,7 +117,7 @@ class GroupHandler extends Handler implements ProcessableHandlerInterface, Reset } /** - * @inheritDoc + * {@inheritDoc} */ public function setFormatter(FormatterInterface $formatter): HandlerInterface { diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/Handler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/Handler.php index e89f969b8..34b4935dd 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/Handler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/Handler.php @@ -19,7 +19,7 @@ namespace Monolog\Handler; abstract class Handler implements HandlerInterface { /** - * @inheritDoc + * {@inheritDoc} */ public function handleBatch(array $records): void { @@ -29,7 +29,7 @@ abstract class Handler implements HandlerInterface } /** - * @inheritDoc + * {@inheritDoc} */ public function close(): void { diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/HandlerInterface.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/HandlerInterface.php index 83905c323..affcc51fc 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/HandlerInterface.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/HandlerInterface.php @@ -11,12 +11,13 @@ namespace Monolog\Handler; -use Monolog\LogRecord; - /** * Interface that all Monolog Handlers must implement * * @author Jordi Boggiano + * + * @phpstan-import-type Record from \Monolog\Logger + * @phpstan-import-type Level from \Monolog\Logger */ interface HandlerInterface { @@ -29,9 +30,13 @@ interface HandlerInterface * is no guarantee that handle() will not be called, and isHandling() might not be called * for a given record. * - * @param LogRecord $record Partial log record having only a level initialized + * @param array $record Partial log record containing only a level key + * + * @return bool + * + * @phpstan-param array{level: Level} $record */ - public function isHandling(LogRecord $record): bool; + public function isHandling(array $record): bool; /** * Handles a record. @@ -43,16 +48,20 @@ interface HandlerInterface * Unless the bubbling is interrupted (by returning true), the Logger class will keep on * calling further handlers in the stack with a given log record. * - * @param LogRecord $record The record to handle - * @return bool true means that this handler handled the record, and that bubbling is not permitted. - * false means the record was either not processed or that this handler allows bubbling. + * @param array $record The record to handle + * @return bool true means that this handler handled the record, and that bubbling is not permitted. + * false means the record was either not processed or that this handler allows bubbling. + * + * @phpstan-param Record $record */ - public function handle(LogRecord $record): bool; + public function handle(array $record): bool; /** * Handles a set of records at once. * - * @param array $records The records to handle + * @param array $records The records to handle (an array of record arrays) + * + * @phpstan-param Record[] $records */ public function handleBatch(array $records): void; diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/HandlerWrapper.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/HandlerWrapper.php index 541ec2541..d4351b9f9 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/HandlerWrapper.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/HandlerWrapper.php @@ -13,7 +13,6 @@ namespace Monolog\Handler; use Monolog\ResettableInterface; use Monolog\Formatter\FormatterInterface; -use Monolog\LogRecord; /** * This simple wrapper class can be used to extend handlers functionality. @@ -22,7 +21,7 @@ use Monolog\LogRecord; * * Inherit from this class and override handle() like this: * - * public function handle(LogRecord $record) + * public function handle(array $record) * { * if ($record meets certain conditions) { * return false; @@ -34,7 +33,10 @@ use Monolog\LogRecord; */ class HandlerWrapper implements HandlerInterface, ProcessableHandlerInterface, FormattableHandlerInterface, ResettableInterface { - protected HandlerInterface $handler; + /** + * @var HandlerInterface + */ + protected $handler; public function __construct(HandlerInterface $handler) { @@ -42,23 +44,23 @@ class HandlerWrapper implements HandlerInterface, ProcessableHandlerInterface, F } /** - * @inheritDoc + * {@inheritDoc} */ - public function isHandling(LogRecord $record): bool + public function isHandling(array $record): bool { return $this->handler->isHandling($record); } /** - * @inheritDoc + * {@inheritDoc} */ - public function handle(LogRecord $record): bool + public function handle(array $record): bool { return $this->handler->handle($record); } /** - * @inheritDoc + * {@inheritDoc} */ public function handleBatch(array $records): void { @@ -66,7 +68,7 @@ class HandlerWrapper implements HandlerInterface, ProcessableHandlerInterface, F } /** - * @inheritDoc + * {@inheritDoc} */ public function close(): void { @@ -74,7 +76,7 @@ class HandlerWrapper implements HandlerInterface, ProcessableHandlerInterface, F } /** - * @inheritDoc + * {@inheritDoc} */ public function pushProcessor(callable $callback): HandlerInterface { @@ -88,7 +90,7 @@ class HandlerWrapper implements HandlerInterface, ProcessableHandlerInterface, F } /** - * @inheritDoc + * {@inheritDoc} */ public function popProcessor(): callable { @@ -100,7 +102,7 @@ class HandlerWrapper implements HandlerInterface, ProcessableHandlerInterface, F } /** - * @inheritDoc + * {@inheritDoc} */ public function setFormatter(FormatterInterface $formatter): HandlerInterface { @@ -114,7 +116,7 @@ class HandlerWrapper implements HandlerInterface, ProcessableHandlerInterface, F } /** - * @inheritDoc + * {@inheritDoc} */ public function getFormatter(): FormatterInterface { @@ -125,7 +127,7 @@ class HandlerWrapper implements HandlerInterface, ProcessableHandlerInterface, F throw new \LogicException('The wrapped handler does not implement ' . FormattableHandlerInterface::class); } - public function reset(): void + public function reset() { if ($this->handler instanceof ResettableInterface) { $this->handler->reset(); diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/IFTTTHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/IFTTTHandler.php index ee7f81f6a..000ccea40 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/IFTTTHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/IFTTTHandler.php @@ -11,9 +11,8 @@ namespace Monolog\Handler; -use Monolog\Level; +use Monolog\Logger; use Monolog\Utils; -use Monolog\LogRecord; /** * IFTTTHandler uses cURL to trigger IFTTT Maker actions @@ -28,14 +27,16 @@ use Monolog\LogRecord; */ class IFTTTHandler extends AbstractProcessingHandler { - private string $eventName; - private string $secretKey; + /** @var string */ + private $eventName; + /** @var string */ + private $secretKey; /** * @param string $eventName The name of the IFTTT Maker event that should be triggered * @param string $secretKey A valid IFTTT secret key */ - public function __construct(string $eventName, string $secretKey, int|string|Level $level = Level::Error, bool $bubble = true) + public function __construct(string $eventName, string $secretKey, $level = Logger::ERROR, bool $bubble = true) { if (!extension_loaded('curl')) { throw new MissingExtensionException('The curl extension is needed to use the IFTTTHandler'); @@ -48,14 +49,14 @@ class IFTTTHandler extends AbstractProcessingHandler } /** - * @inheritDoc + * {@inheritDoc} */ - public function write(LogRecord $record): void + public function write(array $record): void { $postData = [ - "value1" => $record->channel, + "value1" => $record["channel"], "value2" => $record["level_name"], - "value3" => $record->message, + "value3" => $record["message"], ]; $postString = Utils::jsonEncode($postData); diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/InsightOpsHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/InsightOpsHandler.php index abb2f88f7..71f64a267 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/InsightOpsHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/InsightOpsHandler.php @@ -11,8 +11,7 @@ namespace Monolog\Handler; -use Monolog\Level; -use Monolog\LogRecord; +use Monolog\Logger; /** * Inspired on LogEntriesHandler. @@ -22,12 +21,15 @@ use Monolog\LogRecord; */ class InsightOpsHandler extends SocketHandler { - protected string $logToken; + /** + * @var string + */ + protected $logToken; /** - * @param string $token Log token supplied by InsightOps - * @param string $region Region where InsightOps account is hosted. Could be 'us' or 'eu'. - * @param bool $useSSL Whether or not SSL encryption should be used + * @param string $token Log token supplied by InsightOps + * @param string $region Region where InsightOps account is hosted. Could be 'us' or 'eu'. + * @param bool $useSSL Whether or not SSL encryption should be used * * @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing */ @@ -35,7 +37,7 @@ class InsightOpsHandler extends SocketHandler string $token, string $region = 'us', bool $useSSL = true, - $level = Level::Debug, + $level = Logger::DEBUG, bool $bubble = true, bool $persistent = false, float $timeout = 0.0, @@ -65,10 +67,10 @@ class InsightOpsHandler extends SocketHandler } /** - * @inheritDoc + * {@inheritDoc} */ - protected function generateDataStream(LogRecord $record): string + protected function generateDataStream(array $record): string { - return $this->logToken . ' ' . $record->formatted; + return $this->logToken . ' ' . $record['formatted']; } } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php index 00259834e..25fcd1594 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php @@ -11,27 +11,29 @@ namespace Monolog\Handler; -use Monolog\Level; -use Monolog\LogRecord; +use Monolog\Logger; /** * @author Robert Kaufmann III */ class LogEntriesHandler extends SocketHandler { - protected string $logToken; + /** + * @var string + */ + protected $logToken; /** - * @param string $token Log token supplied by LogEntries - * @param bool $useSSL Whether or not SSL encryption should be used. - * @param string $host Custom hostname to send the data to if needed + * @param string $token Log token supplied by LogEntries + * @param bool $useSSL Whether or not SSL encryption should be used. + * @param string $host Custom hostname to send the data to if needed * * @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing */ public function __construct( string $token, bool $useSSL = true, - $level = Level::Debug, + $level = Logger::DEBUG, bool $bubble = true, string $host = 'data.logentries.com', bool $persistent = false, @@ -59,10 +61,10 @@ class LogEntriesHandler extends SocketHandler } /** - * @inheritDoc + * {@inheritDoc} */ - protected function generateDataStream(LogRecord $record): string + protected function generateDataStream(array $record): string { - return $this->logToken . ' ' . $record->formatted; + return $this->logToken . ' ' . $record['formatted']; } } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/LogglyHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/LogglyHandler.php index 2d8e66f18..6d13db375 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/LogglyHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/LogglyHandler.php @@ -11,12 +11,11 @@ namespace Monolog\Handler; -use Monolog\Level; +use Monolog\Logger; use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\LogglyFormatter; use function array_key_exists; use CurlHandle; -use Monolog\LogRecord; /** * Sends errors to Loggly. @@ -34,21 +33,22 @@ class LogglyHandler extends AbstractProcessingHandler /** * Caches the curl handlers for every given endpoint. * - * @var CurlHandle[] + * @var resource[]|CurlHandle[] */ - protected array $curlHandlers = []; + protected $curlHandlers = []; - protected string $token; + /** @var string */ + protected $token; /** @var string[] */ - protected array $tag = []; + protected $tag = []; /** * @param string $token API token supplied by Loggly * * @throws MissingExtensionException If the curl extension is missing */ - public function __construct(string $token, int|string|Level $level = Level::Debug, bool $bubble = true) + public function __construct(string $token, $level = Logger::DEBUG, bool $bubble = true) { if (!extension_loaded('curl')) { throw new MissingExtensionException('The curl extension is needed to use the LogglyHandler'); @@ -61,8 +61,12 @@ class LogglyHandler extends AbstractProcessingHandler /** * Loads and returns the shared curl handler for the given endpoint. + * + * @param string $endpoint + * + * @return resource|CurlHandle */ - protected function getCurlHandler(string $endpoint): CurlHandle + protected function getCurlHandler(string $endpoint) { if (!array_key_exists($endpoint, $this->curlHandlers)) { $this->curlHandlers[$endpoint] = $this->loadCurlHandle($endpoint); @@ -73,8 +77,12 @@ class LogglyHandler extends AbstractProcessingHandler /** * Starts a fresh curl session for the given endpoint and returns its handler. + * + * @param string $endpoint + * + * @return resource|CurlHandle */ - private function loadCurlHandle(string $endpoint): CurlHandle + private function loadCurlHandle(string $endpoint) { $url = sprintf("https://%s/%s/%s/", static::HOST, $endpoint, $this->token); @@ -90,13 +98,10 @@ class LogglyHandler extends AbstractProcessingHandler /** * @param string[]|string $tag */ - public function setTag(string|array $tag): self + public function setTag($tag): self { - if ('' === $tag || [] === $tag) { - $this->tag = []; - } else { - $this->tag = is_array($tag) ? $tag : [$tag]; - } + $tag = !empty($tag) ? $tag : []; + $this->tag = is_array($tag) ? $tag : [$tag]; return $this; } @@ -104,9 +109,9 @@ class LogglyHandler extends AbstractProcessingHandler /** * @param string[]|string $tag */ - public function addTag(string|array $tag): self + public function addTag($tag): self { - if ('' !== $tag) { + if (!empty($tag)) { $tag = is_array($tag) ? $tag : [$tag]; $this->tag = array_unique(array_merge($this->tag, $tag)); } @@ -114,9 +119,9 @@ class LogglyHandler extends AbstractProcessingHandler return $this; } - protected function write(LogRecord $record): void + protected function write(array $record): void { - $this->send($record->formatted, static::ENDPOINT_SINGLE); + $this->send($record["formatted"], static::ENDPOINT_SINGLE); } public function handleBatch(array $records): void @@ -124,10 +129,10 @@ class LogglyHandler extends AbstractProcessingHandler $level = $this->level; $records = array_filter($records, function ($record) use ($level) { - return ($record->level >= $level); + return ($record['level'] >= $level); }); - if (\count($records) > 0) { + if ($records) { $this->send($this->getFormatter()->formatBatch($records), static::ENDPOINT_BATCH); } } @@ -138,7 +143,7 @@ class LogglyHandler extends AbstractProcessingHandler $headers = ['Content-Type: application/json']; - if (\count($this->tag) > 0) { + if (!empty($this->tag)) { $headers[] = 'X-LOGGLY-TAG: '.implode(',', $this->tag); } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/LogmaticHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/LogmaticHandler.php index 876b1a953..859a46906 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/LogmaticHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/LogmaticHandler.php @@ -11,36 +11,44 @@ namespace Monolog\Handler; -use Monolog\Level; +use Monolog\Logger; use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\LogmaticFormatter; -use Monolog\LogRecord; /** * @author Julien Breux */ class LogmaticHandler extends SocketHandler { - private string $logToken; - - private string $hostname; - - private string $appName; + /** + * @var string + */ + private $logToken; /** - * @param string $token Log token supplied by Logmatic. - * @param string $hostname Host name supplied by Logmatic. - * @param string $appName Application name supplied by Logmatic. - * @param bool $useSSL Whether or not SSL encryption should be used. + * @var string + */ + private $hostname; + + /** + * @var string + */ + private $appname; + + /** + * @param string $token Log token supplied by Logmatic. + * @param string $hostname Host name supplied by Logmatic. + * @param string $appname Application name supplied by Logmatic. + * @param bool $useSSL Whether or not SSL encryption should be used. * * @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing */ public function __construct( string $token, string $hostname = '', - string $appName = '', + string $appname = '', bool $useSSL = true, - $level = Level::Debug, + $level = Logger::DEBUG, bool $bubble = true, bool $persistent = false, float $timeout = 0.0, @@ -68,29 +76,29 @@ class LogmaticHandler extends SocketHandler $this->logToken = $token; $this->hostname = $hostname; - $this->appName = $appName; + $this->appname = $appname; } /** - * @inheritDoc + * {@inheritDoc} */ - protected function generateDataStream(LogRecord $record): string + protected function generateDataStream(array $record): string { - return $this->logToken . ' ' . $record->formatted; + return $this->logToken . ' ' . $record['formatted']; } /** - * @inheritDoc + * {@inheritDoc} */ protected function getDefaultFormatter(): FormatterInterface { $formatter = new LogmaticFormatter(); - if ($this->hostname !== '') { + if (!empty($this->hostname)) { $formatter->setHostname($this->hostname); } - if ($this->appName !== '') { - $formatter->setAppName($this->appName); + if (!empty($this->appname)) { + $formatter->setAppname($this->appname); } return $formatter; diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/MailHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/MailHandler.php index b6c822772..97f343202 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/MailHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/MailHandler.php @@ -13,32 +13,33 @@ namespace Monolog\Handler; use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\HtmlFormatter; -use Monolog\LogRecord; /** * Base class for all mail handlers * * @author Gyula Sallai + * + * @phpstan-import-type Record from \Monolog\Logger */ abstract class MailHandler extends AbstractProcessingHandler { /** - * @inheritDoc + * {@inheritDoc} */ public function handleBatch(array $records): void { $messages = []; foreach ($records as $record) { - if ($record->level->isLowerThan($this->level)) { + if ($record['level'] < $this->level) { continue; } - + /** @var Record $message */ $message = $this->processRecord($record); $messages[] = $message; } - if (\count($messages) > 0) { + if (!empty($messages)) { $this->send((string) $this->getFormatter()->formatBatch($messages), $messages); } } @@ -49,26 +50,27 @@ abstract class MailHandler extends AbstractProcessingHandler * @param string $content formatted email body to be sent * @param array $records the array of log records that formed this content * - * @phpstan-param non-empty-array $records + * @phpstan-param Record[] $records */ abstract protected function send(string $content, array $records): void; /** - * @inheritDoc + * {@inheritDoc} */ - protected function write(LogRecord $record): void + protected function write(array $record): void { - $this->send((string) $record->formatted, [$record]); + $this->send((string) $record['formatted'], [$record]); } /** - * @phpstan-param non-empty-array $records + * @phpstan-param non-empty-array $records + * @phpstan-return Record */ - protected function getHighestRecord(array $records): LogRecord + protected function getHighestRecord(array $records): array { $highestRecord = null; foreach ($records as $record) { - if ($highestRecord === null || $record->level->isHigherThan($highestRecord->level)) { + if ($highestRecord === null || $highestRecord['level'] < $record['level']) { $highestRecord = $record; } } @@ -83,6 +85,8 @@ abstract class MailHandler extends AbstractProcessingHandler /** * Gets the default formatter. + * + * @return FormatterInterface */ protected function getDefaultFormatter(): FormatterInterface { diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/MandrillHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/MandrillHandler.php index 0f923bc52..3003500ec 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/MandrillHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/MandrillHandler.php @@ -11,7 +11,7 @@ namespace Monolog\Handler; -use Monolog\Level; +use Monolog\Logger; use Swift; use Swift_Message; @@ -22,20 +22,22 @@ use Swift_Message; */ class MandrillHandler extends MailHandler { - protected Swift_Message $message; - protected string $apiKey; + /** @var Swift_Message */ + protected $message; + /** @var string */ + protected $apiKey; /** - * @phpstan-param (Swift_Message|callable(): Swift_Message) $message + * @psalm-param Swift_Message|callable(): Swift_Message $message * * @param string $apiKey A valid Mandrill API key * @param callable|Swift_Message $message An example message for real messages, only the body will be replaced */ - public function __construct(string $apiKey, callable|Swift_Message $message, int|string|Level $level = Level::Error, bool $bubble = true) + public function __construct(string $apiKey, $message, $level = Logger::ERROR, bool $bubble = true) { parent::__construct($level, $bubble); - if (!$message instanceof Swift_Message) { + if (!$message instanceof Swift_Message && is_callable($message)) { $message = $message(); } if (!$message instanceof Swift_Message) { @@ -46,7 +48,7 @@ class MandrillHandler extends MailHandler } /** - * @inheritDoc + * {@inheritDoc} */ protected function send(string $content, array $records): void { diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/MongoDBHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/MongoDBHandler.php index 33ab68c6d..306309119 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/MongoDBHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/MongoDBHandler.php @@ -14,10 +14,9 @@ namespace Monolog\Handler; use MongoDB\Driver\BulkWrite; use MongoDB\Driver\Manager; use MongoDB\Client; -use Monolog\Level; +use Monolog\Logger; use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\MongoDBFormatter; -use Monolog\LogRecord; /** * Logs to a MongoDB database. @@ -34,11 +33,12 @@ use Monolog\LogRecord; */ class MongoDBHandler extends AbstractProcessingHandler { - private \MongoDB\Collection $collection; - - private Client|Manager $manager; - - private string|null $namespace = null; + /** @var \MongoDB\Collection */ + private $collection; + /** @var Client|Manager */ + private $manager; + /** @var string */ + private $namespace; /** * Constructor. @@ -47,8 +47,12 @@ class MongoDBHandler extends AbstractProcessingHandler * @param string $database Database name * @param string $collection Collection name */ - public function __construct(Client|Manager $mongodb, string $database, string $collection, int|string|Level $level = Level::Debug, bool $bubble = true) + public function __construct($mongodb, string $database, string $collection, $level = Logger::DEBUG, bool $bubble = true) { + if (!($mongodb instanceof Client || $mongodb instanceof Manager)) { + throw new \InvalidArgumentException('MongoDB\Client or MongoDB\Driver\Manager instance required'); + } + if ($mongodb instanceof Client) { $this->collection = $mongodb->selectCollection($database, $collection); } else { @@ -59,21 +63,21 @@ class MongoDBHandler extends AbstractProcessingHandler parent::__construct($level, $bubble); } - protected function write(LogRecord $record): void + protected function write(array $record): void { if (isset($this->collection)) { - $this->collection->insertOne($record->formatted); + $this->collection->insertOne($record['formatted']); } if (isset($this->manager, $this->namespace)) { $bulk = new BulkWrite; - $bulk->insert($record->formatted); + $bulk->insert($record["formatted"]); $this->manager->executeBulkWrite($this->namespace, $bulk); } } /** - * @inheritDoc + * {@inheritDoc} */ protected function getDefaultFormatter(): FormatterInterface { diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php index d4c9d8010..0c0a3bdb1 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php @@ -11,7 +11,7 @@ namespace Monolog\Handler; -use Monolog\Level; +use Monolog\Logger; use Monolog\Formatter\LineFormatter; /** @@ -26,39 +26,43 @@ class NativeMailerHandler extends MailHandler * The email addresses to which the message will be sent * @var string[] */ - protected array $to; + protected $to; /** * The subject of the email + * @var string */ - protected string $subject; + protected $subject; /** * Optional headers for the message * @var string[] */ - protected array $headers = []; + protected $headers = []; /** * Optional parameters for the message * @var string[] */ - protected array $parameters = []; + protected $parameters = []; /** * The wordwrap length for the message + * @var int */ - protected int $maxColumnWidth; + protected $maxColumnWidth; /** * The Content-type for the message + * @var string|null */ - protected string|null $contentType = null; + protected $contentType; /** * The encoding for the message + * @var string */ - protected string $encoding = 'utf-8'; + protected $encoding = 'utf-8'; /** * @param string|string[] $to The receiver of the mail @@ -66,7 +70,7 @@ class NativeMailerHandler extends MailHandler * @param string $from The sender of the mail * @param int $maxColumnWidth The maximum column width that the message lines will have */ - public function __construct(string|array $to, string $subject, string $from, int|string|Level $level = Level::Error, bool $bubble = true, int $maxColumnWidth = 70) + public function __construct($to, string $subject, string $from, $level = Logger::ERROR, bool $bubble = true, int $maxColumnWidth = 70) { parent::__construct($level, $bubble); $this->to = (array) $to; @@ -105,11 +109,11 @@ class NativeMailerHandler extends MailHandler } /** - * @inheritDoc + * {@inheritDoc} */ protected function send(string $content, array $records): void { - $contentType = $this->getContentType() ?? ($this->isHtmlBody($content) ? 'text/html' : 'text/plain'); + $contentType = $this->getContentType() ?: ($this->isHtmlBody($content) ? 'text/html' : 'text/plain'); if ($contentType !== 'text/html') { $content = wordwrap($content, $this->maxColumnWidth); @@ -121,8 +125,11 @@ class NativeMailerHandler extends MailHandler $headers .= 'MIME-Version: 1.0' . "\r\n"; } - $subjectFormatter = new LineFormatter($this->subject); - $subject = $subjectFormatter->format($this->getHighestRecord($records)); + $subject = $this->subject; + if ($records) { + $subjectFormatter = new LineFormatter($this->subject); + $subject = $subjectFormatter->format($this->getHighestRecord($records)); + } $parameters = implode(' ', $this->parameters); foreach ($this->to as $to) { diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php index b8cb3785b..114d749eb 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php @@ -11,17 +11,16 @@ namespace Monolog\Handler; -use Monolog\Level; +use Monolog\Logger; use Monolog\Utils; use Monolog\Formatter\NormalizerFormatter; use Monolog\Formatter\FormatterInterface; -use Monolog\LogRecord; /** * Class to record a log on a NewRelic application. * Enabling New Relic High Security mode may prevent capture of useful information. * - * This handler requires a NormalizerFormatter to function and expects an array in $record->formatted + * This handler requires a NormalizerFormatter to function and expects an array in $record['formatted'] * * @see https://docs.newrelic.com/docs/agents/php-agent * @see https://docs.newrelic.com/docs/accounts-partnerships/accounts/security/high-security @@ -29,58 +28,75 @@ use Monolog\LogRecord; class NewRelicHandler extends AbstractProcessingHandler { /** - * @inheritDoc + * Name of the New Relic application that will receive logs from this handler. + * + * @var ?string + */ + protected $appName; + + /** + * Name of the current transaction + * + * @var ?string + */ + protected $transactionName; + + /** + * Some context and extra data is passed into the handler as arrays of values. Do we send them as is + * (useful if we are using the API), or explode them for display on the NewRelic RPM website? + * + * @var bool + */ + protected $explodeArrays; + + /** + * {@inheritDoc} + * + * @param string|null $appName + * @param bool $explodeArrays + * @param string|null $transactionName */ public function __construct( - int|string|Level $level = Level::Error, + $level = Logger::ERROR, bool $bubble = true, - - /** - * Name of the New Relic application that will receive logs from this handler. - */ - protected string|null $appName = null, - - /** - * Some context and extra data is passed into the handler as arrays of values. Do we send them as is - * (useful if we are using the API), or explode them for display on the NewRelic RPM website? - */ - protected bool $explodeArrays = false, - - /** - * Name of the current transaction - */ - protected string|null $transactionName = null + ?string $appName = null, + bool $explodeArrays = false, + ?string $transactionName = null ) { parent::__construct($level, $bubble); + + $this->appName = $appName; + $this->explodeArrays = $explodeArrays; + $this->transactionName = $transactionName; } /** - * @inheritDoc + * {@inheritDoc} */ - protected function write(LogRecord $record): void + protected function write(array $record): void { if (!$this->isNewRelicEnabled()) { throw new MissingExtensionException('The newrelic PHP extension is required to use the NewRelicHandler'); } - if (null !== ($appName = $this->getAppName($record->context))) { + if ($appName = $this->getAppName($record['context'])) { $this->setNewRelicAppName($appName); } - if (null !== ($transactionName = $this->getTransactionName($record->context))) { + if ($transactionName = $this->getTransactionName($record['context'])) { $this->setNewRelicTransactionName($transactionName); - unset($record->formatted['context']['transaction_name']); + unset($record['formatted']['context']['transaction_name']); } - if (isset($record->context['exception']) && $record->context['exception'] instanceof \Throwable) { - newrelic_notice_error($record->message, $record->context['exception']); - unset($record->formatted['context']['exception']); + if (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Throwable) { + newrelic_notice_error($record['message'], $record['context']['exception']); + unset($record['formatted']['context']['exception']); } else { - newrelic_notice_error($record->message); + newrelic_notice_error($record['message']); } - if (isset($record->formatted['context']) && is_array($record->formatted['context'])) { - foreach ($record->formatted['context'] as $key => $parameter) { + if (isset($record['formatted']['context']) && is_array($record['formatted']['context'])) { + foreach ($record['formatted']['context'] as $key => $parameter) { if (is_array($parameter) && $this->explodeArrays) { foreach ($parameter as $paramKey => $paramValue) { $this->setNewRelicParameter('context_' . $key . '_' . $paramKey, $paramValue); @@ -91,8 +107,8 @@ class NewRelicHandler extends AbstractProcessingHandler } } - if (isset($record->formatted['extra']) && is_array($record->formatted['extra'])) { - foreach ($record->formatted['extra'] as $key => $parameter) { + if (isset($record['formatted']['extra']) && is_array($record['formatted']['extra'])) { + foreach ($record['formatted']['extra'] as $key => $parameter) { if (is_array($parameter) && $this->explodeArrays) { foreach ($parameter as $paramKey => $paramValue) { $this->setNewRelicParameter('extra_' . $key . '_' . $paramKey, $paramValue); @@ -106,6 +122,8 @@ class NewRelicHandler extends AbstractProcessingHandler /** * Checks whether the NewRelic extension is enabled in the system. + * + * @return bool */ protected function isNewRelicEnabled(): bool { @@ -159,7 +177,8 @@ class NewRelicHandler extends AbstractProcessingHandler } /** - * @param mixed $value + * @param string $key + * @param mixed $value */ protected function setNewRelicParameter(string $key, $value): void { @@ -171,7 +190,7 @@ class NewRelicHandler extends AbstractProcessingHandler } /** - * @inheritDoc + * {@inheritDoc} */ protected function getDefaultFormatter(): FormatterInterface { diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/NoopHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/NoopHandler.php index d9fea180c..1ddf0beb9 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/NoopHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/NoopHandler.php @@ -11,8 +11,6 @@ namespace Monolog\Handler; -use Monolog\LogRecord; - /** * No-op * @@ -25,17 +23,17 @@ use Monolog\LogRecord; class NoopHandler extends Handler { /** - * @inheritDoc + * {@inheritDoc} */ - public function isHandling(LogRecord $record): bool + public function isHandling(array $record): bool { return true; } /** - * @inheritDoc + * {@inheritDoc} */ - public function handle(LogRecord $record): bool + public function handle(array $record): bool { return false; } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/NullHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/NullHandler.php index 1aa84e4f8..e75ee0c6e 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/NullHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/NullHandler.php @@ -11,10 +11,8 @@ namespace Monolog\Handler; -use Monolog\Level; -use Psr\Log\LogLevel; use Monolog\Logger; -use Monolog\LogRecord; +use Psr\Log\LogLevel; /** * Blackhole @@ -23,34 +21,40 @@ use Monolog\LogRecord; * to put on top of an existing stack to override it temporarily. * * @author Jordi Boggiano + * + * @phpstan-import-type Level from \Monolog\Logger + * @phpstan-import-type LevelName from \Monolog\Logger */ class NullHandler extends Handler { - private Level $level; + /** + * @var int + */ + private $level; /** - * @param string|int|Level $level The minimum logging level at which this handler will be triggered + * @param string|int $level The minimum logging level at which this handler will be triggered * - * @phpstan-param value-of|value-of|Level|LogLevel::* $level + * @phpstan-param Level|LevelName|LogLevel::* $level */ - public function __construct(string|int|Level $level = Level::Debug) + public function __construct($level = Logger::DEBUG) { $this->level = Logger::toMonologLevel($level); } /** - * @inheritDoc + * {@inheritDoc} */ - public function isHandling(LogRecord $record): bool + public function isHandling(array $record): bool { - return $record->level->value >= $this->level->value; + return $record['level'] >= $this->level; } /** - * @inheritDoc + * {@inheritDoc} */ - public function handle(LogRecord $record): bool + public function handle(array $record): bool { - return $record->level->value >= $this->level->value; + return $record['level'] >= $this->level; } } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/OverflowHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/OverflowHandler.php index a72b7a11d..22068c9a3 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/OverflowHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/OverflowHandler.php @@ -11,9 +11,8 @@ namespace Monolog\Handler; -use Monolog\Level; +use Monolog\Logger; use Monolog\Formatter\FormatterInterface; -use Monolog\LogRecord; /** * Handler to only pass log messages when a certain threshold of number of messages is reached. @@ -28,7 +27,7 @@ use Monolog\LogRecord; * $handler = new SomeHandler(...) * * // Pass all warnings to the handler when more than 10 & all error messages when more then 5 - * $overflow = new OverflowHandler($handler, [Level::Warning->value => 10, Level::Error->value => 5]); + * $overflow = new OverflowHandler($handler, [Logger::WARNING => 10, Logger::ERROR => 5]); * * $log->pushHandler($overflow); *``` @@ -37,25 +36,36 @@ use Monolog\LogRecord; */ class OverflowHandler extends AbstractHandler implements FormattableHandlerInterface { - private HandlerInterface $handler; + /** @var HandlerInterface */ + private $handler; - /** @var array */ - private array $thresholdMap = []; + /** @var int[] */ + private $thresholdMap = [ + Logger::DEBUG => 0, + Logger::INFO => 0, + Logger::NOTICE => 0, + Logger::WARNING => 0, + Logger::ERROR => 0, + Logger::CRITICAL => 0, + Logger::ALERT => 0, + Logger::EMERGENCY => 0, + ]; /** * Buffer of all messages passed to the handler before the threshold was reached * * @var mixed[][] */ - private array $buffer = []; + private $buffer = []; /** - * @param array $thresholdMap Dictionary of log level value => threshold + * @param HandlerInterface $handler + * @param int[] $thresholdMap Dictionary of logger level => threshold */ public function __construct( HandlerInterface $handler, array $thresholdMap = [], - $level = Level::Debug, + $level = Logger::DEBUG, bool $bubble = true ) { $this->handler = $handler; @@ -75,15 +85,15 @@ class OverflowHandler extends AbstractHandler implements FormattableHandlerInter * Unless the bubbling is interrupted (by returning true), the Logger class will keep on * calling further handlers in the stack with a given log record. * - * @inheritDoc + * {@inheritDoc} */ - public function handle(LogRecord $record): bool + public function handle(array $record): bool { - if ($record->level->isLowerThan($this->level)) { + if ($record['level'] < $this->level) { return false; } - $level = $record->level->value; + $level = $record['level']; if (!isset($this->thresholdMap[$level])) { $this->thresholdMap[$level] = 0; @@ -112,7 +122,7 @@ class OverflowHandler extends AbstractHandler implements FormattableHandlerInter } /** - * @inheritDoc + * {@inheritDoc} */ public function setFormatter(FormatterInterface $formatter): HandlerInterface { @@ -126,7 +136,7 @@ class OverflowHandler extends AbstractHandler implements FormattableHandlerInter } /** - * @inheritDoc + * {@inheritDoc} */ public function getFormatter(): FormatterInterface { diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.php index 8aa78e4c4..23a1d1178 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.php @@ -13,13 +13,11 @@ namespace Monolog\Handler; use Monolog\Formatter\LineFormatter; use Monolog\Formatter\FormatterInterface; -use Monolog\Level; +use Monolog\Logger; use Monolog\Utils; use PhpConsole\Connector; use PhpConsole\Handler as VendorPhpConsoleHandler; use PhpConsole\Helper; -use Monolog\LogRecord; -use PhpConsole\Storage; /** * Monolog handler for Google Chrome extension "PHP Console" @@ -39,59 +37,14 @@ use PhpConsole\Storage; * PC::debug($_SERVER); // PHP Console debugger for any type of vars * * @author Sergey Barbushin https://www.linkedin.com/in/barbushin - * @phpstan-type Options array{ - * enabled: bool, - * classesPartialsTraceIgnore: string[], - * debugTagsKeysInContext: array, - * useOwnErrorsHandler: bool, - * useOwnExceptionsHandler: bool, - * sourcesBasePath: string|null, - * registerHelper: bool, - * serverEncoding: string|null, - * headersLimit: int|null, - * password: string|null, - * enableSslOnlyMode: bool, - * ipMasks: string[], - * enableEvalListener: bool, - * dumperDetectCallbacks: bool, - * dumperLevelLimit: int, - * dumperItemsCountLimit: int, - * dumperItemSizeLimit: int, - * dumperDumpSizeLimit: int, - * detectDumpTraceAndSource: bool, - * dataStorage: Storage|null - * } - * @phpstan-type InputOptions array{ - * enabled?: bool, - * classesPartialsTraceIgnore?: string[], - * debugTagsKeysInContext?: array, - * useOwnErrorsHandler?: bool, - * useOwnExceptionsHandler?: bool, - * sourcesBasePath?: string|null, - * registerHelper?: bool, - * serverEncoding?: string|null, - * headersLimit?: int|null, - * password?: string|null, - * enableSslOnlyMode?: bool, - * ipMasks?: string[], - * enableEvalListener?: bool, - * dumperDetectCallbacks?: bool, - * dumperLevelLimit?: int, - * dumperItemsCountLimit?: int, - * dumperItemSizeLimit?: int, - * dumperDumpSizeLimit?: int, - * detectDumpTraceAndSource?: bool, - * dataStorage?: Storage|null - * } * + * @phpstan-import-type Record from \Monolog\Logger * @deprecated Since 2.8.0 and 3.2.0, PHPConsole is abandoned and thus we will drop this handler in Monolog 4 */ class PHPConsoleHandler extends AbstractProcessingHandler { - /** - * @phpstan-var Options - */ - private array $options = [ + /** @var array */ + private $options = [ 'enabled' => true, // bool Is PHP Console server enabled 'classesPartialsTraceIgnore' => ['Monolog\\'], // array Hide calls of classes started with... 'debugTagsKeysInContext' => [0, 'tag'], // bool Is PHP Console server enabled @@ -114,15 +67,15 @@ class PHPConsoleHandler extends AbstractProcessingHandler 'dataStorage' => null, // \PhpConsole\Storage|null Fixes problem with custom $_SESSION handler(see http://goo.gl/Ne8juJ) ]; - private Connector $connector; + /** @var Connector */ + private $connector; /** * @param array $options See \Monolog\Handler\PHPConsoleHandler::$options for more details * @param Connector|null $connector Instance of \PhpConsole\Connector class (optional) * @throws \RuntimeException - * @phpstan-param InputOptions $options */ - public function __construct(array $options = [], ?Connector $connector = null, int|string|Level $level = Level::Debug, bool $bubble = true) + public function __construct(array $options = [], ?Connector $connector = null, $level = Logger::DEBUG, bool $bubble = true) { if (!class_exists('PhpConsole\Connector')) { throw new \RuntimeException('PHP Console library not found. See https://github.com/barbushin/php-console#installation'); @@ -133,16 +86,14 @@ class PHPConsoleHandler extends AbstractProcessingHandler } /** - * @param array $options - * @return array + * @param array $options * - * @phpstan-param InputOptions $options - * @phpstan-return Options + * @return array */ private function initOptions(array $options): array { $wrongOptions = array_diff(array_keys($options), array_keys($this->options)); - if (\count($wrongOptions) > 0) { + if ($wrongOptions) { throw new \RuntimeException('Unknown options: ' . implode(', ', $wrongOptions)); } @@ -151,8 +102,8 @@ class PHPConsoleHandler extends AbstractProcessingHandler private function initConnector(?Connector $connector = null): Connector { - if (null === $connector) { - if ($this->options['dataStorage'] instanceof Storage) { + if (!$connector) { + if ($this->options['dataStorage']) { Connector::setPostponeStorage($this->options['dataStorage']); } $connector = Connector::getInstance(); @@ -169,22 +120,22 @@ class PHPConsoleHandler extends AbstractProcessingHandler $handler->setHandleExceptions($this->options['useOwnExceptionsHandler']); $handler->start(); } - if (null !== $this->options['sourcesBasePath']) { + if ($this->options['sourcesBasePath']) { $connector->setSourcesBasePath($this->options['sourcesBasePath']); } - if (null !== $this->options['serverEncoding']) { + if ($this->options['serverEncoding']) { $connector->setServerEncoding($this->options['serverEncoding']); } - if (null !== $this->options['password']) { + if ($this->options['password']) { $connector->setPassword($this->options['password']); } if ($this->options['enableSslOnlyMode']) { $connector->enableSslOnlyMode(); } - if (\count($this->options['ipMasks']) > 0) { + if ($this->options['ipMasks']) { $connector->setAllowedIpMasks($this->options['ipMasks']); } - if (null !== $this->options['headersLimit'] && $this->options['headersLimit'] > 0) { + if ($this->options['headersLimit']) { $connector->setHeadersLimit($this->options['headersLimit']); } if ($this->options['detectDumpTraceAndSource']) { @@ -217,7 +168,7 @@ class PHPConsoleHandler extends AbstractProcessingHandler return $this->options; } - public function handle(LogRecord $record): bool + public function handle(array $record): bool { if ($this->options['enabled'] && $this->connector->isActiveClient()) { return parent::handle($record); @@ -229,39 +180,48 @@ class PHPConsoleHandler extends AbstractProcessingHandler /** * Writes the record down to the log of the implementing handler */ - protected function write(LogRecord $record): void + protected function write(array $record): void { - if ($record->level->isLowerThan(Level::Notice)) { + if ($record['level'] < Logger::NOTICE) { $this->handleDebugRecord($record); - } elseif (isset($record->context['exception']) && $record->context['exception'] instanceof \Throwable) { + } elseif (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Throwable) { $this->handleExceptionRecord($record); } else { $this->handleErrorRecord($record); } } - private function handleDebugRecord(LogRecord $record): void + /** + * @phpstan-param Record $record + */ + private function handleDebugRecord(array $record): void { - [$tags, $filteredContext] = $this->getRecordTags($record); - $message = $record->message; - if (\count($filteredContext) > 0) { - $message .= ' ' . Utils::jsonEncode($this->connector->getDumper()->dump(array_filter($filteredContext)), null, true); + $tags = $this->getRecordTags($record); + $message = $record['message']; + if ($record['context']) { + $message .= ' ' . Utils::jsonEncode($this->connector->getDumper()->dump(array_filter($record['context'])), null, true); } $this->connector->getDebugDispatcher()->dispatchDebug($message, $tags, $this->options['classesPartialsTraceIgnore']); } - private function handleExceptionRecord(LogRecord $record): void + /** + * @phpstan-param Record $record + */ + private function handleExceptionRecord(array $record): void { - $this->connector->getErrorsDispatcher()->dispatchException($record->context['exception']); + $this->connector->getErrorsDispatcher()->dispatchException($record['context']['exception']); } - private function handleErrorRecord(LogRecord $record): void + /** + * @phpstan-param Record $record + */ + private function handleErrorRecord(array $record): void { - $context = $record->context; + $context = $record['context']; $this->connector->getErrorsDispatcher()->dispatchError( $context['code'] ?? null, - $context['message'] ?? $record->message, + $context['message'] ?? $record['message'], $context['file'] ?? null, $context['line'] ?? null, $this->options['classesPartialsTraceIgnore'] @@ -269,32 +229,32 @@ class PHPConsoleHandler extends AbstractProcessingHandler } /** - * @return array{string, mixed[]} + * @phpstan-param Record $record + * @return string */ - private function getRecordTags(LogRecord $record): array + private function getRecordTags(array &$record) { $tags = null; - $filteredContext = []; - if ($record->context !== []) { - $filteredContext = $record->context; + if (!empty($record['context'])) { + $context = & $record['context']; foreach ($this->options['debugTagsKeysInContext'] as $key) { - if (isset($filteredContext[$key])) { - $tags = $filteredContext[$key]; + if (!empty($context[$key])) { + $tags = $context[$key]; if ($key === 0) { - array_shift($filteredContext); + array_shift($context); } else { - unset($filteredContext[$key]); + unset($context[$key]); } break; } } } - return [$tags ?? $record->level->toPsrLogLevel(), $filteredContext]; + return $tags ?: strtolower($record['level_name']); } /** - * @inheritDoc + * {@inheritDoc} */ protected function getDefaultFormatter(): FormatterInterface { diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/ProcessHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/ProcessHandler.php index 9edc9ac54..8a8cf1be6 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/ProcessHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/ProcessHandler.php @@ -11,8 +11,7 @@ namespace Monolog\Handler; -use Monolog\Level; -use Monolog\LogRecord; +use Monolog\Logger; /** * Stores to STDIN of any process, specified by a command. @@ -34,14 +33,20 @@ class ProcessHandler extends AbstractProcessingHandler */ private $process; - private string $command; + /** + * @var string + */ + private $command; - private ?string $cwd; + /** + * @var string|null + */ + private $cwd; /** * @var resource[] */ - private array $pipes = []; + private $pipes = []; /** * @var array @@ -58,7 +63,7 @@ class ProcessHandler extends AbstractProcessingHandler * @param string|null $cwd "Current working directory" (CWD) for the process to be executed in. * @throws \InvalidArgumentException */ - public function __construct(string $command, int|string|Level $level = Level::Debug, bool $bubble = true, ?string $cwd = null) + public function __construct(string $command, $level = Logger::DEBUG, bool $bubble = true, ?string $cwd = null) { if ($command === '') { throw new \InvalidArgumentException('The command argument must be a non-empty string.'); @@ -78,14 +83,14 @@ class ProcessHandler extends AbstractProcessingHandler * * @throws \UnexpectedValueException */ - protected function write(LogRecord $record): void + protected function write(array $record): void { $this->ensureProcessIsStarted(); - $this->writeProcessInput($record->formatted); + $this->writeProcessInput($record['formatted']); $errors = $this->readProcessErrors(); - if ($errors !== '') { + if (empty($errors) === false) { throw new \UnexpectedValueException(sprintf('Errors while writing to process: %s', $errors)); } } @@ -129,7 +134,7 @@ class ProcessHandler extends AbstractProcessingHandler $errors = $this->readProcessErrors(); - if (is_resource($this->process) === false || $errors !== '') { + if (is_resource($this->process) === false || empty($errors) === false) { throw new \UnexpectedValueException( sprintf('The process "%s" could not be opened: ' . $errors, $this->command) ); @@ -171,7 +176,7 @@ class ProcessHandler extends AbstractProcessingHandler } /** - * @inheritDoc + * {@inheritDoc} */ public function close(): void { diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/ProcessableHandlerInterface.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/ProcessableHandlerInterface.php index 9fb290faa..3adec7a4d 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/ProcessableHandlerInterface.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/ProcessableHandlerInterface.php @@ -12,19 +12,20 @@ namespace Monolog\Handler; use Monolog\Processor\ProcessorInterface; -use Monolog\LogRecord; /** * Interface to describe loggers that have processors * * @author Jordi Boggiano + * + * @phpstan-import-type Record from \Monolog\Logger */ interface ProcessableHandlerInterface { /** * Adds a processor in the stack. * - * @phpstan-param ProcessorInterface|(callable(LogRecord): LogRecord) $callback + * @psalm-param ProcessorInterface|callable(Record): Record $callback * * @param ProcessorInterface|callable $callback * @return HandlerInterface self @@ -34,7 +35,7 @@ interface ProcessableHandlerInterface /** * Removes the processor on top of the stack and returns it. * - * @phpstan-return ProcessorInterface|(callable(LogRecord): LogRecord) $callback + * @psalm-return ProcessorInterface|callable(Record): Record $callback * * @throws \LogicException In case the processor stack is empty * @return callable|ProcessorInterface diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/ProcessableHandlerTrait.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/ProcessableHandlerTrait.php index 74eeddddc..9ef6e301c 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/ProcessableHandlerTrait.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/ProcessableHandlerTrait.php @@ -13,23 +13,24 @@ namespace Monolog\Handler; use Monolog\ResettableInterface; use Monolog\Processor\ProcessorInterface; -use Monolog\LogRecord; /** * Helper trait for implementing ProcessableInterface * * @author Jordi Boggiano + * + * @phpstan-import-type Record from \Monolog\Logger */ trait ProcessableHandlerTrait { /** * @var callable[] - * @phpstan-var array<(callable(LogRecord): LogRecord)|ProcessorInterface> + * @phpstan-var array */ - protected array $processors = []; + protected $processors = []; /** - * @inheritDoc + * {@inheritDoc} */ public function pushProcessor(callable $callback): HandlerInterface { @@ -39,18 +40,24 @@ trait ProcessableHandlerTrait } /** - * @inheritDoc + * {@inheritDoc} */ public function popProcessor(): callable { - if (\count($this->processors) === 0) { + if (!$this->processors) { throw new \LogicException('You tried to pop from an empty processor stack.'); } return array_shift($this->processors); } - protected function processRecord(LogRecord $record): LogRecord + /** + * Processes a record. + * + * @phpstan-param Record $record + * @phpstan-return Record + */ + protected function processRecord(array $record): array { foreach ($this->processors as $processor) { $record = $processor($record); diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/PsrHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/PsrHandler.php index 6599a83b4..36e19cccf 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/PsrHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/PsrHandler.php @@ -11,10 +11,9 @@ namespace Monolog\Handler; -use Monolog\Level; +use Monolog\Logger; use Psr\Log\LoggerInterface; use Monolog\Formatter\FormatterInterface; -use Monolog\LogRecord; /** * Proxies log messages to an existing PSR-3 compliant logger. @@ -29,15 +28,20 @@ class PsrHandler extends AbstractHandler implements FormattableHandlerInterface { /** * PSR-3 compliant logger + * + * @var LoggerInterface */ - protected LoggerInterface $logger; + protected $logger; - protected FormatterInterface|null $formatter = null; + /** + * @var FormatterInterface|null + */ + protected $formatter; /** * @param LoggerInterface $logger The underlying PSR-3 compliant logger to which messages will be proxied */ - public function __construct(LoggerInterface $logger, int|string|Level $level = Level::Debug, bool $bubble = true) + public function __construct(LoggerInterface $logger, $level = Logger::DEBUG, bool $bubble = true) { parent::__construct($level, $bubble); @@ -45,19 +49,19 @@ class PsrHandler extends AbstractHandler implements FormattableHandlerInterface } /** - * @inheritDoc + * {@inheritDoc} */ - public function handle(LogRecord $record): bool + public function handle(array $record): bool { if (!$this->isHandling($record)) { return false; } - if ($this->formatter !== null) { + if ($this->formatter) { $formatted = $this->formatter->format($record); - $this->logger->log($record->level->toPsrLogLevel(), (string) $formatted, $record->context); + $this->logger->log(strtolower($record['level_name']), (string) $formatted, $record['context']); } else { - $this->logger->log($record->level->toPsrLogLevel(), $record->message, $record->context); + $this->logger->log(strtolower($record['level_name']), $record['message'], $record['context']); } return false === $this->bubble; @@ -65,6 +69,8 @@ class PsrHandler extends AbstractHandler implements FormattableHandlerInterface /** * Sets the formatter. + * + * @param FormatterInterface $formatter */ public function setFormatter(FormatterInterface $formatter): HandlerInterface { @@ -75,10 +81,12 @@ class PsrHandler extends AbstractHandler implements FormattableHandlerInterface /** * Gets the formatter. + * + * @return FormatterInterface */ public function getFormatter(): FormatterInterface { - if ($this->formatter === null) { + if (!$this->formatter) { throw new \LogicException('No formatter has been set and this handler does not have a default formatter'); } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/PushoverHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/PushoverHandler.php index 118f5760a..fed2303d7 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/PushoverHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/PushoverHandler.php @@ -11,45 +11,48 @@ namespace Monolog\Handler; -use Monolog\Level; use Monolog\Logger; use Monolog\Utils; use Psr\Log\LogLevel; -use Monolog\LogRecord; /** * Sends notifications through the pushover api to mobile phones * * @author Sebastian Göttschkes * @see https://www.pushover.net/api + * + * @phpstan-import-type FormattedRecord from AbstractProcessingHandler + * @phpstan-import-type Level from \Monolog\Logger + * @phpstan-import-type LevelName from \Monolog\Logger */ class PushoverHandler extends SocketHandler { - private string $token; - + /** @var string */ + private $token; /** @var array */ - private array $users; + private $users; + /** @var string */ + private $title; + /** @var string|int|null */ + private $user = null; + /** @var int */ + private $retry; + /** @var int */ + private $expire; - private string $title; - - private string|int|null $user = null; - - private int $retry; - - private int $expire; - - private Level $highPriorityLevel; - - private Level $emergencyLevel; - - private bool $useFormattedMessage = false; + /** @var int */ + private $highPriorityLevel; + /** @var int */ + private $emergencyLevel; + /** @var bool */ + private $useFormattedMessage = false; /** * All parameters that can be sent to Pushover * @see https://pushover.net/api * @var array */ - private array $parameterNames = [ + private $parameterNames = [ 'token' => true, 'user' => true, 'message' => true, @@ -70,42 +73,40 @@ class PushoverHandler extends SocketHandler * @see https://pushover.net/api#sounds * @var string[] */ - private array $sounds = [ + private $sounds = [ 'pushover', 'bike', 'bugle', 'cashregister', 'classical', 'cosmic', 'falling', 'gamelan', 'incoming', 'intermission', 'magic', 'mechanical', 'pianobar', 'siren', 'spacealarm', 'tugboat', 'alien', 'climb', 'persistent', 'echo', 'updown', 'none', ]; /** - * @param string $token Pushover api token - * @param string|array $users Pushover user id or array of ids the message will be sent to - * @param string|null $title Title sent to the Pushover API - * @param bool $useSSL Whether to connect via SSL. Required when pushing messages to users that are not - * the pushover.net app owner. OpenSSL is required for this option. - * @param int $retry The retry parameter specifies how often (in seconds) the Pushover servers will - * send the same notification to the user. - * @param int $expire The expire parameter specifies how many seconds your notification will continue - * to be retried for (every retry seconds). - * - * @param int|string|Level|LogLevel::* $highPriorityLevel The minimum logging level at which this handler will start - * sending "high priority" requests to the Pushover API - * @param int|string|Level|LogLevel::* $emergencyLevel The minimum logging level at which this handler will start - * sending "emergency" requests to the Pushover API - * + * @param string $token Pushover api token + * @param string|array $users Pushover user id or array of ids the message will be sent to + * @param string|null $title Title sent to the Pushover API + * @param bool $useSSL Whether to connect via SSL. Required when pushing messages to users that are not + * the pushover.net app owner. OpenSSL is required for this option. + * @param string|int $highPriorityLevel The minimum logging level at which this handler will start + * sending "high priority" requests to the Pushover API + * @param string|int $emergencyLevel The minimum logging level at which this handler will start + * sending "emergency" requests to the Pushover API + * @param int $retry The retry parameter specifies how often (in seconds) the Pushover servers will + * send the same notification to the user. + * @param int $expire The expire parameter specifies how many seconds your notification will continue + * to be retried for (every retry seconds). * * @phpstan-param string|array $users - * @phpstan-param value-of|value-of|Level|LogLevel::* $highPriorityLevel - * @phpstan-param value-of|value-of|Level|LogLevel::* $emergencyLevel + * @phpstan-param Level|LevelName|LogLevel::* $highPriorityLevel + * @phpstan-param Level|LevelName|LogLevel::* $emergencyLevel */ public function __construct( string $token, $users, ?string $title = null, - int|string|Level $level = Level::Critical, + $level = Logger::CRITICAL, bool $bubble = true, bool $useSSL = true, - int|string|Level $highPriorityLevel = Level::Critical, - int|string|Level $emergencyLevel = Level::Emergency, + $highPriorityLevel = Logger::CRITICAL, + $emergencyLevel = Logger::EMERGENCY, int $retry = 30, int $expire = 25200, bool $persistent = false, @@ -128,29 +129,32 @@ class PushoverHandler extends SocketHandler $this->token = $token; $this->users = (array) $users; - $this->title = $title ?? (string) gethostname(); + $this->title = $title ?: (string) gethostname(); $this->highPriorityLevel = Logger::toMonologLevel($highPriorityLevel); $this->emergencyLevel = Logger::toMonologLevel($emergencyLevel); $this->retry = $retry; $this->expire = $expire; } - protected function generateDataStream(LogRecord $record): string + protected function generateDataStream(array $record): string { $content = $this->buildContent($record); return $this->buildHeader($content) . $content; } - private function buildContent(LogRecord $record): string + /** + * @phpstan-param FormattedRecord $record + */ + private function buildContent(array $record): string { // Pushover has a limit of 512 characters on title and message combined. $maxMessageLength = 512 - strlen($this->title); - $message = ($this->useFormattedMessage) ? $record->formatted : $record->message; + $message = ($this->useFormattedMessage) ? $record['formatted'] : $record['message']; $message = Utils::substr($message, 0, $maxMessageLength); - $timestamp = $record->datetime->getTimestamp(); + $timestamp = $record['datetime']->getTimestamp(); $dataArray = [ 'token' => $this->token, @@ -160,23 +164,23 @@ class PushoverHandler extends SocketHandler 'timestamp' => $timestamp, ]; - if ($record->level->value >= $this->emergencyLevel->value) { + if (isset($record['level']) && $record['level'] >= $this->emergencyLevel) { $dataArray['priority'] = 2; $dataArray['retry'] = $this->retry; $dataArray['expire'] = $this->expire; - } elseif ($record->level->value >= $this->highPriorityLevel->value) { + } elseif (isset($record['level']) && $record['level'] >= $this->highPriorityLevel) { $dataArray['priority'] = 1; } // First determine the available parameters - $context = array_intersect_key($record->context, $this->parameterNames); - $extra = array_intersect_key($record->extra, $this->parameterNames); + $context = array_intersect_key($record['context'], $this->parameterNames); + $extra = array_intersect_key($record['extra'], $this->parameterNames); // Least important info should be merged with subsequent info $dataArray = array_merge($extra, $context, $dataArray); // Only pass sounds that are supported by the API - if (isset($dataArray['sound']) && !in_array($dataArray['sound'], $this->sounds, true)) { + if (isset($dataArray['sound']) && !in_array($dataArray['sound'], $this->sounds)) { unset($dataArray['sound']); } @@ -194,7 +198,7 @@ class PushoverHandler extends SocketHandler return $header; } - protected function write(LogRecord $record): void + protected function write(array $record): void { foreach ($this->users as $user) { $this->user = $user; @@ -207,25 +211,25 @@ class PushoverHandler extends SocketHandler } /** - * @param int|string|Level|LogLevel::* $level + * @param int|string $value * - * @phpstan-param value-of|value-of|Level|LogLevel::* $level + * @phpstan-param Level|LevelName|LogLevel::* $value */ - public function setHighPriorityLevel(int|string|Level $level): self + public function setHighPriorityLevel($value): self { - $this->highPriorityLevel = Logger::toMonologLevel($level); + $this->highPriorityLevel = Logger::toMonologLevel($value); return $this; } /** - * @param int|string|Level|LogLevel::* $level + * @param int|string $value * - * @phpstan-param value-of|value-of|Level|LogLevel::* $level + * @phpstan-param Level|LevelName|LogLevel::* $value */ - public function setEmergencyLevel(int|string|Level $level): self + public function setEmergencyLevel($value): self { - $this->emergencyLevel = Logger::toMonologLevel($level); + $this->emergencyLevel = Logger::toMonologLevel($value); return $this; } @@ -233,9 +237,9 @@ class PushoverHandler extends SocketHandler /** * Use the formatted message? */ - public function useFormattedMessage(bool $useFormattedMessage): self + public function useFormattedMessage(bool $value): self { - $this->useFormattedMessage = $useFormattedMessage; + $this->useFormattedMessage = $value; return $this; } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/RedisHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/RedisHandler.php index 5eee5dc69..91d16eaf6 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/RedisHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/RedisHandler.php @@ -13,10 +13,7 @@ namespace Monolog\Handler; use Monolog\Formatter\LineFormatter; use Monolog\Formatter\FormatterInterface; -use Monolog\Level; -use Monolog\LogRecord; -use Predis\Client as Predis; -use Redis; +use Monolog\Logger; /** * Logs to a Redis key using rpush @@ -28,21 +25,29 @@ use Redis; * $log->pushHandler($redis); * * @author Thomas Tourlourat + * + * @phpstan-import-type FormattedRecord from AbstractProcessingHandler */ class RedisHandler extends AbstractProcessingHandler { - /** @var Predis|Redis */ - private Predis|Redis $redisClient; - private string $redisKey; - protected int $capSize; + /** @var \Predis\Client<\Predis\Client>|\Redis */ + private $redisClient; + /** @var string */ + private $redisKey; + /** @var int */ + protected $capSize; /** - * @param Predis|Redis $redis The redis instance - * @param string $key The key name to push records to - * @param int $capSize Number of entries to limit list size to, 0 = unlimited + * @param \Predis\Client<\Predis\Client>|\Redis $redis The redis instance + * @param string $key The key name to push records to + * @param int $capSize Number of entries to limit list size to, 0 = unlimited */ - public function __construct(Predis|Redis $redis, string $key, int|string|Level $level = Level::Debug, bool $bubble = true, int $capSize = 0) + public function __construct($redis, string $key, $level = Logger::DEBUG, bool $bubble = true, int $capSize = 0) { + if (!(($redis instanceof \Predis\Client) || ($redis instanceof \Redis))) { + throw new \InvalidArgumentException('Predis\Client or Redis instance required'); + } + $this->redisClient = $redis; $this->redisKey = $key; $this->capSize = $capSize; @@ -51,41 +56,43 @@ class RedisHandler extends AbstractProcessingHandler } /** - * @inheritDoc + * {@inheritDoc} */ - protected function write(LogRecord $record): void + protected function write(array $record): void { - if ($this->capSize > 0) { + if ($this->capSize) { $this->writeCapped($record); } else { - $this->redisClient->rpush($this->redisKey, $record->formatted); + $this->redisClient->rpush($this->redisKey, $record["formatted"]); } } /** * Write and cap the collection * Writes the record to the redis list and caps its + * + * @phpstan-param FormattedRecord $record */ - protected function writeCapped(LogRecord $record): void + protected function writeCapped(array $record): void { - if ($this->redisClient instanceof Redis) { - $mode = defined('Redis::MULTI') ? Redis::MULTI : 1; + if ($this->redisClient instanceof \Redis) { + $mode = defined('\Redis::MULTI') ? \Redis::MULTI : 1; $this->redisClient->multi($mode) - ->rPush($this->redisKey, $record->formatted) + ->rpush($this->redisKey, $record["formatted"]) ->ltrim($this->redisKey, -$this->capSize, -1) ->exec(); } else { $redisKey = $this->redisKey; $capSize = $this->capSize; $this->redisClient->transaction(function ($tx) use ($record, $redisKey, $capSize) { - $tx->rpush($redisKey, $record->formatted); + $tx->rpush($redisKey, $record["formatted"]); $tx->ltrim($redisKey, -$capSize, -1); }); } } /** - * @inheritDoc + * {@inheritDoc} */ protected function getDefaultFormatter(): FormatterInterface { diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/RedisPubSubHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/RedisPubSubHandler.php index fa8e9e9ff..7789309c1 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/RedisPubSubHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/RedisPubSubHandler.php @@ -13,10 +13,7 @@ namespace Monolog\Handler; use Monolog\Formatter\LineFormatter; use Monolog\Formatter\FormatterInterface; -use Monolog\Level; -use Monolog\LogRecord; -use Predis\Client as Predis; -use Redis; +use Monolog\Logger; /** * Sends the message to a Redis Pub/Sub channel using PUBLISH @@ -24,23 +21,28 @@ use Redis; * usage example: * * $log = new Logger('application'); - * $redis = new RedisPubSubHandler(new Predis\Client("tcp://localhost:6379"), "logs", Level::Warning); + * $redis = new RedisPubSubHandler(new Predis\Client("tcp://localhost:6379"), "logs", Logger::WARNING); * $log->pushHandler($redis); * * @author Gaëtan Faugère */ class RedisPubSubHandler extends AbstractProcessingHandler { - /** @var Predis|Redis */ - private Predis|Redis $redisClient; - private string $channelKey; + /** @var \Predis\Client<\Predis\Client>|\Redis */ + private $redisClient; + /** @var string */ + private $channelKey; /** - * @param Predis|Redis $redis The redis instance - * @param string $key The channel key to publish records to + * @param \Predis\Client<\Predis\Client>|\Redis $redis The redis instance + * @param string $key The channel key to publish records to */ - public function __construct(Predis|Redis $redis, string $key, int|string|Level $level = Level::Debug, bool $bubble = true) + public function __construct($redis, string $key, $level = Logger::DEBUG, bool $bubble = true) { + if (!(($redis instanceof \Predis\Client) || ($redis instanceof \Redis))) { + throw new \InvalidArgumentException('Predis\Client or Redis instance required'); + } + $this->redisClient = $redis; $this->channelKey = $key; @@ -48,15 +50,15 @@ class RedisPubSubHandler extends AbstractProcessingHandler } /** - * @inheritDoc + * {@inheritDoc} */ - protected function write(LogRecord $record): void + protected function write(array $record): void { - $this->redisClient->publish($this->channelKey, $record->formatted); + $this->redisClient->publish($this->channelKey, $record["formatted"]); } /** - * @inheritDoc + * {@inheritDoc} */ protected function getDefaultFormatter(): FormatterInterface { diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/RollbarHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/RollbarHandler.php index 1d124723b..adcc9395a 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/RollbarHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/RollbarHandler.php @@ -11,10 +11,9 @@ namespace Monolog\Handler; -use Monolog\Level; use Rollbar\RollbarLogger; use Throwable; -use Monolog\LogRecord; +use Monolog\Logger; /** * Sends errors to Rollbar @@ -34,19 +33,37 @@ use Monolog\LogRecord; */ class RollbarHandler extends AbstractProcessingHandler { - protected RollbarLogger $rollbarLogger; + /** + * @var RollbarLogger + */ + protected $rollbarLogger; + + /** @var string[] */ + protected $levelMap = [ + Logger::DEBUG => 'debug', + Logger::INFO => 'info', + Logger::NOTICE => 'info', + Logger::WARNING => 'warning', + Logger::ERROR => 'error', + Logger::CRITICAL => 'critical', + Logger::ALERT => 'critical', + Logger::EMERGENCY => 'critical', + ]; /** * Records whether any log records have been added since the last flush of the rollbar notifier + * + * @var bool */ - private bool $hasRecords = false; + private $hasRecords = false; - protected bool $initialized = false; + /** @var bool */ + protected $initialized = false; /** * @param RollbarLogger $rollbarLogger RollbarLogger object constructed with valid token */ - public function __construct(RollbarLogger $rollbarLogger, int|string|Level $level = Level::Error, bool $bubble = true) + public function __construct(RollbarLogger $rollbarLogger, $level = Logger::ERROR, bool $bubble = true) { $this->rollbarLogger = $rollbarLogger; @@ -54,41 +71,22 @@ class RollbarHandler extends AbstractProcessingHandler } /** - * Translates Monolog log levels to Rollbar levels. - * - * @return 'debug'|'info'|'warning'|'error'|'critical' + * {@inheritDoc} */ - protected function toRollbarLevel(Level $level): string - { - return match ($level) { - Level::Debug => 'debug', - Level::Info => 'info', - Level::Notice => 'info', - Level::Warning => 'warning', - Level::Error => 'error', - Level::Critical => 'critical', - Level::Alert => 'critical', - Level::Emergency => 'critical', - }; - } - - /** - * @inheritDoc - */ - protected function write(LogRecord $record): void + protected function write(array $record): void { if (!$this->initialized) { // __destructor() doesn't get called on Fatal errors - register_shutdown_function([$this, 'close']); + register_shutdown_function(array($this, 'close')); $this->initialized = true; } - $context = $record->context; - $context = array_merge($context, $record->extra, [ - 'level' => $this->toRollbarLevel($record->level), - 'monolog_level' => $record->level->getName(), - 'channel' => $record->channel, - 'datetime' => $record->datetime->format('U'), + $context = $record['context']; + $context = array_merge($context, $record['extra'], [ + 'level' => $this->levelMap[$record['level']], + 'monolog_level' => $record['level_name'], + 'channel' => $record['channel'], + 'datetime' => $record['datetime']->format('U'), ]); if (isset($context['exception']) && $context['exception'] instanceof Throwable) { @@ -96,7 +94,7 @@ class RollbarHandler extends AbstractProcessingHandler unset($context['exception']); $toLog = $exception; } else { - $toLog = $record->message; + $toLog = $record['message']; } // @phpstan-ignore-next-line @@ -114,7 +112,7 @@ class RollbarHandler extends AbstractProcessingHandler } /** - * @inheritDoc + * {@inheritDoc} */ public function close(): void { @@ -122,9 +120,9 @@ class RollbarHandler extends AbstractProcessingHandler } /** - * @inheritDoc + * {@inheritDoc} */ - public function reset(): void + public function reset() { $this->flush(); diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php index 12ce69236..17745d221 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php @@ -12,9 +12,8 @@ namespace Monolog\Handler; use InvalidArgumentException; -use Monolog\Level; +use Monolog\Logger; use Monolog\Utils; -use Monolog\LogRecord; /** * Stores logs to files that are rotated every day and a limited number of files are kept. @@ -31,19 +30,26 @@ class RotatingFileHandler extends StreamHandler public const FILE_PER_MONTH = 'Y-m'; public const FILE_PER_YEAR = 'Y'; - protected string $filename; - protected int $maxFiles; - protected bool|null $mustRotate = null; - protected \DateTimeImmutable $nextRotation; - protected string $filenameFormat; - protected string $dateFormat; + /** @var string */ + protected $filename; + /** @var int */ + protected $maxFiles; + /** @var bool */ + protected $mustRotate; + /** @var \DateTimeImmutable */ + protected $nextRotation; + /** @var string */ + protected $filenameFormat; + /** @var string */ + protected $dateFormat; /** - * @param int $maxFiles The maximal amount of files to keep (0 means unlimited) - * @param int|null $filePermission Optional file permissions (default (0644) are only for owner read/write) - * @param bool $useLocking Try to lock log file before doing any writes + * @param string $filename + * @param int $maxFiles The maximal amount of files to keep (0 means unlimited) + * @param int|null $filePermission Optional file permissions (default (0644) are only for owner read/write) + * @param bool $useLocking Try to lock log file before doing any writes */ - public function __construct(string $filename, int $maxFiles = 0, int|string|Level $level = Level::Debug, bool $bubble = true, ?int $filePermission = null, bool $useLocking = false) + public function __construct(string $filename, int $maxFiles = 0, $level = Logger::DEBUG, bool $bubble = true, ?int $filePermission = null, bool $useLocking = false) { $this->filename = Utils::canonicalizePath($filename); $this->maxFiles = $maxFiles; @@ -55,7 +61,7 @@ class RotatingFileHandler extends StreamHandler } /** - * @inheritDoc + * {@inheritDoc} */ public function close(): void { @@ -67,9 +73,9 @@ class RotatingFileHandler extends StreamHandler } /** - * @inheritDoc + * {@inheritDoc} */ - public function reset(): void + public function reset() { parent::reset(); @@ -80,7 +86,7 @@ class RotatingFileHandler extends StreamHandler public function setFilenameFormat(string $filenameFormat, string $dateFormat): self { - if (0 === preg_match('{^[Yy](([/_.-]?m)([/_.-]?d)?)?$}', $dateFormat)) { + if (!preg_match('{^[Yy](([/_.-]?m)([/_.-]?d)?)?$}', $dateFormat)) { throw new InvalidArgumentException( 'Invalid date format - format must be one of '. 'RotatingFileHandler::FILE_PER_DAY ("Y-m-d"), RotatingFileHandler::FILE_PER_MONTH ("Y-m") '. @@ -102,16 +108,16 @@ class RotatingFileHandler extends StreamHandler } /** - * @inheritDoc + * {@inheritDoc} */ - protected function write(LogRecord $record): void + protected function write(array $record): void { // on the first record written, if the log is new, we should rotate (once per day) if (null === $this->mustRotate) { $this->mustRotate = null === $this->url || !file_exists($this->url); } - if ($this->nextRotation <= $record->datetime) { + if ($this->nextRotation <= $record['datetime']) { $this->mustRotate = true; $this->close(); } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/SamplingHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/SamplingHandler.php index 511ec5854..c128a32d1 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/SamplingHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/SamplingHandler.php @@ -11,9 +11,7 @@ namespace Monolog\Handler; -use Closure; use Monolog\Formatter\FormatterInterface; -use Monolog\LogRecord; /** * Sampling handler @@ -28,42 +26,52 @@ use Monolog\LogRecord; * * @author Bryan Davis * @author Kunal Mehta + * + * @phpstan-import-type Record from \Monolog\Logger + * @phpstan-import-type Level from \Monolog\Logger */ class SamplingHandler extends AbstractHandler implements ProcessableHandlerInterface, FormattableHandlerInterface { use ProcessableHandlerTrait; /** - * Handler or factory Closure($record, $this) - * - * @phpstan-var (Closure(LogRecord|null, HandlerInterface): HandlerInterface)|HandlerInterface + * @var HandlerInterface|callable + * @phpstan-var HandlerInterface|callable(Record|array{level: Level}|null, HandlerInterface): HandlerInterface */ - protected Closure|HandlerInterface $handler; - - protected int $factor; + protected $handler; /** - * @phpstan-param (Closure(LogRecord|null, HandlerInterface): HandlerInterface)|HandlerInterface $handler - * - * @param Closure|HandlerInterface $handler Handler or factory Closure($record|null, $samplingHandler). - * @param int $factor Sample factor (e.g. 10 means every ~10th record is sampled) + * @var int $factor */ - public function __construct(Closure|HandlerInterface $handler, int $factor) + protected $factor; + + /** + * @psalm-param HandlerInterface|callable(Record|array{level: Level}|null, HandlerInterface): HandlerInterface $handler + * + * @param callable|HandlerInterface $handler Handler or factory callable($record|null, $samplingHandler). + * @param int $factor Sample factor (e.g. 10 means every ~10th record is sampled) + */ + public function __construct($handler, int $factor) { parent::__construct(); $this->handler = $handler; $this->factor = $factor; + + if (!$this->handler instanceof HandlerInterface && !is_callable($this->handler)) { + throw new \RuntimeException("The given handler (".json_encode($this->handler).") is not a callable nor a Monolog\Handler\HandlerInterface object"); + } } - public function isHandling(LogRecord $record): bool + public function isHandling(array $record): bool { return $this->getHandler($record)->isHandling($record); } - public function handle(LogRecord $record): bool + public function handle(array $record): bool { if ($this->isHandling($record) && mt_rand(1, $this->factor) === 1) { - if (\count($this->processors) > 0) { + if ($this->processors) { + /** @var Record $record */ $record = $this->processRecord($record); } @@ -76,23 +84,26 @@ class SamplingHandler extends AbstractHandler implements ProcessableHandlerInter /** * Return the nested handler * - * If the handler was provided as a factory, this will trigger the handler's instantiation. + * If the handler was provided as a factory callable, this will trigger the handler's instantiation. + * + * @phpstan-param Record|array{level: Level}|null $record + * + * @return HandlerInterface */ - public function getHandler(LogRecord $record = null): HandlerInterface + public function getHandler(array $record = null) { if (!$this->handler instanceof HandlerInterface) { - $handler = ($this->handler)($record, $this); - if (!$handler instanceof HandlerInterface) { - throw new \RuntimeException("The factory Closure should return a HandlerInterface"); + $this->handler = ($this->handler)($record, $this); + if (!$this->handler instanceof HandlerInterface) { + throw new \RuntimeException("The factory callable should return a HandlerInterface"); } - $this->handler = $handler; } return $this->handler; } /** - * @inheritDoc + * {@inheritDoc} */ public function setFormatter(FormatterInterface $formatter): HandlerInterface { @@ -107,7 +118,7 @@ class SamplingHandler extends AbstractHandler implements ProcessableHandlerInter } /** - * @inheritDoc + * {@inheritDoc} */ public function getFormatter(): FormatterInterface { diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/SendGridHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/SendGridHandler.php index 6228a02f2..1280ee703 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/SendGridHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/SendGridHandler.php @@ -11,7 +11,7 @@ namespace Monolog\Handler; -use Monolog\Level; +use Monolog\Logger; /** * SendGridrHandler uses the SendGrid API v2 function to send Log emails, more information in https://sendgrid.com/docs/API_Reference/Web_API/mail.html @@ -22,29 +22,33 @@ class SendGridHandler extends MailHandler { /** * The SendGrid API User + * @var string */ - protected string $apiUser; + protected $apiUser; /** * The SendGrid API Key + * @var string */ - protected string $apiKey; + protected $apiKey; /** * The email addresses to which the message will be sent + * @var string */ - protected string $from; + protected $from; /** * The email addresses to which the message will be sent * @var string[] */ - protected array $to; + protected $to; /** * The subject of the email + * @var string */ - protected string $subject; + protected $subject; /** * @param string $apiUser The SendGrid API User @@ -53,7 +57,7 @@ class SendGridHandler extends MailHandler * @param string|string[] $to The recipients of the email * @param string $subject The subject of the mail */ - public function __construct(string $apiUser, string $apiKey, string $from, string|array $to, string $subject, int|string|Level $level = Level::Error, bool $bubble = true) + public function __construct(string $apiUser, string $apiKey, string $from, $to, string $subject, $level = Logger::ERROR, bool $bubble = true) { if (!extension_loaded('curl')) { throw new MissingExtensionException('The curl extension is needed to use the SendGridHandler'); @@ -68,7 +72,7 @@ class SendGridHandler extends MailHandler } /** - * @inheritDoc + * {@inheritDoc} */ protected function send(string $content, array $records): void { diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/Slack/SlackRecord.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/Slack/SlackRecord.php index 7e9cccc9d..71a410946 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/Slack/SlackRecord.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/Slack/SlackRecord.php @@ -11,11 +11,10 @@ namespace Monolog\Handler\Slack; -use Monolog\Level; +use Monolog\Logger; use Monolog\Utils; use Monolog\Formatter\NormalizerFormatter; use Monolog\Formatter\FormatterInterface; -use Monolog\LogRecord; /** * Slack record utility helping to log to Slack webhooks or API. @@ -24,6 +23,9 @@ use Monolog\LogRecord; * @author Haralan Dobrev * @see https://api.slack.com/incoming-webhooks * @see https://api.slack.com/docs/message-attachments + * + * @phpstan-import-type FormattedRecord from \Monolog\Handler\AbstractProcessingHandler + * @phpstan-import-type Record from \Monolog\Logger */ class SlackRecord { @@ -37,43 +39,55 @@ class SlackRecord /** * Slack channel (encoded ID or name) + * @var string|null */ - private string|null $channel; + private $channel; /** * Name of a bot + * @var string|null */ - private string|null $username; + private $username; /** * User icon e.g. 'ghost', 'http://example.com/user.png' + * @var string|null */ - private string|null $userIcon; + private $userIcon; /** * Whether the message should be added to Slack as attachment (plain text otherwise) + * @var bool */ - private bool $useAttachment; + private $useAttachment; /** * Whether the the context/extra messages added to Slack as attachments are in a short style + * @var bool */ - private bool $useShortAttachment; + private $useShortAttachment; /** * Whether the attachment should include context and extra data + * @var bool */ - private bool $includeContextAndExtra; + private $includeContextAndExtra; /** * Dot separated list of fields to exclude from slack message. E.g. ['context.field1', 'extra.field2'] * @var string[] */ - private array $excludeFields; + private $excludeFields; - private FormatterInterface|null $formatter; + /** + * @var ?FormatterInterface + */ + private $formatter; - private NormalizerFormatter $normalizerFormatter; + /** + * @var NormalizerFormatter + */ + private $normalizerFormatter; /** * @param string[] $excludeFields @@ -85,7 +99,7 @@ class SlackRecord ?string $userIcon = null, bool $useShortAttachment = false, bool $includeContextAndExtra = false, - array $excludeFields = [], + array $excludeFields = array(), FormatterInterface $formatter = null ) { $this @@ -107,76 +121,77 @@ class SlackRecord * Returns required data in format that Slack * is expecting. * + * @phpstan-param FormattedRecord $record * @phpstan-return mixed[] */ - public function getSlackData(LogRecord $record): array + public function getSlackData(array $record): array { - $dataArray = []; + $dataArray = array(); + $record = $this->removeExcludedFields($record); - if ($this->username !== null) { + if ($this->username) { $dataArray['username'] = $this->username; } - if ($this->channel !== null) { + if ($this->channel) { $dataArray['channel'] = $this->channel; } - if ($this->formatter !== null && !$this->useAttachment) { + if ($this->formatter && !$this->useAttachment) { + /** @phpstan-ignore-next-line */ $message = $this->formatter->format($record); } else { - $message = $record->message; + $message = $record['message']; } - $recordData = $this->removeExcludedFields($record); - if ($this->useAttachment) { - $attachment = [ - 'fallback' => $message, - 'text' => $message, - 'color' => $this->getAttachmentColor($record->level), - 'fields' => [], - 'mrkdwn_in' => ['fields'], - 'ts' => $recordData['datetime']->getTimestamp(), + $attachment = array( + 'fallback' => $message, + 'text' => $message, + 'color' => $this->getAttachmentColor($record['level']), + 'fields' => array(), + 'mrkdwn_in' => array('fields'), + 'ts' => $record['datetime']->getTimestamp(), 'footer' => $this->username, 'footer_icon' => $this->userIcon, - ]; + ); if ($this->useShortAttachment) { - $attachment['title'] = $recordData['level_name']; + $attachment['title'] = $record['level_name']; } else { $attachment['title'] = 'Message'; - $attachment['fields'][] = $this->generateAttachmentField('Level', $recordData['level_name']); + $attachment['fields'][] = $this->generateAttachmentField('Level', $record['level_name']); } if ($this->includeContextAndExtra) { - foreach (['extra', 'context'] as $key) { - if (!isset($recordData[$key]) || \count($recordData[$key]) === 0) { + foreach (array('extra', 'context') as $key) { + if (empty($record[$key])) { continue; } if ($this->useShortAttachment) { $attachment['fields'][] = $this->generateAttachmentField( - $key, - $recordData[$key] + (string) $key, + $record[$key] ); } else { // Add all extra fields as individual fields in attachment $attachment['fields'] = array_merge( $attachment['fields'], - $this->generateAttachmentFields($recordData[$key]) + $this->generateAttachmentFields($record[$key]) ); } } } - $dataArray['attachments'] = [$attachment]; + $dataArray['attachments'] = array($attachment); } else { $dataArray['text'] = $message; } - if ($this->userIcon !== null) { - if (false !== ($iconUrl = filter_var($this->userIcon, FILTER_VALIDATE_URL))) { - $dataArray['icon_url'] = $iconUrl; + if ($this->userIcon) { + if (filter_var($this->userIcon, FILTER_VALIDATE_URL)) { + $dataArray['icon_url'] = $this->userIcon; } else { $dataArray['icon_emoji'] = ":{$this->userIcon}:"; } @@ -189,14 +204,18 @@ class SlackRecord * Returns a Slack message attachment color associated with * provided level. */ - public function getAttachmentColor(Level $level): string + public function getAttachmentColor(int $level): string { - return match ($level) { - Level::Error, Level::Critical, Level::Alert, Level::Emergency => static::COLOR_DANGER, - Level::Warning => static::COLOR_WARNING, - Level::Info, Level::Notice => static::COLOR_GOOD, - Level::Debug => static::COLOR_DEFAULT - }; + switch (true) { + case $level >= Logger::ERROR: + return static::COLOR_DANGER; + case $level >= Logger::WARNING: + return static::COLOR_WARNING; + case $level >= Logger::INFO: + return static::COLOR_GOOD; + default: + return static::COLOR_DEFAULT; + } } /** @@ -206,13 +225,13 @@ class SlackRecord */ public function stringify(array $fields): string { - /** @var array $normalized */ - $normalized = $this->normalizerFormatter->normalizeValue($fields); + /** @var Record $fields */ + $normalized = $this->normalizerFormatter->format($fields); - $hasSecondDimension = \count(array_filter($normalized, 'is_array')) > 0; - $hasOnlyNonNumericKeys = \count(array_filter(array_keys($normalized), 'is_numeric')) === 0; + $hasSecondDimension = count(array_filter($normalized, 'is_array')); + $hasNonNumericKeys = !count(array_filter(array_keys($normalized), 'is_numeric')); - return $hasSecondDimension || $hasOnlyNonNumericKeys + return $hasSecondDimension || $hasNonNumericKeys ? Utils::jsonEncode($normalized, JSON_PRETTY_PRINT|Utils::DEFAULT_JSON_FLAGS) : Utils::jsonEncode($normalized, Utils::DEFAULT_JSON_FLAGS); } @@ -311,11 +330,11 @@ class SlackRecord ? sprintf('```%s```', substr($this->stringify($value), 0, 1990)) : $value; - return [ + return array( 'title' => ucfirst($title), 'value' => $value, 'short' => false, - ]; + ); } /** @@ -327,10 +346,10 @@ class SlackRecord */ private function generateAttachmentFields(array $data): array { - /** @var array $normalized */ - $normalized = $this->normalizerFormatter->normalizeValue($data); + /** @var Record $data */ + $normalized = $this->normalizerFormatter->format($data); - $fields = []; + $fields = array(); foreach ($normalized as $key => $value) { $fields[] = $this->generateAttachmentField((string) $key, $value); } @@ -341,14 +360,15 @@ class SlackRecord /** * Get a copy of record with fields excluded according to $this->excludeFields * + * @phpstan-param FormattedRecord $record + * * @return mixed[] */ - private function removeExcludedFields(LogRecord $record): array + private function removeExcludedFields(array $record): array { - $recordData = $record->toArray(); foreach ($this->excludeFields as $field) { $keys = explode('.', $field); - $node = &$recordData; + $node = &$record; $lastKey = end($keys); foreach ($keys as $key) { if (!isset($node[$key])) { @@ -362,6 +382,6 @@ class SlackRecord } } - return $recordData; + return $record; } } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/SlackHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/SlackHandler.php index 321d8660f..a648513e0 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/SlackHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/SlackHandler.php @@ -12,28 +12,31 @@ namespace Monolog\Handler; use Monolog\Formatter\FormatterInterface; -use Monolog\Level; +use Monolog\Logger; use Monolog\Utils; use Monolog\Handler\Slack\SlackRecord; -use Monolog\LogRecord; /** * Sends notifications through Slack API * * @author Greg Kedzierski * @see https://api.slack.com/ + * + * @phpstan-import-type FormattedRecord from AbstractProcessingHandler */ class SlackHandler extends SocketHandler { /** * Slack API token + * @var string */ - private string $token; + private $token; /** * Instance of the SlackRecord util class preparing data for Slack API. + * @var SlackRecord */ - private SlackRecord $slackRecord; + private $slackRecord; /** * @param string $token Slack API token @@ -52,11 +55,11 @@ class SlackHandler extends SocketHandler ?string $username = null, bool $useAttachment = true, ?string $iconEmoji = null, - $level = Level::Critical, + $level = Logger::CRITICAL, bool $bubble = true, bool $useShortAttachment = false, bool $includeContextAndExtra = false, - array $excludeFields = [], + array $excludeFields = array(), bool $persistent = false, float $timeout = 0.0, float $writingTimeout = 10.0, @@ -102,9 +105,9 @@ class SlackHandler extends SocketHandler } /** - * @inheritDoc + * {@inheritDoc} */ - protected function generateDataStream(LogRecord $record): string + protected function generateDataStream(array $record): string { $content = $this->buildContent($record); @@ -113,8 +116,10 @@ class SlackHandler extends SocketHandler /** * Builds the body of API call + * + * @phpstan-param FormattedRecord $record */ - private function buildContent(LogRecord $record): string + private function buildContent(array $record): string { $dataArray = $this->prepareContentData($record); @@ -122,14 +127,15 @@ class SlackHandler extends SocketHandler } /** + * @phpstan-param FormattedRecord $record * @return string[] */ - protected function prepareContentData(LogRecord $record): array + protected function prepareContentData(array $record): array { $dataArray = $this->slackRecord->getSlackData($record); $dataArray['token'] = $this->token; - if (isset($dataArray['attachments']) && is_array($dataArray['attachments']) && \count($dataArray['attachments']) > 0) { + if (!empty($dataArray['attachments'])) { $dataArray['attachments'] = Utils::jsonEncode($dataArray['attachments']); } @@ -151,9 +157,9 @@ class SlackHandler extends SocketHandler } /** - * @inheritDoc + * {@inheritDoc} */ - protected function write(LogRecord $record): void + protected function write(array $record): void { parent::write($record); $this->finalizeWrite(); diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/SlackWebhookHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/SlackWebhookHandler.php index 14ed6b1fb..8ae3c7882 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/SlackWebhookHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/SlackWebhookHandler.php @@ -12,10 +12,9 @@ namespace Monolog\Handler; use Monolog\Formatter\FormatterInterface; -use Monolog\Level; +use Monolog\Logger; use Monolog\Utils; use Monolog\Handler\Slack\SlackRecord; -use Monolog\LogRecord; /** * Sends notifications through Slack Webhooks @@ -27,13 +26,15 @@ class SlackWebhookHandler extends AbstractProcessingHandler { /** * Slack Webhook token + * @var string */ - private string $webhookUrl; + private $webhookUrl; /** * Instance of the SlackRecord util class preparing data for Slack API. + * @var SlackRecord */ - private SlackRecord $slackRecord; + private $slackRecord; /** * @param string $webhookUrl Slack Webhook URL @@ -53,9 +54,9 @@ class SlackWebhookHandler extends AbstractProcessingHandler ?string $iconEmoji = null, bool $useShortAttachment = false, bool $includeContextAndExtra = false, - $level = Level::Critical, + $level = Logger::CRITICAL, bool $bubble = true, - array $excludeFields = [] + array $excludeFields = array() ) { if (!extension_loaded('curl')) { throw new MissingExtensionException('The curl extension is needed to use the SlackWebhookHandler'); @@ -87,21 +88,21 @@ class SlackWebhookHandler extends AbstractProcessingHandler } /** - * @inheritDoc + * {@inheritDoc} */ - protected function write(LogRecord $record): void + protected function write(array $record): void { $postData = $this->slackRecord->getSlackData($record); $postString = Utils::jsonEncode($postData); $ch = curl_init(); - $options = [ + $options = array( CURLOPT_URL => $this->webhookUrl, CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, - CURLOPT_HTTPHEADER => ['Content-type: application/json'], + CURLOPT_HTTPHEADER => array('Content-type: application/json'), CURLOPT_POSTFIELDS => $postString, - ]; + ); if (defined('CURLOPT_SAFE_UPLOAD')) { $options[CURLOPT_SAFE_UPLOAD] = true; } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/SocketHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/SocketHandler.php index c5f708884..21701afa2 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/SocketHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/SocketHandler.php @@ -11,29 +11,41 @@ namespace Monolog\Handler; -use Monolog\Level; -use Monolog\LogRecord; +use Monolog\Logger; /** * Stores to any socket - uses fsockopen() or pfsockopen(). * * @author Pablo de Leon Belloc * @see http://php.net/manual/en/function.fsockopen.php + * + * @phpstan-import-type Record from \Monolog\Logger + * @phpstan-import-type FormattedRecord from AbstractProcessingHandler */ class SocketHandler extends AbstractProcessingHandler { - private string $connectionString; - private float $connectionTimeout; + /** @var string */ + private $connectionString; + /** @var float */ + private $connectionTimeout; /** @var resource|null */ private $resource; - private float $timeout; - private float $writingTimeout; - private int|null $lastSentBytes = null; - private int|null $chunkSize; - private bool $persistent; - private int|null $errno = null; - private string|null $errstr = null; - private float|null $lastWritingAt = null; + /** @var float */ + private $timeout; + /** @var float */ + private $writingTimeout; + /** @var ?int */ + private $lastSentBytes = null; + /** @var ?int */ + private $chunkSize; + /** @var bool */ + private $persistent; + /** @var ?int */ + private $errno = null; + /** @var ?string */ + private $errstr = null; + /** @var ?float */ + private $lastWritingAt = null; /** * @param string $connectionString Socket connection string @@ -44,11 +56,11 @@ class SocketHandler extends AbstractProcessingHandler * established * @param int|null $chunkSize Sets the chunk size. Only has effect during connection in the writing cycle * - * @throws \InvalidArgumentException If an invalid timeout value (less than 0) is passed. + * @throws \InvalidArgumentException If an invalid timeout value (less than 0) is passed. */ public function __construct( string $connectionString, - $level = Level::Debug, + $level = Logger::DEBUG, bool $bubble = true, bool $persistent = false, float $timeout = 0.0, @@ -75,12 +87,12 @@ class SocketHandler extends AbstractProcessingHandler /** * Connect (if necessary) and write to the socket * - * @inheritDoc + * {@inheritDoc} * * @throws \UnexpectedValueException * @throws \RuntimeException */ - protected function write(LogRecord $record): void + protected function write(array $record): void { $this->connectIfNotConnected(); $data = $this->generateDataStream($record); @@ -201,6 +213,8 @@ class SocketHandler extends AbstractProcessingHandler /** * Get current local writing timeout + * + * @return float */ public function getWritingTimeout(): float { @@ -250,8 +264,10 @@ class SocketHandler extends AbstractProcessingHandler * Wrapper to allow mocking * * @see http://php.net/manual/en/function.stream-set-timeout.php + * + * @return bool */ - protected function streamSetTimeout(): bool + protected function streamSetTimeout() { $seconds = floor($this->timeout); $microseconds = round(($this->timeout - $seconds) * 1e6); @@ -268,9 +284,9 @@ class SocketHandler extends AbstractProcessingHandler * * @see http://php.net/manual/en/function.stream-set-chunk-size.php * - * @return int|false + * @return int|bool */ - protected function streamSetChunkSize(): int|bool + protected function streamSetChunkSize() { if (!is_resource($this->resource)) { throw new \LogicException('streamSetChunkSize called but $this->resource is not a resource'); @@ -286,9 +302,9 @@ class SocketHandler extends AbstractProcessingHandler /** * Wrapper to allow mocking * - * @return int|false + * @return int|bool */ - protected function fwrite(string $data): int|bool + protected function fwrite(string $data) { if (!is_resource($this->resource)) { throw new \LogicException('fwrite called but $this->resource is not a resource'); @@ -302,7 +318,7 @@ class SocketHandler extends AbstractProcessingHandler * * @return mixed[]|bool */ - protected function streamGetMetadata(): array|bool + protected function streamGetMetadata() { if (!is_resource($this->resource)) { throw new \LogicException('streamGetMetadata called but $this->resource is not a resource'); @@ -326,9 +342,12 @@ class SocketHandler extends AbstractProcessingHandler $this->connect(); } - protected function generateDataStream(LogRecord $record): string + /** + * @phpstan-param FormattedRecord $record + */ + protected function generateDataStream(array $record): string { - return (string) $record->formatted; + return (string) $record['formatted']; } /** @@ -368,7 +387,7 @@ class SocketHandler extends AbstractProcessingHandler private function setStreamChunkSize(): void { - if (null !== $this->chunkSize && false === $this->streamSetChunkSize()) { + if ($this->chunkSize && !$this->streamSetChunkSize()) { throw new \UnexpectedValueException("Failed setting chunk size with stream_set_chunk_size()"); } } @@ -389,7 +408,7 @@ class SocketHandler extends AbstractProcessingHandler } $sent += $chunk; $socketInfo = $this->streamGetMetadata(); - if (is_array($socketInfo) && (bool) $socketInfo['timed_out']) { + if (is_array($socketInfo) && $socketInfo['timed_out']) { throw new \RuntimeException("Write timed-out"); } @@ -418,7 +437,7 @@ class SocketHandler extends AbstractProcessingHandler usleep(100); } - if ((microtime(true) - (float) $this->lastWritingAt) >= $this->writingTimeout) { + if ((microtime(true) - $this->lastWritingAt) >= $this->writingTimeout) { $this->closeSocket(); return true; diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/SqsHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/SqsHandler.php index b4512a601..dcf282b45 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/SqsHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/SqsHandler.php @@ -12,9 +12,8 @@ namespace Monolog\Handler; use Aws\Sqs\SqsClient; -use Monolog\Level; +use Monolog\Logger; use Monolog\Utils; -use Monolog\LogRecord; /** * Writes to any sqs queue. @@ -28,10 +27,12 @@ class SqsHandler extends AbstractProcessingHandler /** 100 KB in bytes - head message size for new error log */ protected const HEAD_MESSAGE_SIZE = 102400; - private SqsClient $client; - private string $queueUrl; + /** @var SqsClient */ + private $client; + /** @var string */ + private $queueUrl; - public function __construct(SqsClient $sqsClient, string $queueUrl, int|string|Level $level = Level::Debug, bool $bubble = true) + public function __construct(SqsClient $sqsClient, string $queueUrl, $level = Logger::DEBUG, bool $bubble = true) { parent::__construct($level, $bubble); @@ -40,15 +41,15 @@ class SqsHandler extends AbstractProcessingHandler } /** - * @inheritDoc + * {@inheritDoc} */ - protected function write(LogRecord $record): void + protected function write(array $record): void { - if (!isset($record->formatted) || 'string' !== gettype($record->formatted)) { + if (!isset($record['formatted']) || 'string' !== gettype($record['formatted'])) { throw new \InvalidArgumentException('SqsHandler accepts only formatted records as a string' . Utils::getRecordMessageForException($record)); } - $messageBody = $record->formatted; + $messageBody = $record['formatted']; if (strlen($messageBody) >= static::MAX_MESSAGE_SIZE) { $messageBody = Utils::substr($messageBody, 0, static::HEAD_MESSAGE_SIZE); } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php index 027a7217d..651835122 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php @@ -11,9 +11,8 @@ namespace Monolog\Handler; -use Monolog\Level; +use Monolog\Logger; use Monolog\Utils; -use Monolog\LogRecord; /** * Stores to any stream resource @@ -21,21 +20,29 @@ use Monolog\LogRecord; * Can be used to store into php://stderr, remote and local files, etc. * * @author Jordi Boggiano + * + * @phpstan-import-type FormattedRecord from AbstractProcessingHandler */ class StreamHandler extends AbstractProcessingHandler { + /** @const int */ protected const MAX_CHUNK_SIZE = 2147483647; - /** 10MB */ + /** @const int 10MB */ protected const DEFAULT_CHUNK_SIZE = 10 * 1024 * 1024; - protected int $streamChunkSize; + /** @var int */ + protected $streamChunkSize; /** @var resource|null */ protected $stream; - protected string|null $url = null; - private string|null $errorMessage = null; - protected int|null $filePermission; - protected bool $useLocking; + /** @var ?string */ + protected $url = null; + /** @var ?string */ + private $errorMessage = null; + /** @var ?int */ + protected $filePermission; + /** @var bool */ + protected $useLocking; /** @var true|null */ - private bool|null $dirCreated = null; + private $dirCreated = null; /** * @param resource|string $stream If a missing path can't be created, an UnexpectedValueException will be thrown on first write @@ -44,7 +51,7 @@ class StreamHandler extends AbstractProcessingHandler * * @throws \InvalidArgumentException If stream is not a resource or string */ - public function __construct($stream, int|string|Level $level = Level::Debug, bool $bubble = true, ?int $filePermission = null, bool $useLocking = false) + public function __construct($stream, $level = Logger::DEBUG, bool $bubble = true, ?int $filePermission = null, bool $useLocking = false) { parent::__construct($level, $bubble); @@ -76,11 +83,11 @@ class StreamHandler extends AbstractProcessingHandler } /** - * @inheritDoc + * {@inheritDoc} */ public function close(): void { - if (null !== $this->url && is_resource($this->stream)) { + if ($this->url && is_resource($this->stream)) { fclose($this->stream); } $this->stream = null; @@ -99,21 +106,26 @@ class StreamHandler extends AbstractProcessingHandler /** * Return the stream URL if it was configured with a URL and not an active resource + * + * @return string|null */ public function getUrl(): ?string { return $this->url; } + /** + * @return int + */ public function getStreamChunkSize(): int { return $this->streamChunkSize; } /** - * @inheritDoc + * {@inheritDoc} */ - protected function write(LogRecord $record): void + protected function write(array $record): void { if (!is_resource($this->stream)) { $url = $this->url; @@ -138,6 +150,10 @@ class StreamHandler extends AbstractProcessingHandler } $stream = $this->stream; + if (!is_resource($stream)) { + throw new \LogicException('No stream was opened yet' . Utils::getRecordMessageForException($record)); + } + if ($this->useLocking) { // ignoring errors here, there's not much we can do about them flock($stream, LOCK_EX); @@ -153,10 +169,13 @@ class StreamHandler extends AbstractProcessingHandler /** * Write to stream * @param resource $stream + * @param array $record + * + * @phpstan-param FormattedRecord $record */ - protected function streamWrite($stream, LogRecord $record): void + protected function streamWrite($stream, array $record): void { - fwrite($stream, (string) $record->formatted); + fwrite($stream, (string) $record['formatted']); } private function customErrorHandler(int $code, string $msg): bool @@ -183,7 +202,7 @@ class StreamHandler extends AbstractProcessingHandler private function createDir(string $url): void { // Do not try to create dir if it has already been tried. - if (true === $this->dirCreated) { + if ($this->dirCreated) { return; } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/SymfonyMailerHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/SymfonyMailerHandler.php index 842b6577f..130e6f1f3 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/SymfonyMailerHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/SymfonyMailerHandler.php @@ -11,10 +11,7 @@ namespace Monolog\Handler; -use Closure; -use Monolog\Level; use Monolog\Logger; -use Monolog\LogRecord; use Monolog\Utils; use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\LineFormatter; @@ -26,20 +23,23 @@ use Symfony\Component\Mime\Email; * SymfonyMailerHandler uses Symfony's Mailer component to send the emails * * @author Jordi Boggiano + * + * @phpstan-import-type Record from \Monolog\Logger */ class SymfonyMailerHandler extends MailHandler { - protected MailerInterface|TransportInterface $mailer; - /** @var Email|Closure(string, LogRecord[]): Email */ - private Email|Closure $emailTemplate; + /** @var MailerInterface|TransportInterface */ + protected $mailer; + /** @var Email|callable(string, Record[]): Email */ + private $emailTemplate; /** - * @phpstan-param Email|Closure(string, LogRecord[]): Email $email + * @psalm-param Email|callable(string, Record[]): Email $email * * @param MailerInterface|TransportInterface $mailer The mailer to use - * @param Closure|Email $email An email template, the subject/body will be replaced + * @param callable|Email $email An email template, the subject/body will be replaced */ - public function __construct($mailer, Email|Closure $email, int|string|Level $level = Level::Error, bool $bubble = true) + public function __construct($mailer, $email, $level = Logger::ERROR, bool $bubble = true) { parent::__construct($level, $bubble); @@ -68,8 +68,10 @@ class SymfonyMailerHandler extends MailHandler /** * Creates instance of Email to be sent * - * @param string $content formatted email body to be sent - * @param LogRecord[] $records Log records that formed the content + * @param string $content formatted email body to be sent + * @param array $records Log records that formed the content + * + * @phpstan-param Record[] $records */ protected function buildMessage(string $content, array $records): Email { @@ -82,10 +84,10 @@ class SymfonyMailerHandler extends MailHandler if (!$message instanceof Email) { $record = reset($records); - throw new \InvalidArgumentException('Could not resolve message as instance of Email or a callable returning it' . ($record instanceof LogRecord ? Utils::getRecordMessageForException($record) : '')); + throw new \InvalidArgumentException('Could not resolve message as instance of Email or a callable returning it' . ($record ? Utils::getRecordMessageForException($record) : '')); } - if (\count($records) > 0) { + if ($records) { $subjectFormatter = $this->getSubjectFormatter($message->getSubject()); $message->subject($subjectFormatter->format($this->getHighestRecord($records))); } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/SyslogHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/SyslogHandler.php index 0816a0119..1d543b7ec 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/SyslogHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/SyslogHandler.php @@ -11,9 +11,8 @@ namespace Monolog\Handler; -use Monolog\Level; +use Monolog\Logger; use Monolog\Utils; -use Monolog\LogRecord; /** * Logs to syslog service. @@ -30,14 +29,17 @@ use Monolog\LogRecord; */ class SyslogHandler extends AbstractSyslogHandler { - protected string $ident; - protected int $logopts; + /** @var string */ + protected $ident; + /** @var int */ + protected $logopts; /** + * @param string $ident * @param string|int $facility Either one of the names of the keys in $this->facilities, or a LOG_* facility constant * @param int $logopts Option flags for the openlog() call, defaults to LOG_PID */ - public function __construct(string $ident, string|int $facility = LOG_USER, int|string|Level $level = Level::Debug, bool $bubble = true, int $logopts = LOG_PID) + public function __construct(string $ident, $facility = LOG_USER, $level = Logger::DEBUG, bool $bubble = true, int $logopts = LOG_PID) { parent::__construct($facility, $level, $bubble); @@ -46,7 +48,7 @@ class SyslogHandler extends AbstractSyslogHandler } /** - * @inheritDoc + * {@inheritDoc} */ public function close(): void { @@ -54,13 +56,13 @@ class SyslogHandler extends AbstractSyslogHandler } /** - * @inheritDoc + * {@inheritDoc} */ - protected function write(LogRecord $record): void + protected function write(array $record): void { if (!openlog($this->ident, $this->logopts, $this->facility)) { throw new \LogicException('Can\'t open syslog for ident "'.$this->ident.'" and facility "'.$this->facility.'"' . Utils::getRecordMessageForException($record)); } - syslog($this->toSyslogPriority($record->level), (string) $record->formatted); + syslog($this->logLevels[$record['level']], (string) $record['formatted']); } } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/SyslogUdp/UdpSocket.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/SyslogUdp/UdpSocket.php index 6a4833450..dbd8ef69d 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/SyslogUdp/UdpSocket.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/SyslogUdp/UdpSocket.php @@ -18,9 +18,12 @@ class UdpSocket { protected const DATAGRAM_MAX_LENGTH = 65023; - protected string $ip; - protected int $port; - protected ?Socket $socket = null; + /** @var string */ + protected $ip; + /** @var int */ + protected $port; + /** @var resource|Socket|null */ + protected $socket = null; public function __construct(string $ip, int $port = 514) { @@ -28,20 +31,28 @@ class UdpSocket $this->port = $port; } - public function write(string $line, string $header = ""): void + /** + * @param string $line + * @param string $header + * @return void + */ + public function write($line, $header = "") { $this->send($this->assembleMessage($line, $header)); } public function close(): void { - if ($this->socket instanceof Socket) { + if (is_resource($this->socket) || $this->socket instanceof Socket) { socket_close($this->socket); $this->socket = null; } } - protected function getSocket(): Socket + /** + * @return resource|Socket + */ + protected function getSocket() { if (null !== $this->socket) { return $this->socket; @@ -55,12 +66,12 @@ class UdpSocket $protocol = IPPROTO_IP; } - $socket = socket_create($domain, SOCK_DGRAM, $protocol); - if ($socket instanceof Socket) { - return $this->socket = $socket; + $this->socket = socket_create($domain, SOCK_DGRAM, $protocol) ?: null; + if (null === $this->socket) { + throw new \RuntimeException('The UdpSocket to '.$this->ip.':'.$this->port.' could not be opened via socket_create'); } - throw new \RuntimeException('The UdpSocket to '.$this->ip.':'.$this->port.' could not be opened via socket_create'); + return $this->socket; } protected function send(string $chunk): void diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php index abb8be9b2..deaa19f80 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php @@ -12,9 +12,8 @@ namespace Monolog\Handler; use DateTimeInterface; +use Monolog\Logger; use Monolog\Handler\SyslogUdp\UdpSocket; -use Monolog\Level; -use Monolog\LogRecord; use Monolog\Utils; /** @@ -30,29 +29,31 @@ class SyslogUdpHandler extends AbstractSyslogHandler const RFC5424e = 2; /** @var array */ - private array $dateFormats = [ + private $dateFormats = array( self::RFC3164 => 'M d H:i:s', self::RFC5424 => \DateTime::RFC3339, self::RFC5424e => \DateTime::RFC3339_EXTENDED, - ]; + ); - protected UdpSocket $socket; - protected string $ident; + /** @var UdpSocket */ + protected $socket; + /** @var string */ + protected $ident; /** @var self::RFC* */ - protected int $rfc; + protected $rfc; /** - * @param string $host Either IP/hostname or a path to a unix socket (port must be 0 then) - * @param int $port Port number, or 0 if $host is a unix socket - * @param string|int $facility Either one of the names of the keys in $this->facilities, or a LOG_* facility constant - * @param bool $bubble Whether the messages that are handled can bubble up the stack or not - * @param string $ident Program name or tag for each log message. - * @param int $rfc RFC to format the message for. + * @param string $host Either IP/hostname or a path to a unix socket (port must be 0 then) + * @param int $port Port number, or 0 if $host is a unix socket + * @param string|int $facility Either one of the names of the keys in $this->facilities, or a LOG_* facility constant + * @param bool $bubble Whether the messages that are handled can bubble up the stack or not + * @param string $ident Program name or tag for each log message. + * @param int $rfc RFC to format the message for. * @throws MissingExtensionException * * @phpstan-param self::RFC* $rfc */ - public function __construct(string $host, int $port = 514, string|int $facility = LOG_USER, int|string|Level $level = Level::Debug, bool $bubble = true, string $ident = 'php', int $rfc = self::RFC5424) + public function __construct(string $host, int $port = 514, $facility = LOG_USER, $level = Logger::DEBUG, bool $bubble = true, string $ident = 'php', int $rfc = self::RFC5424) { if (!extension_loaded('sockets')) { throw new MissingExtensionException('The sockets extension is required to use the SyslogUdpHandler'); @@ -66,11 +67,11 @@ class SyslogUdpHandler extends AbstractSyslogHandler $this->socket = new UdpSocket($host, $port); } - protected function write(LogRecord $record): void + protected function write(array $record): void { - $lines = $this->splitMessageIntoLines($record->formatted); + $lines = $this->splitMessageIntoLines($record['formatted']); - $header = $this->makeCommonSyslogHeader($this->toSyslogPriority($record->level), $record->datetime); + $header = $this->makeCommonSyslogHeader($this->logLevels[$record['level']], $record['datetime']); foreach ($lines as $line) { $this->socket->write($line, $header); @@ -95,7 +96,6 @@ class SyslogUdpHandler extends AbstractSyslogHandler $lines = preg_split('/$\R?^/m', (string) $message, -1, PREG_SPLIT_NO_EMPTY); if (false === $lines) { $pcreErrorCode = preg_last_error(); - throw new \RuntimeException('Could not preg_split: ' . $pcreErrorCode . ' / ' . Utils::pcreLastErrorMessage($pcreErrorCode)); } @@ -109,13 +109,11 @@ class SyslogUdpHandler extends AbstractSyslogHandler { $priority = $severity + $this->facility; - $pid = getmypid(); - if (false === $pid) { + if (!$pid = getmypid()) { $pid = '-'; } - $hostname = gethostname(); - if (false === $hostname) { + if (!$hostname = gethostname()) { $hostname = '-'; } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/TelegramBotHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/TelegramBotHandler.php index 2e1be9f6b..8912eba51 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/TelegramBotHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/TelegramBotHandler.php @@ -12,9 +12,8 @@ namespace Monolog\Handler; use RuntimeException; -use Monolog\Level; +use Monolog\Logger; use Monolog\Utils; -use Monolog\LogRecord; /** * Handler send logs to Telegram using Telegram Bot API. @@ -29,6 +28,8 @@ use Monolog\LogRecord; * @link https://core.telegram.org/bots/api * * @author Mazur Alexandr + * + * @phpstan-import-type Record from \Monolog\Logger */ class TelegramBotHandler extends AbstractProcessingHandler { @@ -51,61 +52,69 @@ class TelegramBotHandler extends AbstractProcessingHandler /** * Telegram bot access token provided by BotFather. * Create telegram bot with https://telegram.me/BotFather and use access token from it. + * @var string */ - private string $apiKey; + private $apiKey; /** * Telegram channel name. * Since to start with '@' symbol as prefix. + * @var string */ - private string $channel; + private $channel; /** * The kind of formatting that is used for the message. * See available options at https://core.telegram.org/bots/api#formatting-options * or in AVAILABLE_PARSE_MODES + * @var ?string */ - private string|null $parseMode; + private $parseMode; /** * Disables link previews for links in the message. + * @var ?bool */ - private bool|null $disableWebPagePreview; + private $disableWebPagePreview; /** * Sends the message silently. Users will receive a notification with no sound. + * @var ?bool */ - private bool|null $disableNotification; + private $disableNotification; /** * True - split a message longer than MAX_MESSAGE_LENGTH into parts and send in multiple messages. * False - truncates a message that is too long. + * @var bool */ - private bool $splitLongMessages; + private $splitLongMessages; /** * Adds 1-second delay between sending a split message (according to Telegram API to avoid 429 Too Many Requests). + * @var bool */ - private bool $delayBetweenMessages; + private $delayBetweenMessages; /** - * @param string $apiKey Telegram bot access token provided by BotFather - * @param string $channel Telegram channel name - * @param bool $splitLongMessages Split a message longer than MAX_MESSAGE_LENGTH into parts and send in multiple messages - * @param bool $delayBetweenMessages Adds delay between sending a split message according to Telegram API + * @param string $apiKey Telegram bot access token provided by BotFather + * @param string $channel Telegram channel name + * @param bool $splitLongMessages Split a message longer than MAX_MESSAGE_LENGTH into parts and send in multiple messages + * @param bool $delayBetweenMessages Adds delay between sending a split message according to Telegram API * @throws MissingExtensionException */ public function __construct( string $apiKey, string $channel, - $level = Level::Debug, + $level = Logger::DEBUG, bool $bubble = true, string $parseMode = null, bool $disableWebPagePreview = null, bool $disableNotification = null, bool $splitLongMessages = false, bool $delayBetweenMessages = false - ) { + ) + { if (!extension_loaded('curl')) { throw new MissingExtensionException('The curl extension is needed to use the TelegramBotHandler'); } @@ -123,7 +132,7 @@ class TelegramBotHandler extends AbstractProcessingHandler public function setParseMode(string $parseMode = null): self { - if ($parseMode !== null && !in_array($parseMode, self::AVAILABLE_PARSE_MODES, true)) { + if ($parseMode !== null && !in_array($parseMode, self::AVAILABLE_PARSE_MODES)) { throw new \InvalidArgumentException('Unknown parseMode, use one of these: ' . implode(', ', self::AVAILABLE_PARSE_MODES) . '.'); } @@ -149,6 +158,7 @@ class TelegramBotHandler extends AbstractProcessingHandler /** * True - split a message longer than MAX_MESSAGE_LENGTH into parts and send in multiple messages. * False - truncates a message that is too long. + * @param bool $splitLongMessages * @return $this */ public function splitLongMessages(bool $splitLongMessages = false): self @@ -160,6 +170,7 @@ class TelegramBotHandler extends AbstractProcessingHandler /** * Adds 1-second delay between sending a split message (according to Telegram API to avoid 429 Too Many Requests). + * @param bool $delayBetweenMessages * @return $this */ public function delayBetweenMessages(bool $delayBetweenMessages = false): self @@ -170,10 +181,11 @@ class TelegramBotHandler extends AbstractProcessingHandler } /** - * @inheritDoc + * {@inheritDoc} */ public function handleBatch(array $records): void { + /** @var Record[] $messages */ $messages = []; foreach ($records as $record) { @@ -181,28 +193,30 @@ class TelegramBotHandler extends AbstractProcessingHandler continue; } - if (\count($this->processors) > 0) { + if ($this->processors) { + /** @var Record $record */ $record = $this->processRecord($record); } $messages[] = $record; } - if (\count($messages) > 0) { - $this->send((string) $this->getFormatter()->formatBatch($messages)); + if (!empty($messages)) { + $this->send((string)$this->getFormatter()->formatBatch($messages)); } } /** * @inheritDoc */ - protected function write(LogRecord $record): void + protected function write(array $record): void { - $this->send($record->formatted); + $this->send($record['formatted']); } /** * Send request to @link https://api.telegram.org/bot on SendMessage action. + * @param string $message */ protected function send(string $message): void { @@ -245,6 +259,7 @@ class TelegramBotHandler extends AbstractProcessingHandler /** * Handle a message that is too long: truncates or splits into several + * @param string $message * @return string[] */ private function handleMessageLength(string $message): array diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/TestHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/TestHandler.php index 1884f83fc..0986da270 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/TestHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/TestHandler.php @@ -11,10 +11,8 @@ namespace Monolog\Handler; -use Monolog\Level; use Monolog\Logger; use Psr\Log\LogLevel; -use Monolog\LogRecord; /** * Used for testing purposes. @@ -67,67 +65,85 @@ use Monolog\LogRecord; * @method bool hasNoticeThatPasses($message) * @method bool hasInfoThatPasses($message) * @method bool hasDebugThatPasses($message) + * + * @phpstan-import-type Record from \Monolog\Logger + * @phpstan-import-type Level from \Monolog\Logger + * @phpstan-import-type LevelName from \Monolog\Logger */ class TestHandler extends AbstractProcessingHandler { - /** @var LogRecord[] */ - protected array $records = []; - /** @phpstan-var array, LogRecord[]> */ - protected array $recordsByLevel = []; - private bool $skipReset = false; + /** @var Record[] */ + protected $records = []; + /** @var array */ + protected $recordsByLevel = []; + /** @var bool */ + private $skipReset = false; /** - * @return array + * @return array + * + * @phpstan-return Record[] */ - public function getRecords(): array + public function getRecords() { return $this->records; } - public function clear(): void + /** + * @return void + */ + public function clear() { $this->records = []; $this->recordsByLevel = []; } - public function reset(): void + /** + * @return void + */ + public function reset() { if (!$this->skipReset) { $this->clear(); } } - public function setSkipReset(bool $skipReset): void + /** + * @return void + */ + public function setSkipReset(bool $skipReset) { $this->skipReset = $skipReset; } /** - * @param int|string|Level|LogLevel::* $level Logging level value or name + * @param string|int $level Logging level value or name * - * @phpstan-param value-of|value-of|Level|LogLevel::* $level + * @phpstan-param Level|LevelName|LogLevel::* $level */ - public function hasRecords(int|string|Level $level): bool + public function hasRecords($level): bool { - return isset($this->recordsByLevel[Logger::toMonologLevel($level)->value]); + return isset($this->recordsByLevel[Logger::toMonologLevel($level)]); } /** - * @param string|array $recordAssertions Either a message string or an array containing message and optionally context keys that will be checked against all records + * @param string|array $record Either a message string or an array containing message and optionally context keys that will be checked against all records + * @param string|int $level Logging level value or name * - * @phpstan-param array{message: string, context?: mixed[]}|string $recordAssertions + * @phpstan-param array{message: string, context?: mixed[]}|string $record + * @phpstan-param Level|LevelName|LogLevel::* $level */ - public function hasRecord(string|array $recordAssertions, Level $level): bool + public function hasRecord($record, $level): bool { - if (is_string($recordAssertions)) { - $recordAssertions = ['message' => $recordAssertions]; + if (is_string($record)) { + $record = array('message' => $record); } - return $this->hasRecordThatPasses(function (LogRecord $rec) use ($recordAssertions) { - if ($rec->message !== $recordAssertions['message']) { + return $this->hasRecordThatPasses(function ($rec) use ($record) { + if ($rec['message'] !== $record['message']) { return false; } - if (isset($recordAssertions['context']) && $rec->context !== $recordAssertions['context']) { + if (isset($record['context']) && $rec['context'] !== $record['context']) { return false; } @@ -135,29 +151,47 @@ class TestHandler extends AbstractProcessingHandler }, $level); } - public function hasRecordThatContains(string $message, Level $level): bool + /** + * @param string|int $level Logging level value or name + * + * @phpstan-param Level|LevelName|LogLevel::* $level + */ + public function hasRecordThatContains(string $message, $level): bool { - return $this->hasRecordThatPasses(fn (LogRecord $rec) => str_contains($rec->message, $message), $level); - } - - public function hasRecordThatMatches(string $regex, Level $level): bool - { - return $this->hasRecordThatPasses(fn (LogRecord $rec) => preg_match($regex, $rec->message) > 0, $level); + return $this->hasRecordThatPasses(function ($rec) use ($message) { + return strpos($rec['message'], $message) !== false; + }, $level); } /** - * @phpstan-param callable(LogRecord, int): mixed $predicate + * @param string|int $level Logging level value or name + * + * @phpstan-param Level|LevelName|LogLevel::* $level */ - public function hasRecordThatPasses(callable $predicate, Level $level): bool + public function hasRecordThatMatches(string $regex, $level): bool + { + return $this->hasRecordThatPasses(function (array $rec) use ($regex): bool { + return preg_match($regex, $rec['message']) > 0; + }, $level); + } + + /** + * @param string|int $level Logging level value or name + * @return bool + * + * @psalm-param callable(Record, int): mixed $predicate + * @phpstan-param Level|LevelName|LogLevel::* $level + */ + public function hasRecordThatPasses(callable $predicate, $level) { $level = Logger::toMonologLevel($level); - if (!isset($this->recordsByLevel[$level->value])) { + if (!isset($this->recordsByLevel[$level])) { return false; } - foreach ($this->recordsByLevel[$level->value] as $i => $rec) { - if ((bool) $predicate($rec, $i)) { + foreach ($this->recordsByLevel[$level] as $i => $rec) { + if ($predicate($rec, $i)) { return true; } } @@ -166,22 +200,24 @@ class TestHandler extends AbstractProcessingHandler } /** - * @inheritDoc + * {@inheritDoc} */ - protected function write(LogRecord $record): void + protected function write(array $record): void { - $this->recordsByLevel[$record->level->value][] = $record; + $this->recordsByLevel[$record['level']][] = $record; $this->records[] = $record; } /** - * @param mixed[] $args + * @param string $method + * @param mixed[] $args + * @return bool */ - public function __call(string $method, array $args): bool + public function __call($method, $args) { if (preg_match('/(.*)(Debug|Info|Notice|Warning|Error|Critical|Alert|Emergency)(.*)/', $method, $matches) > 0) { $genericMethod = $matches[1] . ('Records' !== $matches[3] ? 'Record' : '') . $matches[3]; - $level = constant(Level::class.'::' . $matches[2]); + $level = constant('Monolog\Logger::' . strtoupper($matches[2])); $callback = [$this, $genericMethod]; if (is_callable($callback)) { $args[] = $level; diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/WebRequestRecognizerTrait.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/WebRequestRecognizerTrait.php index 9c12c3d56..c81835288 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/WebRequestRecognizerTrait.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/WebRequestRecognizerTrait.php @@ -15,6 +15,7 @@ trait WebRequestRecognizerTrait { /** * Checks if PHP's serving a web request + * @return bool */ protected function isWebRequest(): bool { diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php index 2dbc5fe8d..b6d3d3b19 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php @@ -11,30 +11,30 @@ namespace Monolog\Handler; -use Monolog\LogRecord; -use Throwable; - /** * Forwards records to multiple handlers suppressing failures of each handler * and continuing through to give every handler a chance to succeed. * * @author Craig D'Amelio + * + * @phpstan-import-type Record from \Monolog\Logger */ class WhatFailureGroupHandler extends GroupHandler { /** - * @inheritDoc + * {@inheritDoc} */ - public function handle(LogRecord $record): bool + public function handle(array $record): bool { - if (\count($this->processors) > 0) { + if ($this->processors) { + /** @var Record $record */ $record = $this->processRecord($record); } foreach ($this->handlers as $handler) { try { $handler->handle($record); - } catch (Throwable) { + } catch (\Throwable $e) { // What failure? } } @@ -43,22 +43,37 @@ class WhatFailureGroupHandler extends GroupHandler } /** - * @inheritDoc + * {@inheritDoc} */ public function handleBatch(array $records): void { - if (\count($this->processors) > 0) { - $processed = []; + if ($this->processors) { + $processed = array(); foreach ($records as $record) { $processed[] = $this->processRecord($record); } + /** @var Record[] $records */ $records = $processed; } foreach ($this->handlers as $handler) { try { $handler->handleBatch($records); - } catch (Throwable) { + } catch (\Throwable $e) { + // What failure? + } + } + } + + /** + * {@inheritDoc} + */ + public function close(): void + { + foreach ($this->handlers as $handler) { + try { + $handler->close(); + } catch (\Throwable $e) { // What failure? } } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Handler/ZendMonitorHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/Handler/ZendMonitorHandler.php index 1e71194bc..ddd46d8c5 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Handler/ZendMonitorHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Handler/ZendMonitorHandler.php @@ -13,67 +13,70 @@ namespace Monolog\Handler; use Monolog\Formatter\FormatterInterface; use Monolog\Formatter\NormalizerFormatter; -use Monolog\Level; -use Monolog\LogRecord; +use Monolog\Logger; /** * Handler sending logs to Zend Monitor * * @author Christian Bergau * @author Jason Davis + * + * @phpstan-import-type FormattedRecord from AbstractProcessingHandler */ class ZendMonitorHandler extends AbstractProcessingHandler { + /** + * Monolog level / ZendMonitor Custom Event priority map + * + * @var array + */ + protected $levelMap = []; + /** * @throws MissingExtensionException */ - public function __construct(int|string|Level $level = Level::Debug, bool $bubble = true) + public function __construct($level = Logger::DEBUG, bool $bubble = true) { if (!function_exists('zend_monitor_custom_event')) { throw new MissingExtensionException( 'You must have Zend Server installed with Zend Monitor enabled in order to use this handler' ); } - + //zend monitor constants are not defined if zend monitor is not enabled. + $this->levelMap = [ + Logger::DEBUG => \ZEND_MONITOR_EVENT_SEVERITY_INFO, + Logger::INFO => \ZEND_MONITOR_EVENT_SEVERITY_INFO, + Logger::NOTICE => \ZEND_MONITOR_EVENT_SEVERITY_INFO, + Logger::WARNING => \ZEND_MONITOR_EVENT_SEVERITY_WARNING, + Logger::ERROR => \ZEND_MONITOR_EVENT_SEVERITY_ERROR, + Logger::CRITICAL => \ZEND_MONITOR_EVENT_SEVERITY_ERROR, + Logger::ALERT => \ZEND_MONITOR_EVENT_SEVERITY_ERROR, + Logger::EMERGENCY => \ZEND_MONITOR_EVENT_SEVERITY_ERROR, + ]; parent::__construct($level, $bubble); } /** - * Translates Monolog log levels to ZendMonitor levels. + * {@inheritDoc} */ - protected function toZendMonitorLevel(Level $level): int - { - return match ($level) { - Level::Debug => \ZEND_MONITOR_EVENT_SEVERITY_INFO, - Level::Info => \ZEND_MONITOR_EVENT_SEVERITY_INFO, - Level::Notice => \ZEND_MONITOR_EVENT_SEVERITY_INFO, - Level::Warning => \ZEND_MONITOR_EVENT_SEVERITY_WARNING, - Level::Error => \ZEND_MONITOR_EVENT_SEVERITY_ERROR, - Level::Critical => \ZEND_MONITOR_EVENT_SEVERITY_ERROR, - Level::Alert => \ZEND_MONITOR_EVENT_SEVERITY_ERROR, - Level::Emergency => \ZEND_MONITOR_EVENT_SEVERITY_ERROR, - }; - } - - /** - * @inheritDoc - */ - protected function write(LogRecord $record): void + protected function write(array $record): void { $this->writeZendMonitorCustomEvent( - $record->level->getName(), - $record->message, - $record->formatted, - $this->toZendMonitorLevel($record->level) + Logger::getLevelName($record['level']), + $record['message'], + $record['formatted'], + $this->levelMap[$record['level']] ); } /** * Write to Zend Monitor Events - * @param string $type Text displayed in "Class Name (custom)" field - * @param string $message Text displayed in "Error String" - * @param array $formatted Displayed in Custom Variables tab - * @param int $severity Set the event severity level (-1,0,1) + * @param string $type Text displayed in "Class Name (custom)" field + * @param string $message Text displayed in "Error String" + * @param array $formatted Displayed in Custom Variables tab + * @param int $severity Set the event severity level (-1,0,1) + * + * @phpstan-param FormattedRecord $formatted */ protected function writeZendMonitorCustomEvent(string $type, string $message, array $formatted, int $severity): void { @@ -81,10 +84,18 @@ class ZendMonitorHandler extends AbstractProcessingHandler } /** - * @inheritDoc + * {@inheritDoc} */ public function getDefaultFormatter(): FormatterInterface { return new NormalizerFormatter(); } + + /** + * @return array + */ + public function getLevelMap(): array + { + return $this->levelMap; + } } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Level.php b/monolog/vendor/monolog/monolog/src/Monolog/Level.php deleted file mode 100644 index ab04cf4d4..000000000 --- a/monolog/vendor/monolog/monolog/src/Monolog/Level.php +++ /dev/null @@ -1,209 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Monolog; - -use Psr\Log\LogLevel; - -/** - * Represents the log levels - * - * Monolog supports the logging levels described by RFC 5424 {@see https://datatracker.ietf.org/doc/html/rfc5424} - * but due to BC the severity values used internally are not 0-7. - * - * To get the level name out of a Level there are three options: - * - * - Use ->getName() to get the standard Monolog name which is full uppercased (e.g. "DEBUG") - * - Use ->toPsrLogLevel() to get the standard PSR-3 name which is full lowercased (e.g. "debug") - * - Use ->toRFC5424Level() to get the standard RFC 5424 value (e.g. 7 for debug, 0 for emergency) - * - Use ->name to get the enum case's name which is capitalized (e.g. "Debug") - * - * To get the value for filtering, if the includes/isLowerThan/isHigherThan methods are - * not enough, you can use ->value to get the enum case's integer value. - */ -enum Level: int -{ - /** - * Detailed debug information - */ - case Debug = 100; - - /** - * Interesting events - * - * Examples: User logs in, SQL logs. - */ - case Info = 200; - - /** - * Uncommon events - */ - case Notice = 250; - - /** - * Exceptional occurrences that are not errors - * - * Examples: Use of deprecated APIs, poor use of an API, - * undesirable things that are not necessarily wrong. - */ - case Warning = 300; - - /** - * Runtime errors - */ - case Error = 400; - - /** - * Critical conditions - * - * Example: Application component unavailable, unexpected exception. - */ - case Critical = 500; - - /** - * Action must be taken immediately - * - * Example: Entire website down, database unavailable, etc. - * This should trigger the SMS alerts and wake you up. - */ - case Alert = 550; - - /** - * Urgent alert. - */ - case Emergency = 600; - - /** - * @param value-of|LogLevel::*|'Debug'|'Info'|'Notice'|'Warning'|'Error'|'Critical'|'Alert'|'Emergency' $name - * @return static - */ - public static function fromName(string $name): self - { - return match ($name) { - 'debug', 'Debug', 'DEBUG' => self::Debug, - 'info', 'Info', 'INFO' => self::Info, - 'notice', 'Notice', 'NOTICE' => self::Notice, - 'warning', 'Warning', 'WARNING' => self::Warning, - 'error', 'Error', 'ERROR' => self::Error, - 'critical', 'Critical', 'CRITICAL' => self::Critical, - 'alert', 'Alert', 'ALERT' => self::Alert, - 'emergency', 'Emergency', 'EMERGENCY' => self::Emergency, - }; - } - - /** - * @param value-of $value - * @return static - */ - public static function fromValue(int $value): self - { - return self::from($value); - } - - /** - * Returns true if the passed $level is higher or equal to $this - */ - public function includes(Level $level): bool - { - return $this->value <= $level->value; - } - - public function isHigherThan(Level $level): bool - { - return $this->value > $level->value; - } - - public function isLowerThan(Level $level): bool - { - return $this->value < $level->value; - } - - /** - * Returns the monolog standardized all-capitals name of the level - * - * Use this instead of $level->name which returns the enum case name (e.g. Debug vs DEBUG if you use getName()) - * - * @return value-of - */ - public function getName(): string - { - return match ($this) { - self::Debug => 'DEBUG', - self::Info => 'INFO', - self::Notice => 'NOTICE', - self::Warning => 'WARNING', - self::Error => 'ERROR', - self::Critical => 'CRITICAL', - self::Alert => 'ALERT', - self::Emergency => 'EMERGENCY', - }; - } - - /** - * Returns the PSR-3 level matching this instance - * - * @phpstan-return \Psr\Log\LogLevel::* - */ - public function toPsrLogLevel(): string - { - return match ($this) { - self::Debug => LogLevel::DEBUG, - self::Info => LogLevel::INFO, - self::Notice => LogLevel::NOTICE, - self::Warning => LogLevel::WARNING, - self::Error => LogLevel::ERROR, - self::Critical => LogLevel::CRITICAL, - self::Alert => LogLevel::ALERT, - self::Emergency => LogLevel::EMERGENCY, - }; - } - - /** - * Returns the RFC 5424 level matching this instance - * - * @phpstan-return int<0, 7> - */ - public function toRFC5424Level(): int - { - return match ($this) { - self::Debug => 7, - self::Info => 6, - self::Notice => 5, - self::Warning => 4, - self::Error => 3, - self::Critical => 2, - self::Alert => 1, - self::Emergency => 0, - }; - } - - public const VALUES = [ - 100, - 200, - 250, - 300, - 400, - 500, - 550, - 600, - ]; - - public const NAMES = [ - 'DEBUG', - 'INFO', - 'NOTICE', - 'WARNING', - 'ERROR', - 'CRITICAL', - 'ALERT', - 'EMERGENCY', - ]; -} diff --git a/monolog/vendor/monolog/monolog/src/Monolog/LogRecord.php b/monolog/vendor/monolog/monolog/src/Monolog/LogRecord.php index df758c58b..702807d71 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/LogRecord.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/LogRecord.php @@ -14,111 +14,21 @@ namespace Monolog; use ArrayAccess; /** - * Monolog log record + * Monolog log record interface for forward compatibility with Monolog 3.0 + * + * This is just present in Monolog 2.4+ to allow interoperable code to be written against + * both versions by type-hinting arguments as `array|\Monolog\LogRecord $record` + * + * Do not rely on this interface for other purposes, and do not implement it. * * @author Jordi Boggiano - * @template-implements ArrayAccess<'message'|'level'|'context'|'level_name'|'channel'|'datetime'|'extra', int|string|\DateTimeImmutable|array> + * @template-extends \ArrayAccess<'message'|'level'|'context'|'level_name'|'channel'|'datetime'|'extra'|'formatted', mixed> + * @phpstan-import-type Record from Logger */ -class LogRecord implements ArrayAccess +interface LogRecord extends \ArrayAccess { - private const MODIFIABLE_FIELDS = [ - 'extra' => true, - 'formatted' => true, - ]; - - public function __construct( - public readonly \DateTimeImmutable $datetime, - public readonly string $channel, - public readonly Level $level, - public readonly string $message, - /** @var array */ - public readonly array $context = [], - /** @var array */ - public array $extra = [], - public mixed $formatted = null, - ) { - } - - public function offsetSet(mixed $offset, mixed $value): void - { - if ($offset === 'extra') { - if (!is_array($value)) { - throw new \InvalidArgumentException('extra must be an array'); - } - - $this->extra = $value; - - return; - } - - if ($offset === 'formatted') { - $this->formatted = $value; - - return; - } - - throw new \LogicException('Unsupported operation: setting '.$offset); - } - - public function offsetExists(mixed $offset): bool - { - if ($offset === 'level_name') { - return true; - } - - return isset($this->{$offset}); - } - - public function offsetUnset(mixed $offset): void - { - throw new \LogicException('Unsupported operation'); - } - - public function &offsetGet(mixed $offset): mixed - { - if ($offset === 'level_name' || $offset === 'level') { - // avoid returning readonly props by ref as this is illegal - if ($offset === 'level_name') { - $copy = $this->level->getName(); - } else { - $copy = $this->level->value; - } - - return $copy; - } - - if (isset(self::MODIFIABLE_FIELDS[$offset])) { - return $this->{$offset}; - } - - // avoid returning readonly props by ref as this is illegal - $copy = $this->{$offset}; - - return $copy; - } - /** - * @phpstan-return array{message: string, context: mixed[], level: value-of, level_name: value-of, channel: string, datetime: \DateTimeImmutable, extra: mixed[]} + * @phpstan-return Record */ - public function toArray(): array - { - return [ - 'message' => $this->message, - 'context' => $this->context, - 'level' => $this->level->value, - 'level_name' => $this->level->getName(), - 'channel' => $this->channel, - 'datetime' => $this->datetime, - 'extra' => $this->extra, - ]; - } - - public function with(mixed ...$args): self - { - foreach (['message', 'context', 'level', 'channel', 'datetime', 'extra'] as $prop) { - $args[$prop] ??= $this->{$prop}; - } - - return new self(...$args); - } + public function toArray(): array; } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Logger.php b/monolog/vendor/monolog/monolog/src/Monolog/Logger.php index 5aacc6f87..84a2f5510 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Logger.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Logger.php @@ -11,10 +11,8 @@ namespace Monolog; -use Closure; use DateTimeZone; use Monolog\Handler\HandlerInterface; -use Monolog\Processor\ProcessorInterface; use Psr\Log\LoggerInterface; use Psr\Log\InvalidArgumentException; use Psr\Log\LogLevel; @@ -28,14 +26,15 @@ use Stringable; * and uses them to store records that are added to it. * * @author Jordi Boggiano - * @final + * + * @phpstan-type Level Logger::DEBUG|Logger::INFO|Logger::NOTICE|Logger::WARNING|Logger::ERROR|Logger::CRITICAL|Logger::ALERT|Logger::EMERGENCY + * @phpstan-type LevelName 'DEBUG'|'INFO'|'NOTICE'|'WARNING'|'ERROR'|'CRITICAL'|'ALERT'|'EMERGENCY' + * @phpstan-type Record array{message: string, context: mixed[], level: Level, level_name: LevelName, channel: string, datetime: \DateTimeImmutable, extra: mixed[]} */ class Logger implements LoggerInterface, ResettableInterface { /** * Detailed debug information - * - * @deprecated Use \Monolog\Level::Debug */ public const DEBUG = 100; @@ -43,15 +42,11 @@ class Logger implements LoggerInterface, ResettableInterface * Interesting events * * Examples: User logs in, SQL logs. - * - * @deprecated Use \Monolog\Level::Info */ public const INFO = 200; /** * Uncommon events - * - * @deprecated Use \Monolog\Level::Notice */ public const NOTICE = 250; @@ -60,15 +55,11 @@ class Logger implements LoggerInterface, ResettableInterface * * Examples: Use of deprecated APIs, poor use of an API, * undesirable things that are not necessarily wrong. - * - * @deprecated Use \Monolog\Level::Warning */ public const WARNING = 300; /** * Runtime errors - * - * @deprecated Use \Monolog\Level::Error */ public const ERROR = 400; @@ -76,8 +67,6 @@ class Logger implements LoggerInterface, ResettableInterface * Critical conditions * * Example: Application component unavailable, unexpected exception. - * - * @deprecated Use \Monolog\Level::Critical */ public const CRITICAL = 500; @@ -86,15 +75,11 @@ class Logger implements LoggerInterface, ResettableInterface * * Example: Entire website down, database unavailable, etc. * This should trigger the SMS alerts and wake you up. - * - * @deprecated Use \Monolog\Level::Alert */ public const ALERT = 550; /** * Urgent alert. - * - * @deprecated Use \Monolog\Level::Emergency */ public const EMERGENCY = 600; @@ -103,8 +88,28 @@ class Logger implements LoggerInterface, ResettableInterface * * This is only bumped when API breaks are done and should * follow the major version of the library + * + * @var int */ - public const API = 3; + public const API = 2; + + /** + * This is a static variable and not a constant to serve as an extension point for custom levels + * + * @var array $levels Logging levels with the levels as key + * + * @phpstan-var array $levels Logging levels with the levels as key + */ + protected static $levels = [ + self::DEBUG => 'DEBUG', + self::INFO => 'INFO', + self::NOTICE => 'NOTICE', + self::WARNING => 'WARNING', + self::ERROR => 'ERROR', + self::CRITICAL => 'CRITICAL', + self::ALERT => 'ALERT', + self::EMERGENCY => 'EMERGENCY', + ]; /** * Mapping between levels numbers defined in RFC 5424 and Monolog ones @@ -112,66 +117,90 @@ class Logger implements LoggerInterface, ResettableInterface * @phpstan-var array $rfc_5424_levels */ private const RFC_5424_LEVELS = [ - 7 => Level::Debug, - 6 => Level::Info, - 5 => Level::Notice, - 4 => Level::Warning, - 3 => Level::Error, - 2 => Level::Critical, - 1 => Level::Alert, - 0 => Level::Emergency, + 7 => self::DEBUG, + 6 => self::INFO, + 5 => self::NOTICE, + 4 => self::WARNING, + 3 => self::ERROR, + 2 => self::CRITICAL, + 1 => self::ALERT, + 0 => self::EMERGENCY, ]; - protected string $name; + /** + * @var string + */ + protected $name; /** * The handler stack * - * @var list + * @var HandlerInterface[] */ - protected array $handlers; + protected $handlers; /** * Processors that will process all log records * * To process records of a single handler instead, add the processor on that specific handler * - * @var array<(callable(LogRecord): LogRecord)|ProcessorInterface> + * @var callable[] */ - protected array $processors; - - protected bool $microsecondTimestamps = true; - - protected DateTimeZone $timezone; - - protected Closure|null $exceptionHandler = null; + protected $processors; /** - * Keeps track of depth to prevent infinite logging loops + * @var bool */ - private int $logDepth = 0; + protected $microsecondTimestamps = true; /** - * Whether to detect infinite logging loops + * @var DateTimeZone + */ + protected $timezone; + + /** + * @var callable|null + */ + protected $exceptionHandler; + + /** + * @var int Keeps track of depth to prevent infinite logging loops + */ + private $logDepth = 0; + + /** + * @var \WeakMap<\Fiber, int>|null Keeps track of depth inside fibers to prevent infinite logging loops + */ + private $fiberLogDepth; + + /** + * @var bool Whether to detect infinite logging loops * * This can be disabled via {@see useLoggingLoopDetection} if you have async handlers that do not play well with this */ - private bool $detectCycles = true; + private $detectCycles = true; /** + * @psalm-param array $processors + * * @param string $name The logging channel, a simple descriptive name that is attached to all log records * @param HandlerInterface[] $handlers Optional stack of handlers, the first one in the array is called first, etc. * @param callable[] $processors Optional array of processors * @param DateTimeZone|null $timezone Optional timezone, if not provided date_default_timezone_get() will be used - * - * @phpstan-param array<(callable(LogRecord): LogRecord)|ProcessorInterface> $processors */ - public function __construct(string $name, array $handlers = [], array $processors = [], DateTimeZone|null $timezone = null) + public function __construct(string $name, array $handlers = [], array $processors = [], ?DateTimeZone $timezone = null) { $this->name = $name; $this->setHandlers($handlers); $this->processors = $processors; - $this->timezone = $timezone ?? new DateTimeZone(date_default_timezone_get()); + $this->timezone = $timezone ?: new DateTimeZone(date_default_timezone_get() ?: 'UTC'); + + if (\PHP_VERSION_ID >= 80100) { + // Local variable for phpstan, see https://github.com/phpstan/phpstan/issues/6732#issuecomment-1111118412 + /** @var \WeakMap<\Fiber, int> $fiberLogDepth */ + $fiberLogDepth = new \WeakMap(); + $this->fiberLogDepth = $fiberLogDepth; + } } public function getName(): string @@ -207,7 +236,7 @@ class Logger implements LoggerInterface, ResettableInterface */ public function popHandler(): HandlerInterface { - if (0 === \count($this->handlers)) { + if (!$this->handlers) { throw new \LogicException('You tried to pop from an empty handler stack.'); } @@ -219,7 +248,7 @@ class Logger implements LoggerInterface, ResettableInterface * * If a map is passed, keys will be ignored. * - * @param list $handlers + * @param HandlerInterface[] $handlers */ public function setHandlers(array $handlers): self { @@ -232,7 +261,7 @@ class Logger implements LoggerInterface, ResettableInterface } /** - * @return list + * @return HandlerInterface[] */ public function getHandlers(): array { @@ -241,10 +270,8 @@ class Logger implements LoggerInterface, ResettableInterface /** * Adds a processor on to the stack. - * - * @phpstan-param ProcessorInterface|(callable(LogRecord): LogRecord) $callback */ - public function pushProcessor(ProcessorInterface|callable $callback): self + public function pushProcessor(callable $callback): self { array_unshift($this->processors, $callback); @@ -254,12 +281,12 @@ class Logger implements LoggerInterface, ResettableInterface /** * Removes the processor on top of the stack and returns it. * - * @phpstan-return ProcessorInterface|(callable(LogRecord): LogRecord) * @throws \LogicException If empty processor stack + * @return callable */ public function popProcessor(): callable { - if (0 === \count($this->processors)) { + if (!$this->processors) { throw new \LogicException('You tried to pop from an empty processor stack.'); } @@ -268,7 +295,6 @@ class Logger implements LoggerInterface, ResettableInterface /** * @return callable[] - * @phpstan-return array */ public function getProcessors(): array { @@ -309,49 +335,58 @@ class Logger implements LoggerInterface, ResettableInterface * @param DateTimeImmutable $datetime Optional log date to log into the past or future * @return bool Whether the record has been processed * - * @phpstan-param value-of|Level $level + * @phpstan-param Level $level */ - public function addRecord(int|Level $level, string $message, array $context = [], DateTimeImmutable $datetime = null): bool + public function addRecord(int $level, string $message, array $context = [], DateTimeImmutable $datetime = null): bool { - if (is_int($level) && isset(self::RFC_5424_LEVELS[$level])) { + if (isset(self::RFC_5424_LEVELS[$level])) { $level = self::RFC_5424_LEVELS[$level]; } if ($this->detectCycles) { - $this->logDepth += 1; + if (\PHP_VERSION_ID >= 80100 && $fiber = \Fiber::getCurrent()) { + $this->fiberLogDepth[$fiber] = $this->fiberLogDepth[$fiber] ?? 0; + $logDepth = ++$this->fiberLogDepth[$fiber]; + } else { + $logDepth = ++$this->logDepth; + } + } else { + $logDepth = 0; } - if ($this->logDepth === 3) { + + if ($logDepth === 3) { $this->warning('A possible infinite logging loop was detected and aborted. It appears some of your handler code is triggering logging, see the previous log record for a hint as to what may be the cause.'); return false; - } elseif ($this->logDepth >= 5) { // log depth 4 is let through so we can log the warning above + } elseif ($logDepth >= 5) { // log depth 4 is let through, so we can log the warning above return false; } try { - $recordInitialized = count($this->processors) === 0; - - $record = new LogRecord( - message: $message, - context: $context, - level: self::toMonologLevel($level), - channel: $this->name, - datetime: $datetime ?? new DateTimeImmutable($this->microsecondTimestamps, $this->timezone), - extra: [], - ); - $handled = false; + $record = null; foreach ($this->handlers as $handler) { - if (false === $recordInitialized) { - // skip initializing the record as long as no handler is going to handle it - if (!$handler->isHandling($record)) { + if (null === $record) { + // skip creating the record as long as no handler is going to handle it + if (!$handler->isHandling(['level' => $level])) { continue; } + $levelName = static::getLevelName($level); + + $record = [ + 'message' => $message, + 'context' => $context, + 'level' => $level, + 'level_name' => $levelName, + 'channel' => $this->name, + 'datetime' => $datetime ?? new DateTimeImmutable($this->microsecondTimestamps, $this->timezone), + 'extra' => [], + ]; + try { foreach ($this->processors as $processor) { $record = $processor($record); } - $recordInitialized = true; } catch (Throwable $e) { $this->handleException($e, $record); @@ -359,9 +394,8 @@ class Logger implements LoggerInterface, ResettableInterface } } - // once the record is initialized, send it to all handlers as long as the bubbling chain is not interrupted + // once the record exists, send it to all handlers as long as the bubbling chain is not interrupted try { - $handled = true; if (true === $handler->handle($record)) { break; } @@ -371,13 +405,17 @@ class Logger implements LoggerInterface, ResettableInterface return true; } } - - return $handled; } finally { if ($this->detectCycles) { - $this->logDepth--; + if (isset($fiber)) { + $this->fiberLogDepth[$fiber]--; + } else { + $this->logDepth--; + } } } + + return null !== $record; } /** @@ -423,77 +461,77 @@ class Logger implements LoggerInterface, ResettableInterface } /** - * Gets the name of the logging level as a string. + * Gets all supported logging levels. * - * This still returns a string instead of a Level for BC, but new code should not rely on this method. + * @return array Assoc array with human-readable level names => level codes. + * @phpstan-return array + */ + public static function getLevels(): array + { + return array_flip(static::$levels); + } + + /** + * Gets the name of the logging level. * * @throws \Psr\Log\InvalidArgumentException If level is not defined * - * @phpstan-param value-of|Level $level - * @phpstan-return value-of - * - * @deprecated Since 3.0, use {@see toMonologLevel} or {@see \Monolog\Level->getName()} instead + * @phpstan-param Level $level + * @phpstan-return LevelName */ - public static function getLevelName(int|Level $level): string + public static function getLevelName(int $level): string { - return self::toMonologLevel($level)->getName(); + if (!isset(static::$levels[$level])) { + throw new InvalidArgumentException('Level "'.$level.'" is not defined, use one of: '.implode(', ', array_keys(static::$levels))); + } + + return static::$levels[$level]; } /** * Converts PSR-3 levels to Monolog ones if necessary * - * @param int|string|Level|LogLevel::* $level Level number (monolog) or name (PSR-3) - * @throws \Psr\Log\InvalidArgumentException If level is not defined + * @param string|int $level Level number (monolog) or name (PSR-3) + * @throws \Psr\Log\InvalidArgumentException If level is not defined * - * @phpstan-param value-of|value-of|Level|LogLevel::* $level + * @phpstan-param Level|LevelName|LogLevel::* $level + * @phpstan-return Level */ - public static function toMonologLevel(string|int|Level $level): Level + public static function toMonologLevel($level): int { - if ($level instanceof Level) { - return $level; - } - - if (\is_string($level)) { - if (\is_numeric($level)) { - $levelEnum = Level::tryFrom((int) $level); - if ($levelEnum === null) { - throw new InvalidArgumentException('Level "'.$level.'" is not defined, use one of: '.implode(', ', Level::NAMES + Level::VALUES)); - } - - return $levelEnum; + if (is_string($level)) { + if (is_numeric($level)) { + /** @phpstan-ignore-next-line */ + return intval($level); } - // Contains first char of all log levels and avoids using strtoupper() which may have + // Contains chars of all log levels and avoids using strtoupper() which may have // strange results depending on locale (for example, "i" will become "İ" in Turkish locale) - $upper = strtr(substr($level, 0, 1), 'dinweca', 'DINWECA') . strtolower(substr($level, 1)); - if (defined(Level::class.'::'.$upper)) { - return constant(Level::class . '::' . $upper); + $upper = strtr($level, 'abcdefgilmnortuwy', 'ABCDEFGILMNORTUWY'); + if (defined(__CLASS__.'::'.$upper)) { + return constant(__CLASS__ . '::' . $upper); } - throw new InvalidArgumentException('Level "'.$level.'" is not defined, use one of: '.implode(', ', Level::NAMES + Level::VALUES)); + throw new InvalidArgumentException('Level "'.$level.'" is not defined, use one of: '.implode(', ', array_keys(static::$levels) + static::$levels)); } - $levelEnum = Level::tryFrom($level); - if ($levelEnum === null) { - throw new InvalidArgumentException('Level "'.var_export($level, true).'" is not defined, use one of: '.implode(', ', Level::NAMES + Level::VALUES)); + if (!is_int($level)) { + throw new InvalidArgumentException('Level "'.var_export($level, true).'" is not defined, use one of: '.implode(', ', array_keys(static::$levels) + static::$levels)); } - return $levelEnum; + return $level; } /** * Checks whether the Logger has a handler that listens on the given level * - * @phpstan-param value-of|value-of|Level|LogLevel::* $level + * @phpstan-param Level $level */ - public function isHandling(int|string|Level $level): bool + public function isHandling(int $level): bool { - $record = new LogRecord( - datetime: new DateTimeImmutable($this->microsecondTimestamps, $this->timezone), - channel: $this->name, - message: '', - level: self::toMonologLevel($level), - ); + $record = [ + 'level' => $level, + ]; foreach ($this->handlers as $handler) { if ($handler->isHandling($record)) { @@ -507,16 +545,16 @@ class Logger implements LoggerInterface, ResettableInterface /** * Set a custom exception handler that will be called if adding a new record fails * - * The Closure will receive an exception object and the record that failed to be logged + * The callable will receive an exception object and the record that failed to be logged */ - public function setExceptionHandler(Closure|null $callback): self + public function setExceptionHandler(?callable $callback): self { $this->exceptionHandler = $callback; return $this; } - public function getExceptionHandler(): Closure|null + public function getExceptionHandler(): ?callable { return $this->exceptionHandler; } @@ -530,22 +568,20 @@ class Logger implements LoggerInterface, ResettableInterface * @param string|Stringable $message The log message * @param mixed[] $context The log context * - * @phpstan-param Level|LogLevel::* $level + * @phpstan-param Level|LevelName|LogLevel::* $level */ - public function log($level, string|\Stringable $message, array $context = []): void + public function log($level, $message, array $context = []): void { - if (!$level instanceof Level) { - if (!is_string($level) && !is_int($level)) { - throw new \InvalidArgumentException('$level is expected to be a string, int or '.Level::class.' instance'); - } - - if (isset(self::RFC_5424_LEVELS[$level])) { - $level = self::RFC_5424_LEVELS[$level]; - } - - $level = static::toMonologLevel($level); + if (!is_int($level) && !is_string($level)) { + throw new \InvalidArgumentException('$level is expected to be a string or int'); } + if (isset(self::RFC_5424_LEVELS[$level])) { + $level = self::RFC_5424_LEVELS[$level]; + } + + $level = static::toMonologLevel($level); + $this->addRecord($level, (string) $message, $context); } @@ -557,9 +593,9 @@ class Logger implements LoggerInterface, ResettableInterface * @param string|Stringable $message The log message * @param mixed[] $context The log context */ - public function debug(string|\Stringable $message, array $context = []): void + public function debug($message, array $context = []): void { - $this->addRecord(Level::Debug, (string) $message, $context); + $this->addRecord(static::DEBUG, (string) $message, $context); } /** @@ -570,9 +606,9 @@ class Logger implements LoggerInterface, ResettableInterface * @param string|Stringable $message The log message * @param mixed[] $context The log context */ - public function info(string|\Stringable $message, array $context = []): void + public function info($message, array $context = []): void { - $this->addRecord(Level::Info, (string) $message, $context); + $this->addRecord(static::INFO, (string) $message, $context); } /** @@ -583,9 +619,9 @@ class Logger implements LoggerInterface, ResettableInterface * @param string|Stringable $message The log message * @param mixed[] $context The log context */ - public function notice(string|\Stringable $message, array $context = []): void + public function notice($message, array $context = []): void { - $this->addRecord(Level::Notice, (string) $message, $context); + $this->addRecord(static::NOTICE, (string) $message, $context); } /** @@ -596,9 +632,9 @@ class Logger implements LoggerInterface, ResettableInterface * @param string|Stringable $message The log message * @param mixed[] $context The log context */ - public function warning(string|\Stringable $message, array $context = []): void + public function warning($message, array $context = []): void { - $this->addRecord(Level::Warning, (string) $message, $context); + $this->addRecord(static::WARNING, (string) $message, $context); } /** @@ -609,9 +645,9 @@ class Logger implements LoggerInterface, ResettableInterface * @param string|Stringable $message The log message * @param mixed[] $context The log context */ - public function error(string|\Stringable $message, array $context = []): void + public function error($message, array $context = []): void { - $this->addRecord(Level::Error, (string) $message, $context); + $this->addRecord(static::ERROR, (string) $message, $context); } /** @@ -622,9 +658,9 @@ class Logger implements LoggerInterface, ResettableInterface * @param string|Stringable $message The log message * @param mixed[] $context The log context */ - public function critical(string|\Stringable $message, array $context = []): void + public function critical($message, array $context = []): void { - $this->addRecord(Level::Critical, (string) $message, $context); + $this->addRecord(static::CRITICAL, (string) $message, $context); } /** @@ -635,9 +671,9 @@ class Logger implements LoggerInterface, ResettableInterface * @param string|Stringable $message The log message * @param mixed[] $context The log context */ - public function alert(string|\Stringable $message, array $context = []): void + public function alert($message, array $context = []): void { - $this->addRecord(Level::Alert, (string) $message, $context); + $this->addRecord(static::ALERT, (string) $message, $context); } /** @@ -648,9 +684,9 @@ class Logger implements LoggerInterface, ResettableInterface * @param string|Stringable $message The log message * @param mixed[] $context The log context */ - public function emergency(string|\Stringable $message, array $context = []): void + public function emergency($message, array $context = []): void { - $this->addRecord(Level::Emergency, (string) $message, $context); + $this->addRecord(static::EMERGENCY, (string) $message, $context); } /** @@ -674,13 +710,52 @@ class Logger implements LoggerInterface, ResettableInterface /** * Delegates exception management to the custom exception handler, * or throws the exception if no custom handler is set. + * + * @param array $record + * @phpstan-param Record $record */ - protected function handleException(Throwable $e, LogRecord $record): void + protected function handleException(Throwable $e, array $record): void { - if (null === $this->exceptionHandler) { + if (!$this->exceptionHandler) { throw $e; } ($this->exceptionHandler)($e, $record); } + + /** + * @return array + */ + public function __serialize(): array + { + return [ + 'name' => $this->name, + 'handlers' => $this->handlers, + 'processors' => $this->processors, + 'microsecondTimestamps' => $this->microsecondTimestamps, + 'timezone' => $this->timezone, + 'exceptionHandler' => $this->exceptionHandler, + 'logDepth' => $this->logDepth, + 'detectCycles' => $this->detectCycles, + ]; + } + + /** + * @param array $data + */ + public function __unserialize(array $data): void + { + foreach (['name', 'handlers', 'processors', 'microsecondTimestamps', 'timezone', 'exceptionHandler', 'logDepth', 'detectCycles'] as $property) { + if (isset($data[$property])) { + $this->$property = $data[$property]; + } + } + + if (\PHP_VERSION_ID >= 80100) { + // Local variable for phpstan, see https://github.com/phpstan/phpstan/issues/6732#issuecomment-1111118412 + /** @var \WeakMap<\Fiber, int> $fiberLogDepth */ + $fiberLogDepth = new \WeakMap(); + $this->fiberLogDepth = $fiberLogDepth; + } + } } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Processor/GitProcessor.php b/monolog/vendor/monolog/monolog/src/Monolog/Processor/GitProcessor.php index 4cbd9c84e..8166bdca2 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Processor/GitProcessor.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Processor/GitProcessor.php @@ -11,44 +11,46 @@ namespace Monolog\Processor; -use Monolog\Level; use Monolog\Logger; use Psr\Log\LogLevel; -use Monolog\LogRecord; /** * Injects Git branch and Git commit SHA in all records * * @author Nick Otter * @author Jordi Boggiano + * + * @phpstan-import-type Level from \Monolog\Logger + * @phpstan-import-type LevelName from \Monolog\Logger */ class GitProcessor implements ProcessorInterface { - private Level $level; + /** @var int */ + private $level; /** @var array{branch: string, commit: string}|array|null */ private static $cache = null; /** - * @param int|string|Level|LogLevel::* $level The minimum logging level at which this Processor will be triggered + * @param string|int $level The minimum logging level at which this Processor will be triggered * - * @phpstan-param value-of|value-of|Level|LogLevel::* $level + * @phpstan-param Level|LevelName|LogLevel::* $level */ - public function __construct(int|string|Level $level = Level::Debug) + public function __construct($level = Logger::DEBUG) { $this->level = Logger::toMonologLevel($level); } /** - * @inheritDoc + * {@inheritDoc} */ - public function __invoke(LogRecord $record): LogRecord + public function __invoke(array $record): array { // return if the level is not high enough - if ($record->level < $this->level) { + if ($record['level'] < $this->level) { return $record; } - $record->extra['git'] = self::getGitInfo(); + $record['extra']['git'] = self::getGitInfo(); return $record; } @@ -58,12 +60,12 @@ class GitProcessor implements ProcessorInterface */ private static function getGitInfo(): array { - if (self::$cache !== null) { + if (self::$cache) { return self::$cache; } - $branches = shell_exec('git branch -v --no-abbrev'); - if (is_string($branches) && 1 === preg_match('{^\* (.+?)\s+([a-f0-9]{40})(?:\s|$)}m', $branches, $matches)) { + $branches = `git branch -v --no-abbrev`; + if ($branches && preg_match('{^\* (.+?)\s+([a-f0-9]{40})(?:\s|$)}m', $branches, $matches)) { return self::$cache = [ 'branch' => $matches[1], 'commit' => $matches[2], diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Processor/HostnameProcessor.php b/monolog/vendor/monolog/monolog/src/Monolog/Processor/HostnameProcessor.php index cba6e0963..91fda7d6d 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Processor/HostnameProcessor.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Processor/HostnameProcessor.php @@ -11,14 +11,13 @@ namespace Monolog\Processor; -use Monolog\LogRecord; - /** * Injects value of gethostname in all records */ class HostnameProcessor implements ProcessorInterface { - private static string $host; + /** @var string */ + private static $host; public function __construct() { @@ -26,11 +25,11 @@ class HostnameProcessor implements ProcessorInterface } /** - * @inheritDoc + * {@inheritDoc} */ - public function __invoke(LogRecord $record): LogRecord + public function __invoke(array $record): array { - $record->extra['hostname'] = self::$host; + $record['extra']['hostname'] = self::$host; return $record; } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php b/monolog/vendor/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php index 30e7dfed8..a32e76b21 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php @@ -11,10 +11,8 @@ namespace Monolog\Processor; -use Monolog\Level; use Monolog\Logger; use Psr\Log\LogLevel; -use Monolog\LogRecord; /** * Injects line/file:class/function where the log message came from @@ -26,28 +24,31 @@ use Monolog\LogRecord; * triggered the FingersCrossedHandler. * * @author Jordi Boggiano + * + * @phpstan-import-type Level from \Monolog\Logger + * @phpstan-import-type LevelName from \Monolog\Logger */ class IntrospectionProcessor implements ProcessorInterface { - private Level $level; - + /** @var int */ + private $level; /** @var string[] */ - private array $skipClassesPartials; - - private int $skipStackFramesCount; - - private const SKIP_FUNCTIONS = [ + private $skipClassesPartials; + /** @var int */ + private $skipStackFramesCount; + /** @var string[] */ + private $skipFunctions = [ 'call_user_func', 'call_user_func_array', ]; /** - * @param string|int|Level $level The minimum logging level at which this Processor will be triggered - * @param string[] $skipClassesPartials + * @param string|int $level The minimum logging level at which this Processor will be triggered + * @param string[] $skipClassesPartials * - * @phpstan-param value-of|value-of|Level|LogLevel::* $level + * @phpstan-param Level|LevelName|LogLevel::* $level */ - public function __construct(int|string|Level $level = Level::Debug, array $skipClassesPartials = [], int $skipStackFramesCount = 0) + public function __construct($level = Logger::DEBUG, array $skipClassesPartials = [], int $skipStackFramesCount = 0) { $this->level = Logger::toMonologLevel($level); $this->skipClassesPartials = array_merge(['Monolog\\'], $skipClassesPartials); @@ -55,12 +56,12 @@ class IntrospectionProcessor implements ProcessorInterface } /** - * @inheritDoc + * {@inheritDoc} */ - public function __invoke(LogRecord $record): LogRecord + public function __invoke(array $record): array { // return if the level is not high enough - if ($record->level->isLowerThan($this->level)) { + if ($record['level'] < $this->level) { return $record; } @@ -82,7 +83,7 @@ class IntrospectionProcessor implements ProcessorInterface continue 2; } } - } elseif (in_array($trace[$i]['function'], self::SKIP_FUNCTIONS, true)) { + } elseif (in_array($trace[$i]['function'], $this->skipFunctions)) { $i++; continue; @@ -94,8 +95,8 @@ class IntrospectionProcessor implements ProcessorInterface $i += $this->skipStackFramesCount; // we should have the call source now - $record->extra = array_merge( - $record->extra, + $record['extra'] = array_merge( + $record['extra'], [ 'file' => isset($trace[$i - 1]['file']) ? $trace[$i - 1]['file'] : null, 'line' => isset($trace[$i - 1]['line']) ? $trace[$i - 1]['line'] : null, @@ -109,7 +110,7 @@ class IntrospectionProcessor implements ProcessorInterface } /** - * @param array $trace + * @param array[] $trace */ private function isTraceClassOrSkippedFunction(array $trace, int $index): bool { @@ -117,6 +118,6 @@ class IntrospectionProcessor implements ProcessorInterface return false; } - return isset($trace[$index]['class']) || in_array($trace[$index]['function'], self::SKIP_FUNCTIONS, true); + return isset($trace[$index]['class']) || in_array($trace[$index]['function'], $this->skipFunctions); } } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Processor/MemoryPeakUsageProcessor.php b/monolog/vendor/monolog/monolog/src/Monolog/Processor/MemoryPeakUsageProcessor.php index adc32c65d..37c756fcb 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Processor/MemoryPeakUsageProcessor.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Processor/MemoryPeakUsageProcessor.php @@ -11,8 +11,6 @@ namespace Monolog\Processor; -use Monolog\LogRecord; - /** * Injects memory_get_peak_usage in all records * @@ -22,9 +20,9 @@ use Monolog\LogRecord; class MemoryPeakUsageProcessor extends MemoryProcessor { /** - * @inheritDoc + * {@inheritDoc} */ - public function __invoke(LogRecord $record): LogRecord + public function __invoke(array $record): array { $usage = memory_get_peak_usage($this->realUsage); @@ -32,7 +30,7 @@ class MemoryPeakUsageProcessor extends MemoryProcessor $usage = $this->formatBytes($usage); } - $record->extra['memory_peak_usage'] = $usage; + $record['extra']['memory_peak_usage'] = $usage; return $record; } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Processor/MemoryProcessor.php b/monolog/vendor/monolog/monolog/src/Monolog/Processor/MemoryProcessor.php index f808e51b4..227deb7c8 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Processor/MemoryProcessor.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Processor/MemoryProcessor.php @@ -21,12 +21,12 @@ abstract class MemoryProcessor implements ProcessorInterface /** * @var bool If true, get the real size of memory allocated from system. Else, only the memory used by emalloc() is reported. */ - protected bool $realUsage; + protected $realUsage; /** * @var bool If true, then format memory size to human readable string (MB, KB, B depending on size) */ - protected bool $useFormatting; + protected $useFormatting; /** * @param bool $realUsage Set this to true to get the real size of memory allocated from system. @@ -41,6 +41,7 @@ abstract class MemoryProcessor implements ProcessorInterface /** * Formats bytes into a human readable string if $this->useFormatting is true, otherwise return $bytes as is * + * @param int $bytes * @return string|int Formatted string if $this->useFormatting is true, otherwise return $bytes as int */ protected function formatBytes(int $bytes) diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Processor/MemoryUsageProcessor.php b/monolog/vendor/monolog/monolog/src/Monolog/Processor/MemoryUsageProcessor.php index a814b1df3..e141921e9 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Processor/MemoryUsageProcessor.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Processor/MemoryUsageProcessor.php @@ -11,8 +11,6 @@ namespace Monolog\Processor; -use Monolog\LogRecord; - /** * Injects memory_get_usage in all records * @@ -22,9 +20,9 @@ use Monolog\LogRecord; class MemoryUsageProcessor extends MemoryProcessor { /** - * @inheritDoc + * {@inheritDoc} */ - public function __invoke(LogRecord $record): LogRecord + public function __invoke(array $record): array { $usage = memory_get_usage($this->realUsage); @@ -32,7 +30,7 @@ class MemoryUsageProcessor extends MemoryProcessor $usage = $this->formatBytes($usage); } - $record->extra['memory_usage'] = $usage; + $record['extra']['memory_usage'] = $usage; return $record; } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Processor/MercurialProcessor.php b/monolog/vendor/monolog/monolog/src/Monolog/Processor/MercurialProcessor.php index 47b1e64ff..d4a628f55 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Processor/MercurialProcessor.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Processor/MercurialProcessor.php @@ -11,43 +11,45 @@ namespace Monolog\Processor; -use Monolog\Level; use Monolog\Logger; use Psr\Log\LogLevel; -use Monolog\LogRecord; /** * Injects Hg branch and Hg revision number in all records * * @author Jonathan A. Schweder + * + * @phpstan-import-type LevelName from \Monolog\Logger + * @phpstan-import-type Level from \Monolog\Logger */ class MercurialProcessor implements ProcessorInterface { - private Level $level; + /** @var Level */ + private $level; /** @var array{branch: string, revision: string}|array|null */ private static $cache = null; /** - * @param int|string|Level $level The minimum logging level at which this Processor will be triggered + * @param int|string $level The minimum logging level at which this Processor will be triggered * - * @phpstan-param value-of|value-of|Level|LogLevel::* $level + * @phpstan-param Level|LevelName|LogLevel::* $level */ - public function __construct(int|string|Level $level = Level::Debug) + public function __construct($level = Logger::DEBUG) { $this->level = Logger::toMonologLevel($level); } /** - * @inheritDoc + * {@inheritDoc} */ - public function __invoke(LogRecord $record): LogRecord + public function __invoke(array $record): array { // return if the level is not high enough - if ($record->level->isLowerThan($this->level)) { + if ($record['level'] < $this->level) { return $record; } - $record->extra['hg'] = self::getMercurialInfo(); + $record['extra']['hg'] = self::getMercurialInfo(); return $record; } @@ -57,11 +59,11 @@ class MercurialProcessor implements ProcessorInterface */ private static function getMercurialInfo(): array { - if (self::$cache !== null) { + if (self::$cache) { return self::$cache; } - $result = explode(' ', trim((string) shell_exec('hg id -nb'))); + $result = explode(' ', trim(`hg id -nb`)); if (count($result) >= 3) { return self::$cache = [ diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php b/monolog/vendor/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php index bb9a52243..3b939a951 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php @@ -11,8 +11,6 @@ namespace Monolog\Processor; -use Monolog\LogRecord; - /** * Adds value of getmypid into records * @@ -21,11 +19,11 @@ use Monolog\LogRecord; class ProcessIdProcessor implements ProcessorInterface { /** - * @inheritDoc + * {@inheritDoc} */ - public function __invoke(LogRecord $record): LogRecord + public function __invoke(array $record): array { - $record->extra['process_id'] = getmypid(); + $record['extra']['process_id'] = getmypid(); return $record; } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Processor/ProcessorInterface.php b/monolog/vendor/monolog/monolog/src/Monolog/Processor/ProcessorInterface.php index ebe41fc20..5defb7eb4 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Processor/ProcessorInterface.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Processor/ProcessorInterface.php @@ -11,17 +11,20 @@ namespace Monolog\Processor; -use Monolog\LogRecord; - /** * An optional interface to allow labelling Monolog processors. * * @author Nicolas Grekas + * + * @phpstan-import-type Record from \Monolog\Logger */ interface ProcessorInterface { /** - * @return LogRecord The processed record + * @return array The processed record + * + * @phpstan-param Record $record + * @phpstan-return Record */ - public function __invoke(LogRecord $record); + public function __invoke(array $record); } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php b/monolog/vendor/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php index f2407d563..e7c12176a 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php @@ -12,7 +12,6 @@ namespace Monolog\Processor; use Monolog\Utils; -use Monolog\LogRecord; /** * Processes a record's message according to PSR-3 rules @@ -25,9 +24,11 @@ class PsrLogMessageProcessor implements ProcessorInterface { public const SIMPLE_DATE = "Y-m-d\TH:i:s.uP"; - private ?string $dateFormat; + /** @var string|null */ + private $dateFormat; - private bool $removeUsedContextFields; + /** @var bool */ + private $removeUsedContextFields; /** * @param string|null $dateFormat The format of the timestamp: one supported by DateTime::format @@ -40,33 +41,33 @@ class PsrLogMessageProcessor implements ProcessorInterface } /** - * @inheritDoc + * {@inheritDoc} */ - public function __invoke(LogRecord $record): LogRecord + public function __invoke(array $record): array { - if (false === strpos($record->message, '{')) { + if (false === strpos($record['message'], '{')) { return $record; } $replacements = []; - $context = $record->context; - - foreach ($context as $key => $val) { + foreach ($record['context'] as $key => $val) { $placeholder = '{' . $key . '}'; - if (strpos($record->message, $placeholder) === false) { + if (strpos($record['message'], $placeholder) === false) { continue; } - if (null === $val || is_scalar($val) || (is_object($val) && method_exists($val, "__toString"))) { + if (is_null($val) || is_scalar($val) || (is_object($val) && method_exists($val, "__toString"))) { $replacements[$placeholder] = $val; } elseif ($val instanceof \DateTimeInterface) { - if (null === $this->dateFormat && $val instanceof \Monolog\DateTimeImmutable) { + if (!$this->dateFormat && $val instanceof \Monolog\DateTimeImmutable) { // handle monolog dates using __toString if no specific dateFormat was asked for // so that it follows the useMicroseconds flag $replacements[$placeholder] = (string) $val; } else { - $replacements[$placeholder] = $val->format($this->dateFormat ?? static::SIMPLE_DATE); + $replacements[$placeholder] = $val->format($this->dateFormat ?: static::SIMPLE_DATE); } + } elseif ($val instanceof \UnitEnum) { + $replacements[$placeholder] = $val instanceof \BackedEnum ? $val->value : $val->name; } elseif (is_object($val)) { $replacements[$placeholder] = '[object '.Utils::getClass($val).']'; } elseif (is_array($val)) { @@ -76,10 +77,12 @@ class PsrLogMessageProcessor implements ProcessorInterface } if ($this->removeUsedContextFields) { - unset($context[$key]); + unset($record['context'][$key]); } } - return $record->with(message: strtr($record->message, $replacements), context: $context); + $record['message'] = strtr($record['message'], $replacements); + + return $record; } } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Processor/TagProcessor.php b/monolog/vendor/monolog/monolog/src/Monolog/Processor/TagProcessor.php index 4543ccf61..80f18747a 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Processor/TagProcessor.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Processor/TagProcessor.php @@ -11,8 +11,6 @@ namespace Monolog\Processor; -use Monolog\LogRecord; - /** * Adds a tags array into record * @@ -21,7 +19,7 @@ use Monolog\LogRecord; class TagProcessor implements ProcessorInterface { /** @var string[] */ - private array $tags; + private $tags; /** * @param string[] $tags @@ -52,11 +50,11 @@ class TagProcessor implements ProcessorInterface } /** - * @inheritDoc + * {@inheritDoc} */ - public function __invoke(LogRecord $record): LogRecord + public function __invoke(array $record): array { - $record->extra['tags'] = $this->tags; + $record['extra']['tags'] = $this->tags; return $record; } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Processor/UidProcessor.php b/monolog/vendor/monolog/monolog/src/Monolog/Processor/UidProcessor.php index 3a0c128c2..a27b74dbf 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Processor/UidProcessor.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Processor/UidProcessor.php @@ -12,7 +12,6 @@ namespace Monolog\Processor; use Monolog\ResettableInterface; -use Monolog\LogRecord; /** * Adds a unique identifier into records @@ -21,12 +20,9 @@ use Monolog\LogRecord; */ class UidProcessor implements ProcessorInterface, ResettableInterface { - /** @var non-empty-string */ - private string $uid; + /** @var string */ + private $uid; - /** - * @param int<1, 32> $length - */ public function __construct(int $length = 7) { if ($length > 32 || $length < 1) { @@ -37,11 +33,11 @@ class UidProcessor implements ProcessorInterface, ResettableInterface } /** - * @inheritDoc + * {@inheritDoc} */ - public function __invoke(LogRecord $record): LogRecord + public function __invoke(array $record): array { - $record->extra['uid'] = $this->uid; + $record['extra']['uid'] = $this->uid; return $record; } @@ -51,15 +47,11 @@ class UidProcessor implements ProcessorInterface, ResettableInterface return $this->uid; } - public function reset(): void + public function reset() { $this->uid = $this->generateUid(strlen($this->uid)); } - /** - * @param positive-int $length - * @return non-empty-string - */ private function generateUid(int $length): string { return substr(bin2hex(random_bytes((int) ceil($length / 2))), 0, $length); diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Processor/WebProcessor.php b/monolog/vendor/monolog/monolog/src/Monolog/Processor/WebProcessor.php index 2088b180b..51850e17f 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Processor/WebProcessor.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Processor/WebProcessor.php @@ -11,9 +11,6 @@ namespace Monolog\Processor; -use ArrayAccess; -use Monolog\LogRecord; - /** * Injects url/method and remote IP of the current web request in all records * @@ -22,9 +19,9 @@ use Monolog\LogRecord; class WebProcessor implements ProcessorInterface { /** - * @var array|ArrayAccess + * @var array|\ArrayAccess */ - protected array|ArrayAccess $serverData; + protected $serverData; /** * Default fields @@ -33,7 +30,7 @@ class WebProcessor implements ProcessorInterface * * @var array */ - protected array $extraFields = [ + protected $extraFields = [ 'url' => 'REQUEST_URI', 'ip' => 'REMOTE_ADDR', 'http_method' => 'REQUEST_METHOD', @@ -43,15 +40,17 @@ class WebProcessor implements ProcessorInterface ]; /** - * @param array|ArrayAccess|null $serverData Array or object w/ ArrayAccess that provides access to the $_SERVER data - * @param array|array|null $extraFields Field names and the related key inside $serverData to be added (or just a list of field names to use the default configured $serverData mapping). If not provided it defaults to: [url, ip, http_method, server, referrer] + unique_id if present in server data + * @param array|\ArrayAccess|null $serverData Array or object w/ ArrayAccess that provides access to the $_SERVER data + * @param array|array|null $extraFields Field names and the related key inside $serverData to be added (or just a list of field names to use the default configured $serverData mapping). If not provided it defaults to: [url, ip, http_method, server, referrer] + unique_id if present in server data */ - public function __construct(array|ArrayAccess|null $serverData = null, array|null $extraFields = null) + public function __construct($serverData = null, array $extraFields = null) { if (null === $serverData) { $this->serverData = &$_SERVER; - } else { + } elseif (is_array($serverData) || $serverData instanceof \ArrayAccess) { $this->serverData = $serverData; + } else { + throw new \UnexpectedValueException('$serverData must be an array or object implementing ArrayAccess.'); } $defaultEnabled = ['url', 'ip', 'http_method', 'server', 'referrer']; @@ -65,7 +64,7 @@ class WebProcessor implements ProcessorInterface } if (isset($extraFields[0])) { foreach (array_keys($this->extraFields) as $fieldName) { - if (!in_array($fieldName, $extraFields, true)) { + if (!in_array($fieldName, $extraFields)) { unset($this->extraFields[$fieldName]); } } @@ -75,9 +74,9 @@ class WebProcessor implements ProcessorInterface } /** - * @inheritDoc + * {@inheritDoc} */ - public function __invoke(LogRecord $record): LogRecord + public function __invoke(array $record): array { // skip processing if for some reason request data // is not present (CLI or wonky SAPIs) @@ -85,7 +84,7 @@ class WebProcessor implements ProcessorInterface return $record; } - $record->extra = $this->appendExtraFields($record->extra); + $record['extra'] = $this->appendExtraFields($record['extra']); return $record; } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Registry.php b/monolog/vendor/monolog/monolog/src/Monolog/Registry.php index 2ef2edceb..ae94ae6cc 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Registry.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Registry.php @@ -42,7 +42,7 @@ class Registry * * @var Logger[] */ - private static array $loggers = []; + private static $loggers = []; /** * Adds new logging channel to the registry @@ -51,10 +51,11 @@ class Registry * @param string|null $name Name of the logging channel ($logger->getName() by default) * @param bool $overwrite Overwrite instance in the registry if the given name already exists? * @throws \InvalidArgumentException If $overwrite set to false and named Logger instance already exists + * @return void */ - public static function addLogger(Logger $logger, ?string $name = null, bool $overwrite = false): void + public static function addLogger(Logger $logger, ?string $name = null, bool $overwrite = false) { - $name = $name ?? $logger->getName(); + $name = $name ?: $logger->getName(); if (isset(self::$loggers[$name]) && !$overwrite) { throw new InvalidArgumentException('Logger with the given name already exists'); @@ -109,7 +110,7 @@ class Registry * @param string $name Name of the requested Logger instance * @throws \InvalidArgumentException If named Logger instance is not in the registry */ - public static function getInstance(string $name): Logger + public static function getInstance($name): Logger { if (!isset(self::$loggers[$name])) { throw new InvalidArgumentException(sprintf('Requested "%s" logger instance is not in the registry', $name)); @@ -126,7 +127,7 @@ class Registry * @throws \InvalidArgumentException If named Logger instance is not in the registry * @return Logger Requested instance of Logger */ - public static function __callStatic(string $name, array $arguments): Logger + public static function __callStatic($name, $arguments) { return self::getInstance($name); } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/ResettableInterface.php b/monolog/vendor/monolog/monolog/src/Monolog/ResettableInterface.php index 4983a6b35..2c5fd7851 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/ResettableInterface.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/ResettableInterface.php @@ -27,5 +27,8 @@ namespace Monolog; */ interface ResettableInterface { - public function reset(): void; + /** + * @return void + */ + public function reset(); } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/SignalHandler.php b/monolog/vendor/monolog/monolog/src/Monolog/SignalHandler.php index e6b02b083..d730eea3a 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/SignalHandler.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/SignalHandler.php @@ -19,17 +19,21 @@ use ReflectionExtension; * Monolog POSIX signal handler * * @author Robert Gust-Bardon + * + * @phpstan-import-type Level from \Monolog\Logger + * @phpstan-import-type LevelName from \Monolog\Logger */ class SignalHandler { - private LoggerInterface $logger; + /** @var LoggerInterface */ + private $logger; /** @var array SIG_DFL, SIG_IGN or previous callable */ - private array $previousSignalHandler = []; - /** @var array */ - private array $signalLevelMap = []; + private $previousSignalHandler = []; + /** @var array */ + private $signalLevelMap = []; /** @var array */ - private array $signalRestartSyscalls = []; + private $signalRestartSyscalls = []; public function __construct(LoggerInterface $logger) { @@ -37,18 +41,21 @@ class SignalHandler } /** - * @param int|string|Level $level Level or level name + * @param int|string $level Level or level name + * @param bool $callPrevious + * @param bool $restartSyscalls + * @param bool|null $async * @return $this * - * @phpstan-param value-of|value-of|Level|LogLevel::* $level + * @phpstan-param Level|LevelName|LogLevel::* $level */ - public function registerSignalHandler(int $signo, int|string|Level $level = LogLevel::CRITICAL, bool $callPrevious = true, bool $restartSyscalls = true, ?bool $async = true): self + public function registerSignalHandler(int $signo, $level = LogLevel::CRITICAL, bool $callPrevious = true, bool $restartSyscalls = true, ?bool $async = true): self { if (!extension_loaded('pcntl') || !function_exists('pcntl_signal')) { return $this; } - $level = Logger::toMonologLevel($level)->toPsrLogLevel(); + $level = Logger::toMonologLevel($level); if ($callPrevious) { $handler = pcntl_signal_get_handler($signo); @@ -77,7 +84,8 @@ class SignalHandler if (!$signals && extension_loaded('pcntl')) { $pcntl = new ReflectionExtension('pcntl'); - foreach ($pcntl->getConstants() as $name => $value) { + // HHVM 3.24.2 returns an empty array. + foreach ($pcntl->getConstants() ?: get_defined_constants(true)['Core'] as $name => $value) { if (substr($name, 0, 3) === 'SIG' && $name[3] !== '_' && is_int($value)) { $signals[$value] = $name; } diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Test/TestCase.php b/monolog/vendor/monolog/monolog/src/Monolog/Test/TestCase.php index 98204a95c..bc0b425ea 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Test/TestCase.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Test/TestCase.php @@ -11,18 +11,18 @@ namespace Monolog\Test; -use Monolog\Level; use Monolog\Logger; -use Monolog\LogRecord; use Monolog\DateTimeImmutable; use Monolog\Formatter\FormatterInterface; -use Psr\Log\LogLevel; /** * Lets you easily generate log records and a dummy formatter for testing purposes * * @author Jordi Boggiano * + * @phpstan-import-type Record from \Monolog\Logger + * @phpstan-import-type Level from \Monolog\Logger + * * @internal feel free to reuse this to test your own handlers, this is marked internal to avoid issues with PHPStorm https://github.com/Seldaek/monolog/issues/1677 */ class TestCase extends \PHPUnit\Framework\TestCase @@ -37,44 +37,47 @@ class TestCase extends \PHPUnit\Framework\TestCase } /** - * @param array $context - * @param array $extra + * @param mixed[] $context * - * @phpstan-param value-of|value-of|Level|LogLevel::* $level + * @return array Record + * + * @phpstan-param Level $level + * @phpstan-return Record */ - protected function getRecord(int|string|Level $level = Level::Warning, string|\Stringable $message = 'test', array $context = [], string $channel = 'test', \DateTimeImmutable $datetime = new DateTimeImmutable(true), array $extra = []): LogRecord + protected function getRecord(int $level = Logger::WARNING, string $message = 'test', array $context = []): array { - return new LogRecord( - message: (string) $message, - context: $context, - level: Logger::toMonologLevel($level), - channel: $channel, - datetime: $datetime, - extra: $extra, - ); + return [ + 'message' => (string) $message, + 'context' => $context, + 'level' => $level, + 'level_name' => Logger::getLevelName($level), + 'channel' => 'test', + 'datetime' => new DateTimeImmutable(true), + 'extra' => [], + ]; } /** - * @phpstan-return list + * @phpstan-return Record[] */ protected function getMultipleRecords(): array { return [ - $this->getRecord(Level::Debug, 'debug message 1'), - $this->getRecord(Level::Debug, 'debug message 2'), - $this->getRecord(Level::Info, 'information'), - $this->getRecord(Level::Warning, 'warning'), - $this->getRecord(Level::Error, 'error'), + $this->getRecord(Logger::DEBUG, 'debug message 1'), + $this->getRecord(Logger::DEBUG, 'debug message 2'), + $this->getRecord(Logger::INFO, 'information'), + $this->getRecord(Logger::WARNING, 'warning'), + $this->getRecord(Logger::ERROR, 'error'), ]; } protected function getIdentityFormatter(): FormatterInterface { $formatter = $this->createMock(FormatterInterface::class); - $formatter->expects(self::any()) + $formatter->expects($this->any()) ->method('format') - ->will(self::returnCallback(function ($record) { - return $record->message; + ->will($this->returnCallback(function ($record) { + return $record['message']; })); return $formatter; diff --git a/monolog/vendor/monolog/monolog/src/Monolog/Utils.php b/monolog/vendor/monolog/monolog/src/Monolog/Utils.php index 9dae2535f..360c42199 100644 --- a/monolog/vendor/monolog/monolog/src/Monolog/Utils.php +++ b/monolog/vendor/monolog/monolog/src/Monolog/Utils.php @@ -122,7 +122,7 @@ final class Utils if (is_string($data)) { self::detectAndCleanUtf8($data); } elseif (is_array($data)) { - array_walk_recursive($data, ['Monolog\Utils', 'detectAndCleanUtf8']); + array_walk_recursive($data, array('Monolog\Utils', 'detectAndCleanUtf8')); } else { self::throwEncodeError($code, $data); } @@ -165,16 +165,27 @@ final class Utils * @param int $code return code of json_last_error function * @param mixed $data data that was meant to be encoded * @throws \RuntimeException + * + * @return never */ - private static function throwEncodeError(int $code, $data): never + private static function throwEncodeError(int $code, $data): void { - $msg = match ($code) { - JSON_ERROR_DEPTH => 'Maximum stack depth exceeded', - JSON_ERROR_STATE_MISMATCH => 'Underflow or the modes mismatch', - JSON_ERROR_CTRL_CHAR => 'Unexpected control character found', - JSON_ERROR_UTF8 => 'Malformed UTF-8 characters, possibly incorrectly encoded', - default => 'Unknown error', - }; + switch ($code) { + case JSON_ERROR_DEPTH: + $msg = 'Maximum stack depth exceeded'; + break; + case JSON_ERROR_STATE_MISMATCH: + $msg = 'Underflow or the modes mismatch'; + break; + case JSON_ERROR_CTRL_CHAR: + $msg = 'Unexpected control character found'; + break; + case JSON_ERROR_UTF8: + $msg = 'Malformed UTF-8 characters, possibly incorrectly encoded'; + break; + default: + $msg = 'Unknown error'; + } throw new \RuntimeException('JSON encoding failed: '.$msg.'. Encoding: '.var_export($data, true)); } @@ -196,7 +207,7 @@ final class Utils */ private static function detectAndCleanUtf8(&$data): void { - if (is_string($data) && preg_match('//u', $data) !== 1) { + if (is_string($data) && !preg_match('//u', $data)) { $data = preg_replace_callback( '/[\x80-\xFF]+/', function ($m) { @@ -206,7 +217,6 @@ final class Utils ); if (!is_string($data)) { $pcreErrorCode = preg_last_error(); - throw new \RuntimeException('Failed to preg_replace_callback: ' . $pcreErrorCode . ' / ' . self::pcreLastErrorMessage($pcreErrorCode)); } $data = str_replace( @@ -220,8 +230,8 @@ final class Utils /** * Converts a string with a valid 'memory_limit' format, to bytes. * - * @param string|false $val - * @return int|false Returns an integer representing bytes. Returns FALSE in case of error. + * @param string|false $val + * @return int|false Returns an integer representing bytes. Returns FALSE in case of error. */ public static function expandIniShorthandBytes($val) { @@ -234,7 +244,7 @@ final class Utils return (int) $val; } - if (preg_match('/^\s*(?\d+)(?:\.\d+)?\s*(?[gmk]?)\s*$/i', $val, $match) !== 1) { + if (!preg_match('/^\s*(?\d+)(?:\.\d+)?\s*(?[gmk]?)\s*$/i', $val, $match)) { return false; } @@ -242,10 +252,8 @@ final class Utils switch (strtolower($match['unit'] ?? '')) { case 'g': $val *= 1024; - // no break case 'm': $val *= 1024; - // no break case 'k': $val *= 1024; } @@ -253,22 +261,24 @@ final class Utils return $val; } - public static function getRecordMessageForException(LogRecord $record): string + /** + * @param array $record + */ + public static function getRecordMessageForException(array $record): string { $context = ''; $extra = ''; - try { - if (\count($record->context) > 0) { - $context = "\nContext: " . json_encode($record->context, JSON_THROW_ON_ERROR); + if ($record['context']) { + $context = "\nContext: " . json_encode($record['context']); } - if (\count($record->extra) > 0) { - $extra = "\nExtra: " . json_encode($record->extra, JSON_THROW_ON_ERROR); + if ($record['extra']) { + $extra = "\nExtra: " . json_encode($record['extra']); } } catch (\Throwable $e) { // noop } - return "\nThe exception occurred while attempting to log: " . $record->message . $context . $extra; + return "\nThe exception occurred while attempting to log: " . $record['message'] . $context . $extra; } } diff --git a/monolog/vendor/psr/log/composer.json b/monolog/vendor/psr/log/composer.json index 879fc6f53..ca0569537 100644 --- a/monolog/vendor/psr/log/composer.json +++ b/monolog/vendor/psr/log/composer.json @@ -11,16 +11,16 @@ } ], "require": { - "php": ">=8.0.0" + "php": ">=5.3.0" }, "autoload": { "psr-4": { - "Psr\\Log\\": "src" + "Psr\\Log\\": "Psr/Log/" } }, "extra": { "branch-alias": { - "dev-master": "3.x-dev" + "dev-master": "1.1.x-dev" } } } diff --git a/monolog/vendor/psr/log/src/AbstractLogger.php b/monolog/vendor/psr/log/src/AbstractLogger.php deleted file mode 100644 index d60a091af..000000000 --- a/monolog/vendor/psr/log/src/AbstractLogger.php +++ /dev/null @@ -1,15 +0,0 @@ -logger = $logger; - } -} diff --git a/monolog/vendor/psr/log/src/LoggerInterface.php b/monolog/vendor/psr/log/src/LoggerInterface.php deleted file mode 100644 index b3a24b5f7..000000000 --- a/monolog/vendor/psr/log/src/LoggerInterface.php +++ /dev/null @@ -1,125 +0,0 @@ -log(LogLevel::EMERGENCY, $message, $context); - } - - /** - * Action must be taken immediately. - * - * Example: Entire website down, database unavailable, etc. This should - * trigger the SMS alerts and wake you up. - * - * @param string|\Stringable $message - * @param array $context - * - * @return void - */ - public function alert(string|\Stringable $message, array $context = []): void - { - $this->log(LogLevel::ALERT, $message, $context); - } - - /** - * Critical conditions. - * - * Example: Application component unavailable, unexpected exception. - * - * @param string|\Stringable $message - * @param array $context - * - * @return void - */ - public function critical(string|\Stringable $message, array $context = []): void - { - $this->log(LogLevel::CRITICAL, $message, $context); - } - - /** - * Runtime errors that do not require immediate action but should typically - * be logged and monitored. - * - * @param string|\Stringable $message - * @param array $context - * - * @return void - */ - public function error(string|\Stringable $message, array $context = []): void - { - $this->log(LogLevel::ERROR, $message, $context); - } - - /** - * Exceptional occurrences that are not errors. - * - * Example: Use of deprecated APIs, poor use of an API, undesirable things - * that are not necessarily wrong. - * - * @param string|\Stringable $message - * @param array $context - * - * @return void - */ - public function warning(string|\Stringable $message, array $context = []): void - { - $this->log(LogLevel::WARNING, $message, $context); - } - - /** - * Normal but significant events. - * - * @param string|\Stringable $message - * @param array $context - * - * @return void - */ - public function notice(string|\Stringable $message, array $context = []): void - { - $this->log(LogLevel::NOTICE, $message, $context); - } - - /** - * Interesting events. - * - * Example: User logs in, SQL logs. - * - * @param string|\Stringable $message - * @param array $context - * - * @return void - */ - public function info(string|\Stringable $message, array $context = []): void - { - $this->log(LogLevel::INFO, $message, $context); - } - - /** - * Detailed debug information. - * - * @param string|\Stringable $message - * @param array $context - * - * @return void - */ - public function debug(string|\Stringable $message, array $context = []): void - { - $this->log(LogLevel::DEBUG, $message, $context); - } - - /** - * Logs with an arbitrary level. - * - * @param mixed $level - * @param string|\Stringable $message - * @param array $context - * - * @return void - * - * @throws \Psr\Log\InvalidArgumentException - */ - abstract public function log($level, string|\Stringable $message, array $context = []): void; -} diff --git a/monolog/vendor/psr/log/src/NullLogger.php b/monolog/vendor/psr/log/src/NullLogger.php deleted file mode 100644 index c1cc3c069..000000000 --- a/monolog/vendor/psr/log/src/NullLogger.php +++ /dev/null @@ -1,30 +0,0 @@ -logger) { }` - * blocks. - */ -class NullLogger extends AbstractLogger -{ - /** - * Logs with an arbitrary level. - * - * @param mixed $level - * @param string|\Stringable $message - * @param array $context - * - * @return void - * - * @throws \Psr\Log\InvalidArgumentException - */ - public function log($level, string|\Stringable $message, array $context = []): void - { - // noop - } -} From e315abc788881adf0ccdc5c370ba09125188c326 Mon Sep 17 00:00:00 2001 From: Philipp Date: Mon, 17 Jul 2023 00:10:15 +0200 Subject: [PATCH 007/388] Add tests for InstanceManager and remove Decorator hook logic (avoid complex Dice logic) --- monolog/static/hooks.config.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monolog/static/hooks.config.php b/monolog/static/hooks.config.php index cb3c7efaf..7759e678c 100644 --- a/monolog/static/hooks.config.php +++ b/monolog/static/hooks.config.php @@ -19,7 +19,7 @@ * */ -use Friendica\Core\Hooks\Capabilities\HookType as H; +use Friendica\Core\Hooks\Capabilities\BehavioralHookType as H; return [ H::STRATEGY => [ From d9c54193518678408093f21101b1bcc1c5796d57 Mon Sep 17 00:00:00 2001 From: Philipp Date: Fri, 21 Jul 2023 22:41:35 +0200 Subject: [PATCH 008/388] Adhere feedback - rename hooks.config.php to strategies.config.php - change all corresponding classes and tests --- .../static/{hooks.config.php => strategies.config.php} | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) rename monolog/static/{hooks.config.php => strategies.config.php} (83%) diff --git a/monolog/static/hooks.config.php b/monolog/static/strategies.config.php similarity index 83% rename from monolog/static/hooks.config.php rename to monolog/static/strategies.config.php index 7759e678c..87153839a 100644 --- a/monolog/static/hooks.config.php +++ b/monolog/static/strategies.config.php @@ -19,12 +19,8 @@ * */ -use Friendica\Core\Hooks\Capabilities\BehavioralHookType as H; - return [ - H::STRATEGY => [ - \Psr\Log\LoggerInterface::class => [ - \Monolog\Logger::class => ['monolog'], - ], + \Psr\Log\LoggerInterface::class => [ + \Monolog\Logger::class => ['monolog'], ], ]; From bd405ec98a970b36ce725772ae487eddb4c0c3ed Mon Sep 17 00:00:00 2001 From: Philipp Date: Sun, 23 Jul 2023 23:04:11 +0200 Subject: [PATCH 009/388] [monolog] Fix extra line --- monolog/static/dependencies.config.php | 1 - 1 file changed, 1 deletion(-) diff --git a/monolog/static/dependencies.config.php b/monolog/static/dependencies.config.php index 365f38254..e3066594e 100644 --- a/monolog/static/dependencies.config.php +++ b/monolog/static/dependencies.config.php @@ -1,4 +1,3 @@ - Date: Sat, 22 Jul 2023 23:57:38 +0200 Subject: [PATCH 010/388] Introduce .phpunit --- .woodpecker/.phpunit.yml | 115 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 .woodpecker/.phpunit.yml diff --git a/.woodpecker/.phpunit.yml b/.woodpecker/.phpunit.yml new file mode 100644 index 000000000..893d433af --- /dev/null +++ b/.woodpecker/.phpunit.yml @@ -0,0 +1,115 @@ +matrix: + include: + - PHP_MAJOR_VERSION: 7.3 + PHP_VERSION: 7.3.33 + - PHP_MAJOR_VERSION: 7.4 + PHP_VERSION: 7.4.33 + - PHP_MAJOR_VERSION: 8.0 + PHP_VERSION: 8.0.29 + - PHP_MAJOR_VERSION: 8.1 + PHP_VERSION: 8.1.21 + - PHP_MAJOR_VERSION: 8.2 + PHP_VERSION: 8.2.8 + +# This forces PHP Unit executions at the "opensocial" labeled location (because of much more power...) +labels: + location: opensocial + +skip_clone: true + +pipeline: + clone_friendica_base: + image: alpine/git + commands: + - git clone https://github.com/friendica/friendica.git . + - git checkout $CI_COMMIT_BRANCH + clone_friendica_addon: + image: alpine/git + commands: + - git config --global user.email "no-reply@friendi.ca" + - git config --global user.name "Friendica" + - git clone $CI_REPO_LINK addon + - cd addon/ + - git checkout $CI_COMMIT_BRANCH + - git fetch origin $CI_COMMIT_REF + - git merge $CI_COMMIT_SHA + restore_cache: + image: meltwater/drone-cache:dev + settings: + backend: "filesystem" + restore: true + cache_key: "{{ .Repo.Name }}_php${PHP_MAJOR_VERSION}_{{ arch }}_{{ os }}" + archive_format: "gzip" + mount: + - '.composer' + volumes: + - /tmp/drone-cache:/tmp/cache + composer_install: + image: friendicaci/php${PHP_MAJOR_VERSION}:php${PHP_VERSION} + commands: + - export COMPOSER_HOME=.composer + - ./bin/composer.phar validate + - ./bin/composer.phar install --prefer-dist + volumes: + - /etc/hosts:/etc/hosts + rebuild_cache: + image: meltwater/drone-cache:dev + settings: + backend: "filesystem" + rebuild: true + cache_key: "{{ .Repo.Name }}_php${PHP_MAJOR_VERSION}_{{ arch }}_{{ os }}" + archive_format: "gzip" + mount: + - '.composer' + volumes: + - /tmp/drone-cache:/tmp/cache + test: + image: friendicaci/php${PHP_MAJOR_VERSION}:php${PHP_VERSION} + environment: + MYSQL_HOST: "mariadb" + MYSQL_PORT: "3306" + MYSQL_DATABASE: "test" + MYSQL_PASSWORD: "test" + MYSQL_USER: "test" + REDIS_HOST: "redis" + MEMCACHED_HOST: "memcached" + MEMCACHE_HOST: "memcached" + commands: + - cp config/local-sample.config.php config/local.config.php + - if ! bin/wait-for-connection $MYSQL_HOST $MYSQL_PORT 300; then echo "[ERROR] Waited 300 seconds, no response" >&2; exit 1; fi + - mysql -h$MYSQL_HOST -P$MYSQL_PORT -p$MYSQL_PASSWORD -u$MYSQL_USER $MYSQL_DATABASE < database.sql + - if [ "${PHP_MAJOR_VERSION}" = "7.4" -a "${CI_REPO}" = "friendica/friendica-addons" ]; then + phpenmod xdebug; + export XDEBUG_MODE=coverage; + phpunit --configuration tests/phpunit-addons.xml --coverage-clover clover.xml; + else + phpunit --configuration tests/phpunit-addons.xml; + fi + codecov: + image: friendicaci/codecov + when: + matrix: + PHP_MAJOR_VERSION: 7.4 + PHP_VERSION: 7.4.33 + repo: + - friendica/friendica-addons + commands: + - codecov -R '.' -Z -f 'clover.xml' + secrets: + - source: codecov-token + target: codecov_token + +services: + mariadb: + image: mariadb:latest + environment: + MYSQL_ALLOW_EMPTY_PASSWORD: "true" + MYSQL_DATABASE: "test" + MYSQL_PASSWORD: "test" + MYSQL_USER: "test" + + memcached: + image: memcached + + redis: + image: redis From dc55b89e02faa247d397968acb277a954da3b715 Mon Sep 17 00:00:00 2001 From: Philipp Date: Sun, 23 Jul 2023 03:21:40 +0200 Subject: [PATCH 011/388] Unify "Capability" From a97b3f690c9e4476ba638236897507100f77af6f Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 9 Aug 2023 20:01:57 +0000 Subject: [PATCH 012/388] Twitter: the connector now works as a posting only connector --- twitter/LICENSE | 24 - twitter/README.md | 36 +- twitter/composer.json | 32 - twitter/composer.lock | 328 -- twitter/config/twitter.config.php | 16 - twitter/lang/C/messages.po | 135 +- twitter/lighter.png | Bin 2490 -> 0 bytes twitter/templates/admin.tpl | 4 - twitter/templates/connector_settings.tpl | 28 +- twitter/twitter.css | 12 - twitter/twitter.php | 2441 +----------- twitter/twitter_sync.php | 31 - .../twitteroauth/.github/dependabot.yml | 14 - .../twitteroauth/.github/workflows/lint.yaml | 12 - .../twitteroauth/.github/workflows/test.yaml | 18 - .../vendor/abraham/twitteroauth/.gitignore | 5 - .../abraham/twitteroauth/.prettierignore | 3 - .../abraham/twitteroauth/.prettierrc.json | 6 - .../abraham/twitteroauth/CODE_OF_CONDUCT.md | 46 - .../abraham/twitteroauth/CONTRIBUTING.md | 21 - .../vendor/abraham/twitteroauth/LICENSE.md | 22 - twitter/vendor/abraham/twitteroauth/README.md | 11 - .../vendor/abraham/twitteroauth/autoload.php | 35 - .../vendor/abraham/twitteroauth/composer.json | 55 - .../vendor/abraham/twitteroauth/composer.lock | 2761 -------------- .../abraham/twitteroauth/package-lock.json | 511 --- .../vendor/abraham/twitteroauth/package.json | 44 - twitter/vendor/abraham/twitteroauth/phpmd.xml | 15 - .../vendor/abraham/twitteroauth/phpunit.xml | 18 - .../abraham/twitteroauth/src/Config.php | 109 - .../abraham/twitteroauth/src/Consumer.php | 43 - .../abraham/twitteroauth/src/HmacSha1.php | 46 - .../abraham/twitteroauth/src/Request.php | 289 -- .../abraham/twitteroauth/src/Response.php | 109 - .../twitteroauth/src/SignatureMethod.php | 78 - .../vendor/abraham/twitteroauth/src/Token.php | 43 - .../abraham/twitteroauth/src/TwitterOAuth.php | 727 ---- .../src/TwitterOAuthException.php | 12 - .../vendor/abraham/twitteroauth/src/Util.php | 122 - .../twitteroauth/src/Util/JsonDecoder.php | 29 - .../tests/AbstractSignatureMethodTest.php | 60 - .../twitteroauth/tests/ConsumerTest.php | 23 - .../twitteroauth/tests/HmacSha1Test.php | 47 - .../abraham/twitteroauth/tests/TokenTest.php | 38 - .../twitteroauth/tests/TwitterOAuthTest.php | 397 -- .../tests/Util/JsonDecoderTest.php | 54 - .../abraham/twitteroauth/tests/bootstrap.php | 10 - ...testDeleteDirectMessagesEventsDestroy.json | 40 - .../testGetAccountVerifyCredentials.json | 46 - .../tests/fixtures/testGetSearchTweets.json | 46 - .../testGetSearchTweetsWithMaxId.json | 46 - .../testGetStatusesMentionsTimeline.json | 49 - .../tests/fixtures/testLastResult.json | 46 - .../tests/fixtures/testOauth2BearerToken.json | 49 - .../tests/fixtures/testOauth2Token.json | 46 - .../fixtures/testOauth2TokenInvalidate.json | 46 - .../testOauthAccessTokenTokenException.json | 45 - .../tests/fixtures/testOauthRequestToken.json | 44 - .../testOauthRequestTokenException.json | 43 - .../testPostDirectMessagesEventsNew.json | 46 - .../fixtures/testPostFavoritesCreate.json | 45 - .../fixtures/testPostFavoritesDestroy.json | 45 - ...UpdateWithInvalidMediaThrowsException.json | 1 - .../fixtures/testPostStatusesDestroy.json | 43 - .../fixtures/testPostStatusesUpdateUtf8.json | 45 - .../testPostStatusesUpdateWithMedia.json | 134 - ...estPostStatusesUpdateWithMediaChunked.json | 2392 ------------ .../tests/fixtures/testResetLastResponse.json | 1 - .../tests/fixtures/testSetOauthToken.json | 46 - .../tests/fixtures/testSetProxy.json | 20 - .../abraham/twitteroauth/tests/kitten.jpg | Bin 207808 -> 0 bytes .../abraham/twitteroauth/tests/mocks.php | 21 - .../abraham/twitteroauth/tests/vars.php | 32 - .../abraham/twitteroauth/tests/video.mp4 | Bin 383631 -> 0 bytes twitter/vendor/autoload.php | 7 - twitter/vendor/composer/ClassLoader.php | 445 --- twitter/vendor/composer/LICENSE | 21 - twitter/vendor/composer/autoload_classmap.php | 14 - .../vendor/composer/autoload_namespaces.php | 9 - twitter/vendor/composer/autoload_psr4.php | 12 - twitter/vendor/composer/autoload_real.php | 55 - twitter/vendor/composer/autoload_static.php | 53 - twitter/vendor/composer/ca-bundle/LICENSE | 19 - twitter/vendor/composer/ca-bundle/README.md | 85 - .../vendor/composer/ca-bundle/composer.json | 54 - .../vendor/composer/ca-bundle/res/cacert.pem | 3138 ---------------- .../composer/ca-bundle/src/CaBundle.php | 353 -- twitter/vendor/composer/installed.json | 317 -- twitter/vendor/composer/installers/LICENSE | 19 - .../vendor/composer/installers/composer.json | 105 - .../src/Composer/Installers/AglInstaller.php | 21 - .../Composer/Installers/AimeosInstaller.php | 9 - .../Installers/AnnotateCmsInstaller.php | 11 - .../Composer/Installers/AsgardInstaller.php | 49 - .../Composer/Installers/AttogramInstaller.php | 9 - .../src/Composer/Installers/BaseInstaller.php | 136 - .../Composer/Installers/BitrixInstaller.php | 126 - .../Composer/Installers/BonefishInstaller.php | 9 - .../Composer/Installers/CakePHPInstaller.php | 82 - .../src/Composer/Installers/ChefInstaller.php | 11 - .../Composer/Installers/CiviCrmInstaller.php | 9 - .../Installers/ClanCatsFrameworkInstaller.php | 10 - .../Composer/Installers/CockpitInstaller.php | 34 - .../Installers/CodeIgniterInstaller.php | 11 - .../Installers/Concrete5Installer.php | 13 - .../Composer/Installers/CraftInstaller.php | 35 - .../Composer/Installers/CroogoInstaller.php | 21 - .../Composer/Installers/DecibelInstaller.php | 10 - .../Composer/Installers/DokuWikiInstaller.php | 50 - .../Composer/Installers/DolibarrInstaller.php | 16 - .../Composer/Installers/DrupalInstaller.php | 16 - .../src/Composer/Installers/ElggInstaller.php | 9 - .../Composer/Installers/EliasisInstaller.php | 12 - .../Installers/ExpressionEngineInstaller.php | 29 - .../Installers/EzPlatformInstaller.php | 10 - .../src/Composer/Installers/FuelInstaller.php | 11 - .../Composer/Installers/FuelphpInstaller.php | 9 - .../src/Composer/Installers/GravInstaller.php | 30 - .../Composer/Installers/HuradInstaller.php | 25 - .../Composer/Installers/ImageCMSInstaller.php | 11 - .../src/Composer/Installers/Installer.php | 274 -- .../src/Composer/Installers/ItopInstaller.php | 9 - .../Composer/Installers/JoomlaInstaller.php | 15 - .../Composer/Installers/KanboardInstaller.php | 18 - .../Composer/Installers/KirbyInstaller.php | 11 - .../Composer/Installers/KodiCMSInstaller.php | 10 - .../Composer/Installers/KohanaInstaller.php | 9 - .../LanManagementSystemInstaller.php | 27 - .../Composer/Installers/LaravelInstaller.php | 9 - .../Composer/Installers/LavaLiteInstaller.php | 10 - .../Composer/Installers/LithiumInstaller.php | 10 - .../Installers/MODULEWorkInstaller.php | 9 - .../Composer/Installers/MODXEvoInstaller.php | 16 - .../Composer/Installers/MagentoInstaller.php | 11 - .../Composer/Installers/MajimaInstaller.php | 37 - .../src/Composer/Installers/MakoInstaller.php | 9 - .../Composer/Installers/MauticInstaller.php | 25 - .../src/Composer/Installers/MayaInstaller.php | 33 - .../Installers/MediaWikiInstaller.php | 51 - .../Installers/MicroweberInstaller.php | 111 - .../src/Composer/Installers/ModxInstaller.php | 12 - .../Composer/Installers/MoodleInstaller.php | 57 - .../Composer/Installers/OctoberInstaller.php | 47 - .../Composer/Installers/OntoWikiInstaller.php | 24 - .../Composer/Installers/OsclassInstaller.php | 14 - .../src/Composer/Installers/OxidInstaller.php | 59 - .../src/Composer/Installers/PPIInstaller.php | 9 - .../Composer/Installers/PhiftyInstaller.php | 11 - .../Composer/Installers/PhpBBInstaller.php | 11 - .../Composer/Installers/PimcoreInstaller.php | 21 - .../Composer/Installers/PiwikInstaller.php | 32 - .../Installers/PlentymarketsInstaller.php | 29 - .../src/Composer/Installers/Plugin.php | 17 - .../Composer/Installers/PortoInstaller.php | 9 - .../Installers/PrestashopInstaller.php | 10 - .../Composer/Installers/PuppetInstaller.php | 11 - .../Composer/Installers/PxcmsInstaller.php | 63 - .../Composer/Installers/RadPHPInstaller.php | 24 - .../Composer/Installers/ReIndexInstaller.php | 10 - .../Composer/Installers/RedaxoInstaller.php | 10 - .../Installers/RoundcubeInstaller.php | 22 - .../src/Composer/Installers/SMFInstaller.php | 10 - .../Composer/Installers/ShopwareInstaller.php | 60 - .../Installers/SilverStripeInstaller.php | 35 - .../Installers/SiteDirectInstaller.php | 25 - .../Composer/Installers/SyDESInstaller.php | 49 - .../Composer/Installers/Symfony1Installer.php | 26 - .../Composer/Installers/TYPO3CmsInstaller.php | 16 - .../Installers/TYPO3FlowInstaller.php | 38 - .../Composer/Installers/TheliaInstaller.php | 12 - .../src/Composer/Installers/TuskInstaller.php | 14 - .../Installers/UserFrostingInstaller.php | 9 - .../Composer/Installers/VanillaInstaller.php | 10 - .../Composer/Installers/VgmcpInstaller.php | 49 - .../Composer/Installers/WHMCSInstaller.php | 10 - .../Composer/Installers/WolfCMSInstaller.php | 9 - .../Installers/WordPressInstaller.php | 12 - .../Composer/Installers/YawikInstaller.php | 32 - .../src/Composer/Installers/ZendInstaller.php | 11 - .../Composer/Installers/ZikulaInstaller.php | 10 - .../composer/installers/src/bootstrap.php | 13 - .../jublonet/codebird-php/.gitattributes | 2 - .../vendor/jublonet/codebird-php/.gitignore | 7 - .../vendor/jublonet/codebird-php/.travis.yml | 47 - .../vendor/jublonet/codebird-php/CHANGELOG | 185 - .../jublonet/codebird-php/CONTRIBUTING.md | 11 - twitter/vendor/jublonet/codebird-php/LICENSE | 674 ---- .../vendor/jublonet/codebird-php/README.md | 891 ----- .../vendor/jublonet/codebird-php/bower.json | 25 - .../vendor/jublonet/codebird-php/build.xml | 115 - .../jublonet/codebird-php/composer.json | 45 - .../vendor/jublonet/codebird-php/phpunit.xml | 26 - .../jublonet/codebird-php/phpunit.xml.hhvm | 22 - .../jublonet/codebird-php/src/cacert.pem | 3314 ----------------- .../jublonet/codebird-php/src/codebird.php | 2720 -------------- .../vendor/jublonet/codebird-php/test/README | 16 - .../jublonet/codebird-php/test/codebirdm.php | 204 - .../jublonet/codebird-php/test/codebirdt.php | 97 - .../codebird-php/test/constant_tests.php | 40 - .../jublonet/codebird-php/test/curl_tests.php | 57 - .../codebird-php/test/detection_tests.php | 288 -- .../codebird-php/test/environment_test.php | 40 - .../codebird-php/test/media_tests.php | 56 - .../codebird-php/test/oauth_tests.php | 130 - .../codebird-php/test/replyparse_tests.php | 361 -- .../codebird-php/test/requestparse_tests.php | 212 -- .../codebird-php/test/returnformat_tests.php | 70 - .../codebird-php/test/setter_tests.php | 253 -- .../codebird-php/test/signing_tests.php | 166 - .../codebird-php/test/singleton_tests.php | 31 - 210 files changed, 159 insertions(+), 29479 deletions(-) delete mode 100644 twitter/LICENSE delete mode 100644 twitter/composer.json delete mode 100644 twitter/composer.lock delete mode 100644 twitter/config/twitter.config.php delete mode 100644 twitter/lighter.png delete mode 100644 twitter/templates/admin.tpl delete mode 100644 twitter/twitter.css delete mode 100644 twitter/twitter_sync.php delete mode 100644 twitter/vendor/abraham/twitteroauth/.github/dependabot.yml delete mode 100644 twitter/vendor/abraham/twitteroauth/.github/workflows/lint.yaml delete mode 100644 twitter/vendor/abraham/twitteroauth/.github/workflows/test.yaml delete mode 100644 twitter/vendor/abraham/twitteroauth/.gitignore delete mode 100644 twitter/vendor/abraham/twitteroauth/.prettierignore delete mode 100644 twitter/vendor/abraham/twitteroauth/.prettierrc.json delete mode 100644 twitter/vendor/abraham/twitteroauth/CODE_OF_CONDUCT.md delete mode 100644 twitter/vendor/abraham/twitteroauth/CONTRIBUTING.md delete mode 100644 twitter/vendor/abraham/twitteroauth/LICENSE.md delete mode 100644 twitter/vendor/abraham/twitteroauth/README.md delete mode 100644 twitter/vendor/abraham/twitteroauth/autoload.php delete mode 100644 twitter/vendor/abraham/twitteroauth/composer.json delete mode 100644 twitter/vendor/abraham/twitteroauth/composer.lock delete mode 100644 twitter/vendor/abraham/twitteroauth/package-lock.json delete mode 100644 twitter/vendor/abraham/twitteroauth/package.json delete mode 100644 twitter/vendor/abraham/twitteroauth/phpmd.xml delete mode 100644 twitter/vendor/abraham/twitteroauth/phpunit.xml delete mode 100644 twitter/vendor/abraham/twitteroauth/src/Config.php delete mode 100644 twitter/vendor/abraham/twitteroauth/src/Consumer.php delete mode 100644 twitter/vendor/abraham/twitteroauth/src/HmacSha1.php delete mode 100644 twitter/vendor/abraham/twitteroauth/src/Request.php delete mode 100644 twitter/vendor/abraham/twitteroauth/src/Response.php delete mode 100644 twitter/vendor/abraham/twitteroauth/src/SignatureMethod.php delete mode 100644 twitter/vendor/abraham/twitteroauth/src/Token.php delete mode 100644 twitter/vendor/abraham/twitteroauth/src/TwitterOAuth.php delete mode 100644 twitter/vendor/abraham/twitteroauth/src/TwitterOAuthException.php delete mode 100644 twitter/vendor/abraham/twitteroauth/src/Util.php delete mode 100644 twitter/vendor/abraham/twitteroauth/src/Util/JsonDecoder.php delete mode 100644 twitter/vendor/abraham/twitteroauth/tests/AbstractSignatureMethodTest.php delete mode 100644 twitter/vendor/abraham/twitteroauth/tests/ConsumerTest.php delete mode 100644 twitter/vendor/abraham/twitteroauth/tests/HmacSha1Test.php delete mode 100644 twitter/vendor/abraham/twitteroauth/tests/TokenTest.php delete mode 100644 twitter/vendor/abraham/twitteroauth/tests/TwitterOAuthTest.php delete mode 100644 twitter/vendor/abraham/twitteroauth/tests/Util/JsonDecoderTest.php delete mode 100644 twitter/vendor/abraham/twitteroauth/tests/bootstrap.php delete mode 100644 twitter/vendor/abraham/twitteroauth/tests/fixtures/testDeleteDirectMessagesEventsDestroy.json delete mode 100644 twitter/vendor/abraham/twitteroauth/tests/fixtures/testGetAccountVerifyCredentials.json delete mode 100644 twitter/vendor/abraham/twitteroauth/tests/fixtures/testGetSearchTweets.json delete mode 100644 twitter/vendor/abraham/twitteroauth/tests/fixtures/testGetSearchTweetsWithMaxId.json delete mode 100644 twitter/vendor/abraham/twitteroauth/tests/fixtures/testGetStatusesMentionsTimeline.json delete mode 100644 twitter/vendor/abraham/twitteroauth/tests/fixtures/testLastResult.json delete mode 100644 twitter/vendor/abraham/twitteroauth/tests/fixtures/testOauth2BearerToken.json delete mode 100644 twitter/vendor/abraham/twitteroauth/tests/fixtures/testOauth2Token.json delete mode 100644 twitter/vendor/abraham/twitteroauth/tests/fixtures/testOauth2TokenInvalidate.json delete mode 100644 twitter/vendor/abraham/twitteroauth/tests/fixtures/testOauthAccessTokenTokenException.json delete mode 100644 twitter/vendor/abraham/twitteroauth/tests/fixtures/testOauthRequestToken.json delete mode 100644 twitter/vendor/abraham/twitteroauth/tests/fixtures/testOauthRequestTokenException.json delete mode 100644 twitter/vendor/abraham/twitteroauth/tests/fixtures/testPostDirectMessagesEventsNew.json delete mode 100644 twitter/vendor/abraham/twitteroauth/tests/fixtures/testPostFavoritesCreate.json delete mode 100644 twitter/vendor/abraham/twitteroauth/tests/fixtures/testPostFavoritesDestroy.json delete mode 100644 twitter/vendor/abraham/twitteroauth/tests/fixtures/testPostStatusUpdateWithInvalidMediaThrowsException.json delete mode 100644 twitter/vendor/abraham/twitteroauth/tests/fixtures/testPostStatusesDestroy.json delete mode 100644 twitter/vendor/abraham/twitteroauth/tests/fixtures/testPostStatusesUpdateUtf8.json delete mode 100644 twitter/vendor/abraham/twitteroauth/tests/fixtures/testPostStatusesUpdateWithMedia.json delete mode 100644 twitter/vendor/abraham/twitteroauth/tests/fixtures/testPostStatusesUpdateWithMediaChunked.json delete mode 100644 twitter/vendor/abraham/twitteroauth/tests/fixtures/testResetLastResponse.json delete mode 100644 twitter/vendor/abraham/twitteroauth/tests/fixtures/testSetOauthToken.json delete mode 100644 twitter/vendor/abraham/twitteroauth/tests/fixtures/testSetProxy.json delete mode 100644 twitter/vendor/abraham/twitteroauth/tests/kitten.jpg delete mode 100644 twitter/vendor/abraham/twitteroauth/tests/mocks.php delete mode 100644 twitter/vendor/abraham/twitteroauth/tests/vars.php delete mode 100644 twitter/vendor/abraham/twitteroauth/tests/video.mp4 delete mode 100644 twitter/vendor/autoload.php delete mode 100644 twitter/vendor/composer/ClassLoader.php delete mode 100644 twitter/vendor/composer/LICENSE delete mode 100644 twitter/vendor/composer/autoload_classmap.php delete mode 100644 twitter/vendor/composer/autoload_namespaces.php delete mode 100644 twitter/vendor/composer/autoload_psr4.php delete mode 100644 twitter/vendor/composer/autoload_real.php delete mode 100644 twitter/vendor/composer/autoload_static.php delete mode 100644 twitter/vendor/composer/ca-bundle/LICENSE delete mode 100644 twitter/vendor/composer/ca-bundle/README.md delete mode 100644 twitter/vendor/composer/ca-bundle/composer.json delete mode 100644 twitter/vendor/composer/ca-bundle/res/cacert.pem delete mode 100644 twitter/vendor/composer/ca-bundle/src/CaBundle.php delete mode 100644 twitter/vendor/composer/installed.json delete mode 100644 twitter/vendor/composer/installers/LICENSE delete mode 100644 twitter/vendor/composer/installers/composer.json delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/AglInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/AimeosInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/AnnotateCmsInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/AsgardInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/AttogramInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/BaseInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/BitrixInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/BonefishInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/CakePHPInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/ChefInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/CiviCrmInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/ClanCatsFrameworkInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/CockpitInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/CodeIgniterInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/Concrete5Installer.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/CraftInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/CroogoInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/DecibelInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/DokuWikiInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/DolibarrInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/DrupalInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/ElggInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/EliasisInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/ExpressionEngineInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/EzPlatformInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/FuelInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/FuelphpInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/GravInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/HuradInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/ImageCMSInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/Installer.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/ItopInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/JoomlaInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/KanboardInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/KirbyInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/KodiCMSInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/KohanaInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/LanManagementSystemInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/LaravelInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/LavaLiteInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/LithiumInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/MODULEWorkInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/MODXEvoInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/MagentoInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/MajimaInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/MakoInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/MauticInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/MayaInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/MediaWikiInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/MicroweberInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/ModxInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/MoodleInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/OctoberInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/OntoWikiInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/OsclassInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/OxidInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/PPIInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/PhiftyInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/PhpBBInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/PimcoreInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/PiwikInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/PlentymarketsInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/Plugin.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/PortoInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/PrestashopInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/PuppetInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/PxcmsInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/RadPHPInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/ReIndexInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/RedaxoInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/RoundcubeInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/SMFInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/ShopwareInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/SilverStripeInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/SiteDirectInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/SyDESInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/Symfony1Installer.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/TYPO3CmsInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/TYPO3FlowInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/TheliaInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/TuskInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/UserFrostingInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/VanillaInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/VgmcpInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/WHMCSInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/WolfCMSInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/WordPressInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/YawikInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/ZendInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/Composer/Installers/ZikulaInstaller.php delete mode 100644 twitter/vendor/composer/installers/src/bootstrap.php delete mode 100644 twitter/vendor/jublonet/codebird-php/.gitattributes delete mode 100644 twitter/vendor/jublonet/codebird-php/.gitignore delete mode 100644 twitter/vendor/jublonet/codebird-php/.travis.yml delete mode 100644 twitter/vendor/jublonet/codebird-php/CHANGELOG delete mode 100644 twitter/vendor/jublonet/codebird-php/CONTRIBUTING.md delete mode 100644 twitter/vendor/jublonet/codebird-php/LICENSE delete mode 100644 twitter/vendor/jublonet/codebird-php/README.md delete mode 100644 twitter/vendor/jublonet/codebird-php/bower.json delete mode 100644 twitter/vendor/jublonet/codebird-php/build.xml delete mode 100644 twitter/vendor/jublonet/codebird-php/composer.json delete mode 100644 twitter/vendor/jublonet/codebird-php/phpunit.xml delete mode 100644 twitter/vendor/jublonet/codebird-php/phpunit.xml.hhvm delete mode 100644 twitter/vendor/jublonet/codebird-php/src/cacert.pem delete mode 100644 twitter/vendor/jublonet/codebird-php/src/codebird.php delete mode 100644 twitter/vendor/jublonet/codebird-php/test/README delete mode 100644 twitter/vendor/jublonet/codebird-php/test/codebirdm.php delete mode 100644 twitter/vendor/jublonet/codebird-php/test/codebirdt.php delete mode 100644 twitter/vendor/jublonet/codebird-php/test/constant_tests.php delete mode 100644 twitter/vendor/jublonet/codebird-php/test/curl_tests.php delete mode 100644 twitter/vendor/jublonet/codebird-php/test/detection_tests.php delete mode 100644 twitter/vendor/jublonet/codebird-php/test/environment_test.php delete mode 100644 twitter/vendor/jublonet/codebird-php/test/media_tests.php delete mode 100644 twitter/vendor/jublonet/codebird-php/test/oauth_tests.php delete mode 100644 twitter/vendor/jublonet/codebird-php/test/replyparse_tests.php delete mode 100644 twitter/vendor/jublonet/codebird-php/test/requestparse_tests.php delete mode 100644 twitter/vendor/jublonet/codebird-php/test/returnformat_tests.php delete mode 100644 twitter/vendor/jublonet/codebird-php/test/setter_tests.php delete mode 100644 twitter/vendor/jublonet/codebird-php/test/signing_tests.php delete mode 100644 twitter/vendor/jublonet/codebird-php/test/singleton_tests.php diff --git a/twitter/LICENSE b/twitter/LICENSE deleted file mode 100644 index 496cce20d..000000000 --- a/twitter/LICENSE +++ /dev/null @@ -1,24 +0,0 @@ -Copyright (c) 2011-2018 Tobias Diekershoff, Michael Vogel, Hypolite Petovan -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/twitter/README.md b/twitter/README.md index 7e0fabc51..038bf1ca7 100644 --- a/twitter/README.md +++ b/twitter/README.md @@ -3,44 +3,14 @@ Twitter Addon Main authors Tobias Diekershoff, Michael Vogel and Hypolite Petovan. -This bi-directional connector addon allows each user to crosspost their Friendica public posts to Twitter, import their Twitter timeline, interact with tweets from Friendica, and crosspost to Friendica their public tweets. +This is a uni-directional posting connector addon that allows each user to crosspost their Friendica public posts to Twitter. ## Installation -To use this addon you have to register an [application](https://apps.twitter.com/) for your Friendica instance on Twitter. -Register your Friendica site as "Client" application with "Read & Write" access we do not need "Twitter as login". -Please leave the field "Callback URL" empty. -When you've registered the app you get the OAuth Consumer key and secret pair for your application/site. - -After the registration please enter the values for "Consumer Key" and "Consumer Secret" in the [administration](admin/addons/twitter). - -## Alternative configuration - -Open the `config/local.config.php` file and add "twitter" to the list of activated addons: - - 'addons' => [ - ... - 'twitter' => [ - admin => true, - ], - ] - -Add your key pair to your `config/twitter.config.php` file. - - return [ - 'twitter' => [ - 'consumerkey' => 'your consumer_key here', - 'consumersecret' => 'your consumer_secret here', - ], - ]; - -After this, users can configure their Twitter account settings from "Settings -> Addon Settings". +To use this addon each single user has to register their own [application](https://developer.twitter.com/en/portal/projects-and-apps), no setup is needed by the administration. ## License -The _Twitter Connector_ is licensed under the [3-clause BSD license][2] see the LICENSE file in the addons directory. - -The _Twitter Connector_ uses the [Twitter OAuth library][2] by Abraham Williams, MIT licensed +The _Twitter Connector_ is licensed under the [3-clause BSD license][1] see the LICENSE file in the addons directory. [1]: http://opensource.org/licenses/BSD-3-Clause -[2]: https://github.com/abraham/twitteroauth diff --git a/twitter/composer.json b/twitter/composer.json deleted file mode 100644 index 750901951..000000000 --- a/twitter/composer.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "name": "friendica-addons/twitter", - "description": "Twitter Connector addon for Friendica", - "type": "friendica-addon", - "authors": [ - { - "name": "Tobias Diekershoff", - "homepage": "https://f.diekershoff.de/profile/tobias", - "role": "Developer" - }, - { - "name": "Michael Vogel", - "homepage": "https://pirati.ca/profile/heluecht", - "role": "Developer" - }, - { - "name": "Hypolite Petovan", - "email": "hypolite@mrpetovan.com", - "homepage": "https://friendica.mrpetovan.com/profile/hypolite", - "role": "Developer" - } - ], - "require": { - "abraham/twitteroauth": "2.0.0", - "jublonet/codebird-php": "dev-master" - }, - "license": "3-clause BSD license", - "minimum-stability": "stable", - "config": { - "autoloader-suffix": "TwitterAddon" - } -} diff --git a/twitter/composer.lock b/twitter/composer.lock deleted file mode 100644 index 80583397c..000000000 --- a/twitter/composer.lock +++ /dev/null @@ -1,328 +0,0 @@ -{ - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", - "This file is @generated automatically" - ], - "content-hash": "fafd1db0b4f04c4268f5034ce8c7f6ea", - "packages": [ - { - "name": "abraham/twitteroauth", - "version": "2.0.0", - "source": { - "type": "git", - "url": "https://github.com/abraham/twitteroauth.git", - "reference": "96f49e67baec10f5e5cb703d87be16ba01a798a5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/abraham/twitteroauth/zipball/96f49e67baec10f5e5cb703d87be16ba01a798a5", - "reference": "96f49e67baec10f5e5cb703d87be16ba01a798a5", - "shasum": "" - }, - "require": { - "composer/ca-bundle": "^1.2", - "ext-curl": "*", - "php": "^7.2 || ^7.3 || ^7.4 || ^8.0" - }, - "require-dev": { - "php-vcr/php-vcr": "^1", - "php-vcr/phpunit-testlistener-vcr": "dev-php-8", - "phpmd/phpmd": "^2", - "phpunit/phpunit": "^8", - "squizlabs/php_codesniffer": "^3" - }, - "type": "library", - "autoload": { - "psr-4": { - "Abraham\\TwitterOAuth\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Abraham Williams", - "email": "abraham@abrah.am", - "homepage": "https://abrah.am", - "role": "Developer" - } - ], - "description": "The most popular PHP library for use with the Twitter OAuth REST API.", - "homepage": "https://twitteroauth.com", - "keywords": [ - "Twitter API", - "Twitter oAuth", - "api", - "oauth", - "rest", - "social", - "twitter" - ], - "time": "2020-12-02T01:27:06+00:00" - }, - { - "name": "composer/ca-bundle", - "version": "1.2.10", - "source": { - "type": "git", - "url": "https://github.com/composer/ca-bundle.git", - "reference": "9fdb22c2e97a614657716178093cd1da90a64aa8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/ca-bundle/zipball/9fdb22c2e97a614657716178093cd1da90a64aa8", - "reference": "9fdb22c2e97a614657716178093cd1da90a64aa8", - "shasum": "" - }, - "require": { - "ext-openssl": "*", - "ext-pcre": "*", - "php": "^5.3.2 || ^7.0 || ^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^0.12.55", - "psr/log": "^1.0", - "symfony/phpunit-bridge": "^4.2 || ^5", - "symfony/process": "^2.5 || ^3.0 || ^4.0 || ^5.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\CaBundle\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - } - ], - "description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.", - "keywords": [ - "cabundle", - "cacert", - "certificate", - "ssl", - "tls" - ], - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2021-06-07T13:58:28+00:00" - }, - { - "name": "composer/installers", - "version": "v1.6.0", - "source": { - "type": "git", - "url": "https://github.com/composer/installers.git", - "reference": "cfcca6b1b60bc4974324efb5783c13dca6932b5b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/installers/zipball/cfcca6b1b60bc4974324efb5783c13dca6932b5b", - "reference": "cfcca6b1b60bc4974324efb5783c13dca6932b5b", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^1.0" - }, - "replace": { - "roundcube/plugin-installer": "*", - "shama/baton": "*" - }, - "require-dev": { - "composer/composer": "1.0.*@dev", - "phpunit/phpunit": "^4.8.36" - }, - "type": "composer-plugin", - "extra": { - "class": "Composer\\Installers\\Plugin", - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\Installers\\": "src/Composer/Installers" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Kyle Robinson Young", - "email": "kyle@dontkry.com", - "homepage": "https://github.com/shama" - } - ], - "description": "A multi-framework Composer library installer", - "homepage": "https://composer.github.io/installers/", - "keywords": [ - "Craft", - "Dolibarr", - "Eliasis", - "Hurad", - "ImageCMS", - "Kanboard", - "Lan Management System", - "MODX Evo", - "Mautic", - "Maya", - "OXID", - "Plentymarkets", - "Porto", - "RadPHP", - "SMF", - "Thelia", - "WolfCMS", - "agl", - "aimeos", - "annotatecms", - "attogram", - "bitrix", - "cakephp", - "chef", - "cockpit", - "codeigniter", - "concrete5", - "croogo", - "dokuwiki", - "drupal", - "eZ Platform", - "elgg", - "expressionengine", - "fuelphp", - "grav", - "installer", - "itop", - "joomla", - "kohana", - "laravel", - "lavalite", - "lithium", - "magento", - "majima", - "mako", - "mediawiki", - "modulework", - "modx", - "moodle", - "osclass", - "phpbb", - "piwik", - "ppi", - "puppet", - "pxcms", - "reindex", - "roundcube", - "shopware", - "silverstripe", - "sydes", - "symfony", - "typo3", - "wordpress", - "yawik", - "zend", - "zikula" - ], - "time": "2018-08-27T06:10:37+00:00" - }, - { - "name": "jublonet/codebird-php", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/jublo/codebird-php.git", - "reference": "df362d8ad629aad6c4c7dbf36a440e569ec41368" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/jublo/codebird-php/zipball/df362d8ad629aad6c4c7dbf36a440e569ec41368", - "reference": "df362d8ad629aad6c4c7dbf36a440e569ec41368", - "shasum": "" - }, - "require": { - "composer/installers": "~1.0", - "ext-hash": "*", - "ext-json": "*", - "lib-openssl": "*", - "php": ">=5.5.0" - }, - "require-dev": { - "php-coveralls/php-coveralls": ">=0.6", - "phpunit/phpunit": ">=7.3", - "squizlabs/php_codesniffer": "2.*" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "GPL-3.0+" - ], - "authors": [ - { - "name": "Joshua Atkins", - "role": "Developer", - "email": "joshua.atkins@jublo.net", - "homepage": "http://atkins.im/" - }, - { - "name": "J.M.", - "role": "Developer", - "email": "jm@jublo.net", - "homepage": "http://mynetx.net/" - } - ], - "description": "Easy access to the Twitter REST API, Direct Messages API, Account Activity API, TON (Object Nest) API and Twitter Ads API — all from one PHP library.", - "homepage": "https://www.jublo.net/projects/codebird/php", - "keywords": [ - "api", - "networking", - "twitter" - ], - "time": "2018-08-16T00:07:08+00:00" - } - ], - "packages-dev": [], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": { - "jublonet/codebird-php": 20 - }, - "prefer-stable": false, - "prefer-lowest": false, - "platform": [], - "platform-dev": [], - "plugin-api-version": "1.1.0" -} diff --git a/twitter/config/twitter.config.php b/twitter/config/twitter.config.php deleted file mode 100644 index 8895814d3..000000000 --- a/twitter/config/twitter.config.php +++ /dev/null @@ -1,16 +0,0 @@ - [ - // consumerkey (String) - // OAuth Consumer Key provided by Twitter on registering an app at https://twitter.com/apps - 'consumerkey' => '', - - // consumersecret (String) - // OAuth Consumer Secret provided by Twitter on registering an app at https://twitter.com/apps - 'consumersecret' => '', - ], -]; diff --git a/twitter/lang/C/messages.po b/twitter/lang/C/messages.po index bbab254d6..4bcc4efa5 100644 --- a/twitter/lang/C/messages.po +++ b/twitter/lang/C/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-06-03 15:50-0400\n" +"POT-Creation-Date: 2023-08-09 19:59+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,143 +17,50 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: twitter.php:220 +#: twitter.php:80 msgid "Post to Twitter" msgstr "" -#: twitter.php:267 -msgid "" -"You submitted an empty PIN, please Sign In with Twitter again to get a new " -"one." -msgstr "" - -#: twitter.php:334 -msgid "" -"No consumer key pair for Twitter found. Please contact your site " -"administrator." -msgstr "" - -#: twitter.php:347 -msgid "" -"At this Friendica instance the Twitter addon was enabled but you have not " -"yet connected your account to your Twitter account. To do so click the " -"button below to get a PIN from Twitter which you have to copy into the input " -"box below and submit the form. Only your public posts will " -"be posted to Twitter." -msgstr "" - -#: twitter.php:348 -msgid "Log in with Twitter" -msgstr "" - -#: twitter.php:350 -msgid "Copy the PIN from Twitter here" -msgstr "" - -#: twitter.php:358 twitter.php:403 -msgid "An error occured: " -msgstr "" - -#: twitter.php:372 -#, php-format -msgid "" -"Currently connected to: %1$s" -msgstr "" - -#: twitter.php:378 -msgid "" -"Note: Due to your privacy settings (Hide your profile " -"details from unknown viewers?) the link potentially included in public " -"postings relayed to Twitter will lead the visitor to a blank page informing " -"the visitor that the access to your profile has been restricted." -msgstr "" - -#: twitter.php:385 -msgid "Invalid Twitter info" -msgstr "" - -#: twitter.php:386 -msgid "Disconnect" -msgstr "" - -#: twitter.php:391 +#: twitter.php:117 msgid "Allow posting to Twitter" msgstr "" -#: twitter.php:391 +#: twitter.php:117 msgid "" "If enabled all your public postings can be posted to the " "associated Twitter account. You can choose to do so by default (here) or for " "every posting separately in the posting options when writing the entry." msgstr "" -#: twitter.php:392 +#: twitter.php:118 msgid "Send public postings to Twitter by default" msgstr "" -#: twitter.php:393 -msgid "Use threads instead of truncating the content" +#: twitter.php:119 +msgid "API Key" msgstr "" -#: twitter.php:394 -msgid "Mirror all posts from twitter that are no replies" +#: twitter.php:120 +msgid "API Secret" msgstr "" -#: twitter.php:395 -msgid "Import the remote timeline" +#: twitter.php:121 +msgid "Access Token" msgstr "" -#: twitter.php:396 -msgid "Automatically create contacts" +#: twitter.php:122 +msgid "Access Secret" msgstr "" -#: twitter.php:396 +#: twitter.php:123 msgid "" -"This will automatically create a contact in Friendica as soon as you receive " -"a message from an existing contact via the Twitter network. If you do not " -"enable this, you need to manually add those Twitter contacts in Friendica " -"from whom you would like to see posts here." +"Each user needs to register their own app to be able to post to Twitter. " +"Please visit https://developer.twitter.com/en/portal/projects-and-apps to " +"register a project. Inside the project you then have to register an app. You " +"will find the needed data for the connector on the page \"Keys and token\" " +"in the app settings." msgstr "" -#: twitter.php:397 -msgid "Follow in fediverse" -msgstr "" - -#: twitter.php:397 -msgid "" -"Automatically subscribe to the contact in the fediverse, when a fediverse " -"account is mentioned in name or description and we are following the Twitter " -"contact." -msgstr "" - -#: twitter.php:410 -msgid "Twitter Import/Export/Mirror" -msgstr "" - -#: twitter.php:567 -msgid "" -"Please connect a Twitter account in your Social Network settings to import " -"Twitter posts." -msgstr "" - -#: twitter.php:574 -msgid "Twitter post not found." -msgstr "" - -#: twitter.php:999 -msgid "Save Settings" -msgstr "" - -#: twitter.php:1001 -msgid "Consumer key" -msgstr "" - -#: twitter.php:1002 -msgid "Consumer secret" -msgstr "" - -#: twitter.php:1200 -#, php-format -msgid "%s on Twitter" +#: twitter.php:128 +msgid "Twitter Export" msgstr "" diff --git a/twitter/lighter.png b/twitter/lighter.png deleted file mode 100644 index 297bb03404f2d7462ee9355aae38f5f5f3e47fbd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2490 zcmV;r2}SmaP)dbVG7wVRUJ4ZXi@?ZDjy8FEKeU zFgbGL({lg-0338hSaefwW^{L9a%BKPWN%_+AVz6&Wp{6KYjYq&Q#1y$)1UwV2@^>~ zK~!jg?VEdWl+_u=f8X9WA)72QVM!vF1VSK4AZQ?nK}o}NseS3JN$f zgRQMIo!W~OJ6`ZouvAJ_K&eH%O=zU35Dd9+OGJ}EvYTu++57IdU;kJVc9XpY6B?a; zX3k{ZIp=-eC+|7m`<-)kR{+>vQ7sWi9D|5ebEgWz_KIq$s4!>9f*d_|j-lj_V|e1| zv2!Q@e7>PCTvsDT9K#C=07>!<2 zJRT3v{^4m(e0B`AMuXes=AQD^+;C$tPj22q>4H*zdfz>`#KAid3>9xAeo+*W%jE#P zv+pgwyLbU*^X6iX@D|vxdJPV{BV^y=rMIzo>FtA}CzL%H7|@3PC-uR0k{o`MEpT&+ zmiCUwd$DjaD&G5mR^R=5Ugy>A zFL6`pd;osE=`rd~)-ZEc5shchvh}x5aZ~9nJpS;;UjCggyhMFX4IM@k^;K2OnpeX9 zJ+G59W-M>Ndx+<@J`*QB2?^MN1N-(fead7?=HEi6T!B@Box5IR=L;`>Ej{PX zHuTf??pp_V_K#2V&%f=WuDXUP)2>6K(eP;bS}ruV@b7*5sr;ydIrB8I2tIsDgsYdEB~aA*X6k7? zxX|2;qp^|Gwe@`Y#d&IupCC)EqUw`l7)GU&uTKu*U$o?QG#U*z%qZYj8`hDRoCLu8 zhbzgOI5DbLyT^;&?d{E@=<{Loc(HlBWQ@7?YwIarxgyB6oH@guS9eiXI-mWozJlq( z1uEY@fC2%N(MZ*iqs%Lw&3$(-XHs%f#Ci8GF3A_N^~J`q@N(Yec4#`>p8;Rm>`^(w z^()mX);zY6A1}KTOQ(hBpZ+tI2M_vvC6EgOasg^TuSW9u`2L~=xMTvlF=IdirA&q( z01}jz+(`M#6-+Id=Jypvl2wZSngV!x>{xvBuA7QRt)c4kYU--0D3~!Fhr>aA^+`_G z)iHDWG@POs#IMsQgCL+*sYp&si#>KieJ zAZPaXZl!3>9M-SjNX7dfvh?=bdf)$&1YWO*1jqy#ZFVPakM~lt{ns24pi(Mnce*e+ zoV|U5)IWA0uWtapa=C)>xf3{EU4zZ(WX19y(%RC@hySVMd_x1@*}REPr@KGD1PCBr zszd|P3jULJU(P|*6JUEpf1ZUYMN@b5y{gO~R0`R^ zzo2^1b1iYS>vBugsL9qPM&yVTyCwWp(Uo=ev@y*W7rS{ZmOePbh#j}_&X%YtxeZa(=9L5<&(e8Bi z<5wsYm^&^0MKr*8(egMLdIIf9`S}2Jn9Y=xl~T570XoAdF4!DlHH6a}anEJ-cv*VQ z<;7KRgYq-}Q)5qi@;qcECS38JtLDV#Y+3g(n;(3LUp}&dB%O}ct5)I-xFV2%>k11g zTUf@C&yKTa*KVdw^(R50loR*{_b2SKCHeZt4jkLpj^;ZlKOe6sQZ!>aT9uM(b0*;N zdYL_=0IS=B(gj7|CTgIo3w=s5DLNgUE;lDl z=6*ck(9~r1FRqNt5);TzP2p%4ylH~wfExv!+`pk8s}?!j(i+mgrP)GJVGd2L zrifxR3OQ=I9MLCX4Ray;#3LJ#2{HtkfT^vG#S0hk#JUIhwAC2&WDQrS)2nfk*V=iQ!Y2K(sVlqHpM%x^1{ck;y4Kin5jc`W;@8<8AFx4+YWs z?QSo2A}4+Q<6F?#y0F{r -
diff --git a/twitter/templates/connector_settings.tpl b/twitter/templates/connector_settings.tpl index 5d0061d1f..bdb59891d 100644 --- a/twitter/templates/connector_settings.tpl +++ b/twitter/templates/connector_settings.tpl @@ -1,25 +1,7 @@ -
-{{if $l10n.connected}} -

{{$l10n.connected nofilter}}

-

- - {{$account->description}} -

-{{else}} -

{{$l10n.invalid}}

- -{{/if}} -
- -
- {{include file="field_checkbox.tpl" field=$enable}} -{{if $l10n.privacy_warning}} -

{{$l10n.privacy_warning nofilter}}

-{{/if}} {{include file="field_checkbox.tpl" field=$default}} -{{include file="field_checkbox.tpl" field=$thread}} -{{include file="field_checkbox.tpl" field=$mirror}} -{{include file="field_checkbox.tpl" field=$import}} -{{include file="field_checkbox.tpl" field=$create_user}} -{{include file="field_checkbox.tpl" field=$auto_follow}} +

{{$help}}

+{{include file="field_input.tpl" field=$api_key}} +{{include file="field_input.tpl" field=$api_secret}} +{{include file="field_input.tpl" field=$access_token}} +{{include file="field_input.tpl" field=$access_secret}} \ No newline at end of file diff --git a/twitter/twitter.css b/twitter/twitter.css deleted file mode 100644 index 480ce28d0..000000000 --- a/twitter/twitter.css +++ /dev/null @@ -1,12 +0,0 @@ - - -#twitter-avatar { - float: left; - width: 48px; - height: 48px; - padding: 2px; -} -#twitter-info-block { - height: 52px; - vertical-align: middle; -} diff --git a/twitter/twitter.php b/twitter/twitter.php index c6475aba0..d0f9b5bfe 100644 --- a/twitter/twitter.php +++ b/twitter/twitter.php @@ -1,14 +1,14 @@ * Author: Michael Vogel * Maintainer: Hypolite Petovan - * Status: unsupported + * Maintainer: Michael Vogel * - * Copyright (c) 2011-2013 Tobias Diekershoff, Michael Vogel, Hypolite Petovan + * Copyright (c) 2011-2023 Tobias Diekershoff, Michael Vogel, Hypolite Petovan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,73 +34,24 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ -/* Twitter Addon for Friendica - * - * Author: Tobias Diekershoff - * tobias.diekershoff@gmx.net - * - * License:3-clause BSD license - * - * Configuration: - * To use this addon you need a OAuth Consumer key pair (key & secret) - * you can get it from Twitter at https://twitter.com/apps - * - * Register your Friendica site as "Client" application with "Read & Write" access - * we do not need "Twitter as login". When you've registered the app you get the - * OAuth Consumer key and secret pair for your application/site. - * - * Add this key pair to your config/twitter.config.php file or use the admin panel. - * - * return [ - * 'twitter' => [ - * 'consumerkey' => '', - * 'consumersecret' => '', - * ], - * ]; - * - * To activate the addon itself add it to the system.addon - * setting. After this, your user can configure their Twitter account settings - * from "Settings -> Addon Settings". - * - * Requirements: PHP5, curl - */ -use Abraham\TwitterOAuth\TwitterOAuth; -use Abraham\TwitterOAuth\TwitterOAuthException; -use Codebird\Codebird; -use Friendica\App; use Friendica\Content\Text\BBCode; use Friendica\Content\Text\Plaintext; use Friendica\Core\Hook; use Friendica\Core\Logger; -use Friendica\Core\Protocol; use Friendica\Core\Renderer; use Friendica\Core\Worker; -use Friendica\Database\DBA; use Friendica\DI; -use Friendica\Model\Contact; -use Friendica\Model\Conversation; -use Friendica\Model\Circle; use Friendica\Model\Item; -use Friendica\Model\ItemURI; use Friendica\Model\Post; -use Friendica\Model\Tag; -use Friendica\Model\User; -use Friendica\Protocol\Activity; use Friendica\Core\Config\Util\ConfigFileManager; -use Friendica\Core\System; use Friendica\Model\Photo; -use Friendica\Util\DateTimeFormat; -use Friendica\Util\Images; -use Friendica\Util\Strings; - -require_once __DIR__ . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php'; - -define('TWITTER_DEFAULT_POLL_INTERVAL', 5); // given in minutes +use GuzzleHttp\Client; +use GuzzleHttp\HandlerStack; +use GuzzleHttp\Subscriber\Oauth\Oauth1; function twitter_install() { - // we need some hooks, for the configuration and for sending tweets Hook::register('load_config' , __FILE__, 'twitter_load_config'); Hook::register('connector_settings' , __FILE__, 'twitter_settings'); Hook::register('connector_settings_post', __FILE__, 'twitter_settings_post'); @@ -108,104 +59,13 @@ function twitter_install() Hook::register('post_local' , __FILE__, 'twitter_post_local'); Hook::register('notifier_normal' , __FILE__, 'twitter_post_hook'); Hook::register('jot_networks' , __FILE__, 'twitter_jot_nets'); - Hook::register('cron' , __FILE__, 'twitter_cron'); - Hook::register('support_follow' , __FILE__, 'twitter_support_follow'); - Hook::register('follow' , __FILE__, 'twitter_follow'); - Hook::register('unfollow' , __FILE__, 'twitter_unfollow'); - Hook::register('block' , __FILE__, 'twitter_block'); - Hook::register('unblock' , __FILE__, 'twitter_unblock'); - Hook::register('expire' , __FILE__, 'twitter_expire'); - Hook::register('prepare_body' , __FILE__, 'twitter_prepare_body'); - Hook::register('check_item_notification', __FILE__, 'twitter_check_item_notification'); - Hook::register('probe_detect' , __FILE__, 'twitter_probe_detect'); - Hook::register('item_by_link' , __FILE__, 'twitter_item_by_link'); - Hook::register('parse_link' , __FILE__, 'twitter_parse_link'); - Logger::info('installed twitter'); } -// Hook functions - function twitter_load_config(ConfigFileManager $loader) { DI::app()->getConfigCache()->load($loader->loadAddonConfig('twitter'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); } -function twitter_check_item_notification(array &$notification_data) -{ - $own_id = DI::pConfig()->get($notification_data['uid'], 'twitter', 'own_id'); - - $own_user = Contact::selectFirst(['url'], ['uid' => $notification_data['uid'], 'alias' => 'twitter::'.$own_id]); - if ($own_user) { - $notification_data['profiles'][] = $own_user['url']; - } -} - -function twitter_support_follow(array &$data) -{ - if ($data['protocol'] == Protocol::TWITTER) { - $data['result'] = true; - } -} - -function twitter_follow(array &$contact) -{ - Logger::info('Check if contact is twitter contact', ['url' => $contact['url']]); - - if (!strstr($contact['url'], '://twitter.com') && !strstr($contact['url'], '@twitter.com')) { - return; - } - - // contact seems to be a twitter contact, so continue - $nickname = preg_replace("=https?://twitter.com/(.*)=ism", "$1", $contact['url']); - $nickname = str_replace('@twitter.com', '', $nickname); - - $uid = DI::userSession()->getLocalUserId(); - - if (!twitter_api_contact('friendships/create', ['network' => Protocol::TWITTER, 'nick' => $nickname], $uid)) { - $contact = null; - return; - } - - $user = twitter_fetchuser($nickname); - - $contact_id = twitter_fetch_contact($uid, $user, true); - - $contact = Contact::getById($contact_id, ['name', 'nick', 'url', 'addr', 'batch', 'notify', 'poll', 'request', 'confirm', 'poco', 'photo', 'priority', 'network', 'alias', 'pubkey']); - - if (DBA::isResult($contact)) { - $contact['contact'] = $contact; - } -} - -function twitter_unfollow(array &$hook_data) -{ - $hook_data['result'] = twitter_api_contact('friendships/destroy', $hook_data['contact'], $hook_data['uid']); -} - -function twitter_block(array &$hook_data) -{ - $hook_data['result'] = twitter_api_contact('blocks/create', $hook_data['contact'], $hook_data['uid']); - - if ($hook_data['result'] === true) { - $cdata = Contact::getPublicAndUserContactID($hook_data['contact']['id'], $hook_data['uid']); - Contact::remove($cdata['user']); - } -} - -function twitter_unblock(array &$hook_data) -{ - $hook_data['result'] = twitter_api_contact('blocks/destroy', $hook_data['contact'], $hook_data['uid']); -} - -function twitter_api_contact(string $apiPath, array $contact, int $uid): ?bool -{ - if ($contact['network'] !== Protocol::TWITTER) { - return null; - } - - return (bool)twitter_api_call($uid, $apiPath, ['screen_name' => $contact['nick']]); -} - function twitter_jot_nets(array &$jotnets_fields) { if (!DI::userSession()->getLocalUserId()) { @@ -224,76 +84,18 @@ function twitter_jot_nets(array &$jotnets_fields) } } - function twitter_settings_post() { - if (!DI::userSession()->getLocalUserId()) { - return; - } - // don't check twitter settings if twitter submit button is not clicked - if (empty($_POST['twitter-disconnect']) && empty($_POST['twitter-submit'])) { + if (!DI::userSession()->getLocalUserId() || empty($_POST['twitter-submit'])) { return; } - if (!empty($_POST['twitter-disconnect'])) { - /* * * - * if the twitter-disconnect checkbox is set, clear the OAuth key/secret pair - * from the user configuration - */ - DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'twitter', 'consumerkey'); - DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'twitter', 'consumersecret'); - DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'twitter', 'oauthtoken'); - DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'twitter', 'oauthsecret'); - DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'twitter', 'post'); - DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'twitter', 'post_by_default'); - DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'twitter', 'lastid'); - DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'twitter', 'thread'); - DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'twitter', 'mirror_posts'); - DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'twitter', 'import'); - DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'twitter', 'create_user'); - DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'twitter', 'auto_follow'); - DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'twitter', 'own_id'); - } else { - if (isset($_POST['twitter-pin'])) { - // if the user supplied us with a PIN from Twitter, let the magic of OAuth happen - Logger::notice('got a Twitter PIN'); - $ckey = DI::config()->get('twitter', 'consumerkey'); - $csecret = DI::config()->get('twitter', 'consumersecret'); - // the token and secret for which the PIN was generated were hidden in the settings - // form as token and token2, we need a new connection to Twitter using these token - // and secret to request a Access Token with the PIN - try { - if (empty($_POST['twitter-pin'])) { - throw new Exception(DI::l10n()->t('You submitted an empty PIN, please Sign In with Twitter again to get a new one.')); - } - - $connection = new TwitterOAuth($ckey, $csecret, $_POST['twitter-token'], $_POST['twitter-token2']); - $token = $connection->oauth('oauth/access_token', ['oauth_verifier' => $_POST['twitter-pin']]); - // ok, now that we have the Access Token, save them in the user config - DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'twitter', 'oauthtoken', $token['oauth_token']); - DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'twitter', 'oauthsecret', $token['oauth_token_secret']); - DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'twitter', 'post', 1); - } catch(Exception $e) { - DI::sysmsg()->addNotice($e->getMessage()); - } catch(TwitterOAuthException $e) { - DI::sysmsg()->addNotice($e->getMessage()); - } - } else { - // if no PIN is supplied in the POST variables, the user has changed the setting - // to post a tweet for every new __public__ posting to the wall - DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'twitter', 'post', intval($_POST['twitter-enable'])); - DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'twitter', 'post_by_default', intval($_POST['twitter-default'])); - DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'twitter', 'thread', intval($_POST['twitter-thread'])); - DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'twitter', 'mirror_posts', intval($_POST['twitter-mirror'])); - DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'twitter', 'import', intval($_POST['twitter-import'])); - DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'twitter', 'create_user', intval($_POST['twitter-create_user'])); - DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'twitter', 'auto_follow', intval($_POST['twitter-auto_follow'])); - - if (!intval($_POST['twitter-mirror'])) { - DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'twitter', 'lastid'); - } - } - } + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'twitter', 'post', (bool)$_POST['twitter-enable']); + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'twitter', 'post_by_default', (bool)$_POST['twitter-default']); + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'twitter', 'api_key', $_POST['twitter-api-key']); + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'twitter', 'api_secret', $_POST['twitter-api-secret']); + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'twitter', 'access_token', $_POST['twitter-access-token']); + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'twitter', 'access_secret', $_POST['twitter-access-secret']); } function twitter_settings(array &$data) @@ -302,116 +104,31 @@ function twitter_settings(array &$data) return; } - $user = User::getById(DI::userSession()->getLocalUserId()); + $enabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'twitter', 'post') ?? false; + $def_enabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'twitter', 'post_by_default') ?? false; - DI::page()->registerStylesheet(__DIR__ . '/twitter.css', 'all'); + $api_key = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'twitter', 'api_key'); + $api_secret = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'twitter', 'api_secret'); + $access_token = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'twitter', 'access_token'); + $access_secret = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'twitter', 'access_secret'); - /* * * - * 1) Check that we have global consumer key & secret - * 2) If no OAuthtoken & stuff is present, generate button to get some - * 3) Checkbox for "Send public notices (280 chars only) - */ - $ckey = DI::config()->get('twitter', 'consumerkey'); - $csecret = DI::config()->get('twitter', 'consumersecret'); - $otoken = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'twitter', 'oauthtoken'); - $osecret = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'twitter', 'oauthsecret'); - - $enabled = intval(DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'twitter', 'post')); - $defenabled = intval(DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'twitter', 'post_by_default')); - $threadenabled = intval(DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'twitter', 'thread')); - $mirrorenabled = intval(DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'twitter', 'mirror_posts')); - $importenabled = intval(DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'twitter', 'import')); - $create_userenabled = intval(DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'twitter', 'create_user')); - $auto_followenabled = intval(DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'twitter', 'auto_follow')); - - // Hide the submit button by default - $submit = ''; - - if ((!$ckey) && (!$csecret)) { - /* no global consumer keys - * display warning and skip personal config - */ - $html = '

' . DI::l10n()->t('No consumer key pair for Twitter found. Please contact your site administrator.') . '

'; - } else { - // ok we have a consumer key pair now look into the OAuth stuff - if ((!$otoken) && (!$osecret)) { - /* the user has not yet connected the account to twitter... - * get a temporary OAuth key/secret pair and display a button with - * which the user can request a PIN to connect the account to a - * account at Twitter. - */ - $connection = new TwitterOAuth($ckey, $csecret); - try { - $result = $connection->oauth('oauth/request_token', ['oauth_callback' => 'oob']); - - $html = '

' . DI::l10n()->t('At this Friendica instance the Twitter addon was enabled but you have not yet connected your account to your Twitter account. To do so click the button below to get a PIN from Twitter which you have to copy into the input box below and submit the form. Only your public posts will be posted to Twitter.') . '

'; - $html .= '' . DI::l10n()->t('Log in with Twitter') . ''; - $html .= '
'; - $html .= ''; - $html .= ''; - $html .= ''; - $html .= ''; - $html .= '
'; - - $submit = null; - } catch (TwitterOAuthException $e) { - $html = '

' . DI::l10n()->t('An error occured: ') . $e->getMessage() . '

'; - } - } else { - /* * * - * we have an OAuth key / secret pair for the user - * so let's give a chance to disable the postings to Twitter - */ - $connection = new TwitterOAuth($ckey, $csecret, $otoken, $osecret); - try { - $account = $connection->get('account/verify_credentials'); - if (property_exists($account, 'screen_name') && - property_exists($account, 'description') && - property_exists($account, 'profile_image_url') - ) { - $connected = DI::l10n()->t('Currently connected to: %1$s', $account->screen_name); - } else { - Logger::notice('Invalid twitter info (verify credentials).', ['auth' => TwitterOAuth::class]); - } - - if ($user['hidewall']) { - $privacy_warning = DI::l10n()->t('Note: Due to your privacy settings (Hide your profile details from unknown viewers?) the link potentially included in public postings relayed to Twitter will lead the visitor to a blank page informing the visitor that the access to your profile has been restricted.'); - } - - $t = Renderer::getMarkupTemplate('connector_settings.tpl', 'addon/twitter/'); - $html = Renderer::replaceMacros($t, [ - '$l10n' => [ - 'connected' => $connected ?? '', - 'invalid' => DI::l10n()->t('Invalid Twitter info'), - 'disconnect' => DI::l10n()->t('Disconnect'), - 'privacy_warning' => $privacy_warning ?? '', - ], - - '$account' => $account, - '$enable' => ['twitter-enable', DI::l10n()->t('Allow posting to Twitter'), $enabled, DI::l10n()->t('If enabled all your public postings can be posted to the associated Twitter account. You can choose to do so by default (here) or for every posting separately in the posting options when writing the entry.')], - '$default' => ['twitter-default', DI::l10n()->t('Send public postings to Twitter by default'), $defenabled], - '$thread' => ['twitter-thread', DI::l10n()->t('Use threads instead of truncating the content'), $threadenabled], - '$mirror' => ['twitter-mirror', DI::l10n()->t('Mirror all posts from twitter that are no replies'), $mirrorenabled], - '$import' => ['twitter-import', DI::l10n()->t('Import the remote timeline'), $importenabled], - '$create_user' => ['twitter-create_user', DI::l10n()->t('Automatically create contacts'), $create_userenabled, DI::l10n()->t('This will automatically create a contact in Friendica as soon as you receive a message from an existing contact via the Twitter network. If you do not enable this, you need to manually add those Twitter contacts in Friendica from whom you would like to see posts here.')], - '$auto_follow' => ['twitter-auto_follow', DI::l10n()->t('Follow in fediverse'), $auto_followenabled, DI::l10n()->t('Automatically subscribe to the contact in the fediverse, when a fediverse account is mentioned in name or description and we are following the Twitter contact.')], - ]); - - // Enable the default submit button - $submit = null; - } catch (TwitterOAuthException $e) { - $html = '

' . DI::l10n()->t('An error occured: ') . $e->getMessage() . '

'; - } - } - } + $t = Renderer::getMarkupTemplate('connector_settings.tpl', 'addon/twitter/'); + $html = Renderer::replaceMacros($t, [ + '$enable' => ['twitter-enable', DI::l10n()->t('Allow posting to Twitter'), $enabled, DI::l10n()->t('If enabled all your public postings can be posted to the associated Twitter account. You can choose to do so by default (here) or for every posting separately in the posting options when writing the entry.')], + '$default' => ['twitter-default', DI::l10n()->t('Send public postings to Twitter by default'), $def_enabled], + '$api_key' => ['twitter-api-key', DI::l10n()->t('API Key'), $api_key], + '$api_secret' => ['twitter-api-secret', DI::l10n()->t('API Secret'), $api_secret], + '$access_token' => ['twitter-access-token', DI::l10n()->t('Access Token'), $access_token], + '$access_secret' => ['twitter-access-secret', DI::l10n()->t('Access Secret'), $access_secret], + '$help' => DI::l10n()->t('Each user needs to register their own app to be able to post to Twitter. Please visit https://developer.twitter.com/en/portal/projects-and-apps to register a project. Inside the project you then have to register an app. You will find the needed data for the connector on the page "Keys and token" in the app settings.'), + ]); $data = [ 'connector' => 'twitter', - 'title' => DI::l10n()->t('Twitter Import/Export/Mirror'), + 'title' => DI::l10n()->t('Twitter Export'), 'enabled' => $enabled, 'image' => 'images/twitter.png', 'html' => $html, - 'submit' => $submit ?? null, ]; } @@ -425,64 +142,29 @@ function twitter_hook_fork(array &$b) $post = $b['data']; - // Deletion checks are done in twitter_delete_item() - if ($post['deleted']) { - return; - } - - // Editing is not supported by the addon - if ($post['created'] !== $post['edited']) { - DI::logger()->info('Editing is not supported by the addon'); + if ($post['deleted'] || $post['private'] || ($post['created'] !== $post['edited']) || + !strstr($post['postopts'], 'twitter') || ($post['gravity'] != Item::GRAVITY_PARENT)) { $b['execute'] = false; return; } - - // if post comes from twitter don't send it back - if (($post['extid'] == Protocol::TWITTER) || twitter_get_id($post['extid'])) { - DI::logger()->info('If post comes from twitter don\'t send it back'); - $b['execute'] = false; - return; - } - - if (substr($post['app'] ?? '', 0, 7) == 'Twitter') { - DI::logger()->info('No Twitter app'); - $b['execute'] = false; - return; - } - - if (DI::pConfig()->get($post['uid'], 'twitter', 'import')) { - // Don't fork if it isn't a reply to a twitter post - if (($post['parent'] != $post['id']) && !Post::exists(['id' => $post['parent'], 'network' => Protocol::TWITTER])) { - Logger::notice('No twitter parent found', ['item' => $post['id']]); - $b['execute'] = false; - return; - } - } else { - // Comments are never exported when we don't import the twitter timeline - if (!strstr($post['postopts'] ?? '', 'twitter') || ($post['parent'] != $post['id']) || $post['private']) { - DI::logger()->info('Comments are never exported when we don\'t import the twitter timeline'); - $b['execute'] = false; - return; - } - } } function twitter_post_local(array &$b) { - if ($b['edit']) { - return; - } - if (!DI::userSession()->getLocalUserId() || (DI::userSession()->getLocalUserId() != $b['uid'])) { return; } - $twitter_post = intval(DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'twitter', 'post')); - $twitter_enable = (($twitter_post && !empty($_REQUEST['twitter_enable'])) ? intval($_REQUEST['twitter_enable']) : 0); + if ($b['edit'] || $b['private'] || $b['parent']) { + return; + } + + $twitter_post = (bool)DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'twitter', 'post'); + $twitter_enable = (($twitter_post && !empty($_REQUEST['twitter_enable'])) ? (bool)$_REQUEST['twitter_enable'] : false); // if API is used, default to the chosen settings if ($b['api_source'] && intval(DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'twitter', 'post_by_default'))) { - $twitter_enable = 1; + $twitter_enable = true; } if (!$twitter_enable) { @@ -496,398 +178,86 @@ function twitter_post_local(array &$b) $b['postopts'] .= 'twitter'; } -function twitter_probe_detect(array &$hookData) -{ - // Don't overwrite an existing result - if (isset($hookData['result'])) { - return; - } - - // Avoid a lookup for the wrong network - if (!in_array($hookData['network'], ['', Protocol::TWITTER])) { - return; - } - - if (preg_match('=([^@]+)@(?:mobile\.)?twitter\.com$=i', $hookData['uri'], $matches)) { - $nick = $matches[1]; - } elseif (preg_match('=^https?://(?:mobile\.)?twitter\.com/(.+)=i', $hookData['uri'], $matches)) { - if (strpos($matches[1], '/') !== false) { - // Status case: https://twitter.com//status/ - // Not a contact - $hookData['result'] = false; - return; - } - - $nick = $matches[1]; - } else { - return; - } - - $user = twitter_fetchuser($nick); - - if ($user) { - $hookData['result'] = twitter_user_to_contact($user) ?: null; - } - - // Authoritative probe should set the result even if the probe was unsuccessful - if ($hookData['network'] == Protocol::TWITTER && empty($hookData['result'])) { - $hookData['result'] = []; - } -} - -function twitter_item_by_link(array &$hookData) -{ - // Don't overwrite an existing result - if (isset($hookData['item_id'])) { - return; - } - - // Relevancy check - if (!preg_match('#^https?://(?:mobile\.|www\.)?twitter.com/[^/]+/status/(\d+).*#', $hookData['uri'], $matches)) { - return; - } - - // From now on, any early return should abort the whole chain since we've established it was a Twitter URL - $hookData['item_id'] = false; - - // Node-level configuration check - if (empty(DI::config()->get('twitter', 'consumerkey')) || empty(DI::config()->get('twitter', 'consumersecret'))) { - return; - } - - // No anonymous import - if (!$hookData['uid']) { - return; - } - - if ( - empty(DI::pConfig()->get($hookData['uid'], 'twitter', 'oauthtoken')) - || empty(DI::pConfig()->get($hookData['uid'], 'twitter', 'oauthsecret')) - ) { - DI::sysmsg()->addNotice(DI::l10n()->t('Please connect a Twitter account in your Social Network settings to import Twitter posts.')); - return; - } - - $status = twitter_statuses_show($matches[1]); - - if (empty($status->id_str)) { - DI::sysmsg()->addNotice(DI::l10n()->t('Twitter post not found.')); - return; - } - - $item = twitter_createpost($hookData['uid'], $status, [], true, false, false); - if (!empty($item)) { - $hookData['item_id'] = Item::insert($item); - } -} - -function twitter_api_post(string $apiPath, string $pid, int $uid): ?object -{ - if (empty($pid)) { - return null; - } - - return twitter_api_call($uid, $apiPath, ['id' => $pid]); -} - -function twitter_api_call(int $uid, string $apiPath, array $parameters = []): ?object -{ - $ckey = DI::config()->get('twitter', 'consumerkey'); - $csecret = DI::config()->get('twitter', 'consumersecret'); - $otoken = DI::pConfig()->get($uid, 'twitter', 'oauthtoken'); - $osecret = DI::pConfig()->get($uid, 'twitter', 'oauthsecret'); - - // If the addon is not configured (general or for this user) quit here - if (empty($ckey) || empty($csecret) || empty($otoken) || empty($osecret)) { - return null; - } - - try { - $connection = new TwitterOAuth($ckey, $csecret, $otoken, $osecret); - $result = $connection->post($apiPath, $parameters); - - if ($connection->getLastHttpCode() != 200) { - throw new Exception($result->errors[0]->message ?? json_encode($result), $connection->getLastHttpCode()); - } - - if (!empty($result->errors)) { - throw new Exception($result->errors[0]->message, $result->errors[0]->code); - } - - Logger::info('[twitter] API call successful', ['apiPath' => $apiPath, 'parameters' => $parameters]); - Logger::debug('[twitter] API call result', ['apiPath' => $apiPath, 'parameters' => $parameters, 'result' => $result]); - - return $result; - } catch (TwitterOAuthException $twitterOAuthException) { - Logger::notice('Unable to communicate with twitter', ['apiPath' => $apiPath, 'parameters' => $parameters, 'code' => $twitterOAuthException->getCode(), 'exception' => $twitterOAuthException]); - return null; - } catch (Exception $e) { - Logger::notice('[twitter] API call failed', ['apiPath' => $apiPath, 'parameters' => $parameters, 'code' => $e->getCode(), 'message' => $e->getMessage()]); - return null; - } -} - -function twitter_get_id(string $uri) -{ - if ((substr($uri, 0, 9) != 'twitter::') || (strlen($uri) <= 9)) { - return 0; - } - - $id = substr($uri, 9); - if (!is_numeric($id)) { - return 0; - } - - return (int)$id; -} - function twitter_post_hook(array &$b) { DI::logger()->debug('Invoke post hook', $b); - if ($b['deleted']) { - twitter_delete_item($b); - return; - } - - // Post to Twitter - if (!DI::pConfig()->get($b['uid'], 'twitter', 'import') - && ($b['private'] || ($b['created'] !== $b['edited']))) { + if (($b['gravity'] != Item::GRAVITY_PARENT) || !strstr($b['postopts'], 'twitter') || $b['private'] || $b['deleted'] || ($b['created'] !== $b['edited'])) { return; } $b['body'] = Post\Media::addAttachmentsToBody($b['uri-id'], DI::contentItem()->addSharedPost($b)); - $thr_parent = null; - - if ($b['parent'] != $b['id']) { - Logger::debug('Got comment', ['item' => $b]); - - // Looking if its a reply to a twitter post - if (!twitter_get_id($b['parent-uri']) && - !twitter_get_id($b['extid']) && - !twitter_get_id($b['thr-parent'])) { - Logger::info('No twitter post', ['parent' => $b['parent']]); - return; - } - - $condition = ['uri' => $b['thr-parent'], 'uid' => $b['uid']]; - $thr_parent = Post::selectFirst(['uri', 'extid', 'author-link', 'author-nick', 'author-network'], $condition); - if (!DBA::isResult($thr_parent)) { - Logger::notice('No parent found', ['thr-parent' => $b['thr-parent']]); - return; - } - - if ($thr_parent['author-network'] == Protocol::TWITTER) { - $nickname = '@[url=' . $thr_parent['author-link'] . ']' . $thr_parent['author-nick'] . '[/url]'; - $nicknameplain = '@' . $thr_parent['author-nick']; - - Logger::info('Comparing', ['nickname' => $nickname, 'nicknameplain' => $nicknameplain, 'body' => $b['body']]); - if ((strpos($b['body'], $nickname) === false) && (strpos($b['body'], $nicknameplain) === false)) { - $b['body'] = $nickname . ' ' . $b['body']; - } - } - - Logger::debug('Parent found', ['parent' => $thr_parent]); - } else { - if ($b['private'] || !strstr($b['postopts'], 'twitter')) { - return; - } - - // Dont't post if the post doesn't belong to us. - // This is a check for group postings - $self = DBA::selectFirst('contact', ['id'], ['uid' => $b['uid'], 'self' => true]); - if ($b['contact-id'] != $self['id']) { - return; - } - } - - if ($b['verb'] == Activity::LIKE) { - Logger::info('Like', ['uid' => $b['uid'], 'id' => twitter_get_id($b['thr-parent'])]); - - twitter_api_post('favorites/create', twitter_get_id($b['thr-parent']), $b['uid']); - - return; - } - - if ($b['verb'] == Activity::ANNOUNCE) { - Logger::info('Retweet', ['uid' => $b['uid'], 'id' => twitter_get_id($b['thr-parent'])]); - twitter_retweet($b['uid'], twitter_get_id($b['thr-parent'])); - return; - } - - if ($b['created'] !== $b['edited']) { - return; - } - - // if post comes from twitter don't send it back - if (($b['extid'] == Protocol::TWITTER) || twitter_get_id($b['extid'])) { - return; - } - - if ($b['app'] == 'Twitter') { - return; - } - Logger::notice('twitter post invoked', ['id' => $b['id'], 'guid' => $b['guid']]); DI::pConfig()->load($b['uid'], 'twitter'); - $ckey = DI::config()->get('twitter', 'consumerkey'); - $csecret = DI::config()->get('twitter', 'consumersecret'); - $otoken = DI::pConfig()->get($b['uid'], 'twitter', 'oauthtoken'); - $osecret = DI::pConfig()->get($b['uid'], 'twitter', 'oauthsecret'); + $api_key = DI::pConfig()->get($b['uid'], 'twitter', 'api_key'); + $api_secret = DI::pConfig()->get($b['uid'], 'twitter', 'api_secret'); + $access_token = DI::pConfig()->get($b['uid'], 'twitter', 'access_token'); + $access_secret = DI::pConfig()->get($b['uid'], 'twitter', 'access_secret'); - if ($ckey && $csecret && $otoken && $osecret) { - Logger::info('We have customer key and oauth stuff, going to send.'); + if (empty($api_key) || empty($api_secret) || empty($access_token) || empty($access_secret)) { + Logger::info('Missing keys, secrets or tokens.'); + return; + } - // If it's a repeated message from twitter then do a native retweet and exit - if (twitter_is_retweet($b['uid'], $b['body'])) { - return; - } + $msgarr = Plaintext::getPost($b, 280, true, BBCode::TWITTER); + Logger::debug('Got plaintext', ['id' => $b['id'], 'message' => $msgarr]); - Codebird::setConsumerKey($ckey, $csecret); - $cb = Codebird::getInstance(); - $cb->setToken($otoken, $osecret); + $media_ids = []; - $connection = new TwitterOAuth($ckey, $csecret, $otoken, $osecret); + if (!empty($msgarr['images']) || !empty($msgarr['remote_images'])) { + Logger::info('Got images', ['id' => $b['id'], 'images' => $msgarr['images'] ?? []]); - // Set the timeout for upload to 30 seconds - $connection->setTimeouts(10, 30); - - $max_char = 280; - - // Handling non-native reshares - $b['body'] = Friendica\Content\Text\BBCode::convertShare( - $b['body'], - function (array $attributes, array $author_contact, $content, $is_quote_share) { - return twitter_convert_share($attributes, $author_contact, $content, $is_quote_share); + foreach ($msgarr['images'] ?? [] as $image) { + if (count($media_ids) == 4) { + continue; } - ); - - $b['body'] = twitter_update_mentions($b['body']); - - $msgarr = Plaintext::getPost($b, $max_char, true, BBCode::TWITTER); - Logger::info('Got plaintext', ['id' => $b['id'], 'message' => $msgarr]); - $msg = $msgarr['text']; - - if (($msg == '') && isset($msgarr['title'])) { - $msg = Plaintext::shorten($msgarr['title'], $max_char - 50, $b['uid']); - } - - // Add the link to the body if the type isn't a photo or there are more than 4 images in the post - if (!empty($msgarr['url']) && (strpos($msg, $msgarr['url']) === false) && (($msgarr['type'] != 'photo') || empty($msgarr['images']) || (count($msgarr['images']) > 4))) { - $msg .= "\n" . $msgarr['url']; - } - - if (empty($msg)) { - Logger::notice('Empty message', ['id' => $b['id']]); - return; - } - - // and now tweet it :-) - $post = []; - - if (!empty($msgarr['images']) || !empty($msgarr['remote_images'])) { - Logger::info('Got images', ['id' => $b['id'], 'images' => $msgarr['images'] ?? [], 'remote_images' => $msgarr['remote_images'] ?? []]); try { - $media_ids = []; - foreach ($msgarr['images'] ?? [] as $image) { - if (count($media_ids) == 4) { - continue; - } - try { - $media_ids[] = twitter_upload_image($connection, $cb, $image, $b); - } catch (\Throwable $th) { - Logger::warning('Error while uploading image', ['code' => $th->getCode(), 'message' => $th->getMessage()]); - } - } + $media_ids[] = twitter_upload_image($b['uid'], $image, $b); + } catch (\Throwable $th) { + Logger::warning('Error while uploading image', ['image' => $image, 'code' => $th->getCode(), 'message' => $th->getMessage()]); + Worker::defer(); + break; + } + } + } - foreach ($msgarr['remote_images'] ?? [] as $image) { - if (count($media_ids) == 4) { - continue; - } - try { - $media_ids[] = twitter_upload_image($connection, $cb, $image, $b); - } catch (\Throwable $th) { - Logger::warning('Error while uploading image', ['code' => $th->getCode(), 'message' => $th->getMessage()]); - } - } - $post['media_ids'] = implode(',', $media_ids); - if (empty($post['media_ids'])) { - unset($post['media_ids']); - } - } catch (Exception $e) { - Logger::warning('Exception when trying to send to Twitter', ['id' => $b['id'], 'message' => $e->getMessage()]); - } + $in_reply_to_tweet_id = 0; + + Logger::debug('Post message', ['id' => $b['id'], 'parts' => count($msgarr['parts'])]); + foreach ($msgarr['parts'] as $key => $part) { + try { + $id = twitter_post_status($b['uid'], $part, $media_ids, $in_reply_to_tweet_id); + Logger::info('twitter_post send', ['part' => $key, 'id' => $b['id'], 'result' => $id]); + } catch (\Throwable $th) { + Logger::warning('Error while posting message', ['part' => $key, 'id' => $b['id'], 'code' => $th->getCode(), 'message' => $th->getMessage()]); + Worker::defer(); + break; } - if (!DI::pConfig()->get($b['uid'], 'twitter', 'thread') || empty($msgarr['parts']) || (count($msgarr['parts']) == 1)) { - Logger::debug('Post single message', ['id' => $b['id']]); - - $post['status'] = $msg; - - if ($thr_parent) { - $post['in_reply_to_status_id'] = twitter_get_id($thr_parent['uri']); - } - - $result = $connection->post('statuses/update', $post); - Logger::info('twitter_post send', ['id' => $b['id'], 'result' => $result]); - - if (!empty($result->source)) { - DI::keyValue()->set('twitter_application_name', strip_tags($result->source)); - } - - if (!empty($result->errors)) { - Logger::error('Send to Twitter failed', ['id' => $b['id'], 'error' => $result->errors]); - Worker::defer(); - } elseif ($thr_parent) { - Logger::notice('Post send, updating extid', ['id' => $b['id'], 'extid' => $result->id_str]); - Item::update(['extid' => 'twitter::' . $result->id_str], ['id' => $b['id']]); - } - } else { - if ($thr_parent) { - $in_reply_to_status_id = twitter_get_id($thr_parent['uri']); - } else { - $in_reply_to_status_id = 0; - } - - Logger::debug('Post message thread', ['id' => $b['id'], 'parts' => count($msgarr['parts'])]); - foreach ($msgarr['parts'] as $key => $part) { - $post['status'] = $part; - - if ($in_reply_to_status_id) { - $post['in_reply_to_status_id'] = $in_reply_to_status_id; - } - - $result = $connection->post('statuses/update', $post); - Logger::debug('twitter_post send', ['part' => $key, 'id' => $b['id'], 'result' => $result]); - - if (!empty($result->errors)) { - Logger::warning('Send to Twitter failed', ['part' => $key, 'id' => $b['id'], 'error' => $result->errors]); - Worker::defer(); - break; - } elseif ($key == 0) { - Logger::debug('Updating extid', ['part' => $key, 'id' => $b['id'], 'extid' => $result->id_str]); - Item::update(['extid' => 'twitter::' . $result->id_str], ['id' => $b['id']]); - } - - if (!empty($result->source)) { - $application_name = strip_tags($result->source); - } - - $in_reply_to_status_id = $result->id_str; - unset($post['media_ids']); - } - - if (!empty($application_name)) { - DI::keyValue()->set('twitter_application_name', strip_tags($application_name)); - } - } + $in_reply_to_tweet_id = $id; + $media_ids = []; } } -function twitter_upload_image($connection, $cb, array $image, array $item) +function twitter_post_status(int $uid, string $status, array $media_ids = [], string $in_reply_to_tweet_id = ''): string +{ + $parameters = ['text' => $status]; + if (!empty($media_ids)) { + $parameters['media'] = ['media_ids' => $media_ids]; + } + if (!empty($in_reply_to_tweet_id)) { + $parameters['reply'] = ['in_reply_to_tweet_id' => $in_reply_to_tweet_id]; + } + + $response = twitter_post($uid, 'https://api.twitter.com/2/tweets', 'json', $parameters); + + return $response->data->id; +} + +function twitter_upload_image(int $uid, array $image) { if (!empty($image['id'])) { $photo = Photo::selectFirst([], ['id' => $image['id']]); @@ -895,1606 +265,55 @@ function twitter_upload_image($connection, $cb, array $image, array $item) $photo = Photo::createPhotoForExternalResource($image['url']); } - $tempfile = tempnam(System::getTempPath(), 'cache'); - file_put_contents($tempfile, Photo::getImageForPhoto($photo)); + $parameters = [ + 'name' => 'media_data', + 'contents' => base64_encode(Photo::getImageForPhoto($photo)) + ]; - Logger::info('Uploading', ['id' => $item['id'], 'image' => $image]); - $media = $connection->upload('media/upload', ['media' => $tempfile]); - - unlink($tempfile); + Logger::info('Uploading', ['uid' => $uid, 'image' => $image]); + $media = twitter_post($uid, 'https://upload.twitter.com/1.1/media/upload.json', 'multipart', [$parameters]); if (isset($media->media_id_string)) { $media_id = $media->media_id_string; if (!empty($image['description'])) { - $data = ['media_id' => $media->media_id_string, - 'alt_text' => ['text' => substr($image['description'], 0, 420)]]; - $ret = $cb->media_metadata_create($data); - Logger::info('Metadata create', ['id' => $item['id'], 'data' => $data, 'return' => $ret]); + $data = [ + 'media_id' => $media->media_id_string, + 'alt_text' => [ + 'text' => substr($image['description'], 0, 1000) + ] + ]; + $ret = twitter_post($uid, 'https://upload.twitter.com/1.1/media/metadata/create.json', 'json', $data); + Logger::info('Metadata create', ['uid' => $uid, 'data' => $data, 'return' => $ret]); } } else { - Logger::error('Failed upload', ['id' => $item['id'], 'image' => $image['url'], 'return' => $media]); + Logger::error('Failed upload', ['uid' => $uid, 'image' => $image['url'], 'return' => $media]); throw new Exception('Failed upload of ' . $image['url']); } return $media_id; } -function twitter_delete_item(array $item) +function twitter_post(int $uid, string $url, string $type, array $data): stdClass { - if (!$item['deleted']) { - return; - } - - if ($item['parent'] != $item['id']) { - Logger::debug('Deleting comment/announce', ['item' => $item]); - - // Looking if it's a reply to a twitter post - if (!twitter_get_id($item['parent-uri']) && - !twitter_get_id($item['extid']) && - !twitter_get_id($item['thr-parent'])) { - Logger::info('No twitter post', ['parent' => $item['parent']]); - return; - } - - $condition = ['uri' => $item['thr-parent'], 'uid' => $item['uid']]; - $thr_parent = Post::selectFirst(['uri', 'extid', 'author-link', 'author-nick', 'author-network'], $condition); - if (!DBA::isResult($thr_parent)) { - Logger::notice('No parent found', ['thr-parent' => $item['thr-parent']]); - return; - } - - Logger::debug('Parent found', ['parent' => $thr_parent]); - } else { - if (!strstr($item['extid'], 'twitter')) { - DI::logger()->info('Not a Twitter post', ['extid' => $item['extid']]); - return; - } - - // Don't delete if the post doesn't belong to us. - // This is a check for group postings - $self = DBA::selectFirst('contact', ['id'], ['uid' => $item['uid'], 'self' => true]); - if ($item['contact-id'] != $self['id']) { - DI::logger()->info('Don\'t delete if the post doesn\'t belong to the user', ['contact-id' => $item['contact-id'], 'self' => $self['id']]); - return; - } - } - - /** - * @TODO Remaining caveat: Comments posted on Twitter and imported in Friendica do not trigger any Notifier task, - * possibly because they are private to the user and don't require any remote deletion notifications sent. - * Comments posted on Friendica and mirrored on Twitter trigger the Notifier task and the Twitter counter-part - * will be deleted accordingly. - */ - if ($item['verb'] == Activity::POST) { - Logger::info('Delete post/comment', ['uid' => $item['uid'], 'id' => twitter_get_id($item['extid'])]); - twitter_api_post('statuses/destroy', twitter_get_id($item['extid']), $item['uid']); - return; - } - - if ($item['verb'] == Activity::LIKE) { - Logger::info('Unlike', ['uid' => $item['uid'], 'id' => twitter_get_id($item['thr-parent'])]); - twitter_api_post('favorites/destroy', twitter_get_id($item['thr-parent']), $item['uid']); - return; - } - - if ($item['verb'] == Activity::ANNOUNCE && !empty($thr_parent['uri'])) { - Logger::info('Unretweet', ['uid' => $item['uid'], 'extid' => $thr_parent['uri'], 'id' => twitter_get_id($thr_parent['uri'])]); - twitter_api_post('statuses/unretweet', twitter_get_id($thr_parent['uri']), $item['uid']); - return; - } -} - -function twitter_addon_admin_post() -{ - DI::config()->set('twitter', 'consumerkey', trim($_POST['consumerkey'] ?? '')); - DI::config()->set('twitter', 'consumersecret', trim($_POST['consumersecret'] ?? '')); -} - -function twitter_addon_admin(string &$o) -{ - $t = Renderer::getMarkupTemplate('admin.tpl', 'addon/twitter/'); - - $o = Renderer::replaceMacros($t, [ - '$submit' => DI::l10n()->t('Save Settings'), - // name, label, value, help, [extra values] - '$consumerkey' => ['consumerkey', DI::l10n()->t('Consumer key'), DI::config()->get('twitter', 'consumerkey'), ''], - '$consumersecret' => ['consumersecret', DI::l10n()->t('Consumer secret'), DI::config()->get('twitter', 'consumersecret'), ''], + $stack = HandlerStack::create(); + + $middleware = new Oauth1([ + 'consumer_key' => DI::pConfig()->get($uid, 'twitter', 'api_key'), + 'consumer_secret' => DI::pConfig()->get($uid, 'twitter', 'api_secret'), + 'token' => DI::pConfig()->get($uid, 'twitter', 'access_token'), + 'token_secret' => DI::pConfig()->get($uid, 'twitter', 'access_secret'), ]); -} - -function twitter_cron() -{ - $last = DI::keyValue()->get('twitter_last_poll'); - - $poll_interval = intval(DI::config()->get('twitter', 'poll_interval')); - if (!$poll_interval) { - $poll_interval = TWITTER_DEFAULT_POLL_INTERVAL; - } - - if ($last) { - $next = $last + ($poll_interval * 60); - if ($next > time()) { - Logger::notice('twitter: poll intervall not reached'); - return; - } - } - Logger::notice('twitter: cron_start'); - - $pconfigs = DBA::selectToArray('pconfig', [], ['cat' => 'twitter', 'k' => 'mirror_posts', 'v' => true]); - foreach ($pconfigs as $rr) { - Logger::notice('Fetching', ['user' => $rr['uid']]); - Worker::add(['priority' => Worker::PRIORITY_MEDIUM, 'force_priority' => true], 'addon/twitter/twitter_sync.php', 1, (int) $rr['uid']); - } - - $abandon_days = intval(DI::config()->get('system', 'account_abandon_days')); - if ($abandon_days < 1) { - $abandon_days = 0; - } - - $abandon_limit = date(DateTimeFormat::MYSQL, time() - $abandon_days * 86400); - - $pconfigs = DBA::selectToArray('pconfig', [], ['cat' => 'twitter', 'k' => 'import', 'v' => true]); - foreach ($pconfigs as $rr) { - if ($abandon_days != 0) { - if (!DBA::exists('user', ["`uid` = ? AND `login_date` >= ?", $rr['uid'], $abandon_limit])) { - Logger::notice('abandoned account: timeline from user will not be imported', ['user' => $rr['uid']]); - continue; - } - } - - Logger::notice('importing timeline', ['user' => $rr['uid']]); - Worker::add(['priority' => Worker::PRIORITY_MEDIUM, 'force_priority' => true], 'addon/twitter/twitter_sync.php', 2, (int) $rr['uid']); - /* - // To-Do - // check for new contacts once a day - $last_contact_check = DI::pConfig()->get($rr['uid'],'pumpio','contact_check'); - if($last_contact_check) - $next_contact_check = $last_contact_check + 86400; - else - $next_contact_check = 0; - - if($next_contact_check <= time()) { - pumpio_getallusers($rr["uid"]); - DI::pConfig()->set($rr['uid'],'pumpio','contact_check',time()); - } - */ - } - - Logger::notice('twitter: cron_end'); - - DI::keyValue()->set('twitter_last_poll', time()); -} - -function twitter_expire() -{ - $days = DI::config()->get('twitter', 'expire'); - - if ($days == 0) { - return; - } - - Logger::notice('Start deleting expired posts'); - - $r = Post::select(['id', 'guid'], ['deleted' => true, 'network' => Protocol::TWITTER]); - while ($row = Post::fetch($r)) { - Logger::info('[twitter] Delete expired item', ['id' => $row['id'], 'guid' => $row['guid'], 'callstack' => \Friendica\Core\System::callstack()]); - Item::markForDeletionById($row['id']); - } - DBA::close($r); - - Logger::notice('End deleting expired posts'); - - Logger::notice('Start expiry'); - - $pconfigs = DBA::selectToArray('pconfig', [], ['cat' => 'twitter', 'k' => 'import', 'v' => true]); - foreach ($pconfigs as $rr) { - Logger::notice('twitter_expire', ['user' => $rr['uid']]); - Item::expire($rr['uid'], $days, Protocol::TWITTER, true); - } - - Logger::notice('End expiry'); -} - -function twitter_prepare_body(array &$b) -{ - if ($b['item']['network'] != Protocol::TWITTER) { - return; - } - - if ($b['preview']) { - $max_char = 280; - $item = $b['item']; - $item['plink'] = DI::baseUrl() . '/display/' . $item['guid']; - - $condition = ['uri' => $item['thr-parent'], 'uid' => DI::userSession()->getLocalUserId()]; - $orig_post = Post::selectFirst(['author-link'], $condition); - if (DBA::isResult($orig_post)) { - $nicknameplain = preg_replace("=https?://twitter.com/(.*)=ism", "$1", $orig_post['author-link']); - $nickname = '@[url=' . $orig_post['author-link'] . ']' . $nicknameplain . '[/url]'; - $nicknameplain = '@' . $nicknameplain; - - if ((strpos($item['body'], $nickname) === false) && (strpos($item['body'], $nicknameplain) === false)) { - $item['body'] = $nickname . ' ' . $item['body']; - } - } - - $msgarr = Plaintext::getPost($item, $max_char, true, BBCode::TWITTER); - $msg = $msgarr['text']; - - if (isset($msgarr['url']) && ($msgarr['type'] != 'photo')) { - $msg .= ' ' . $msgarr['url']; - } - - if (isset($msgarr['image'])) { - $msg .= ' ' . $msgarr['image']; - } - - $b['html'] = nl2br(htmlspecialchars($msg)); - } -} - -function twitter_statuses_show(string $id, TwitterOAuth $twitterOAuth = null) -{ - if ($twitterOAuth === null) { - $ckey = DI::config()->get('twitter', 'consumerkey'); - $csecret = DI::config()->get('twitter', 'consumersecret'); - - if (empty($ckey) || empty($csecret)) { - return new stdClass(); - } - - $twitterOAuth = new TwitterOAuth($ckey, $csecret); - } - - $parameters = ['trim_user' => false, 'tweet_mode' => 'extended', 'id' => $id, 'include_ext_alt_text' => true]; - - return $twitterOAuth->get('statuses/show', $parameters); -} - -/** - * Parse Twitter status URLs since Twitter removed OEmbed - * - * @param array $b Expected format: - * [ - * 'url' => [URL to parse], - * 'format' => 'json'|'', - * 'text' => Output parameter - * ] - * @throws \Friendica\Network\HTTPException\InternalServerErrorException - */ -function twitter_parse_link(array &$b) -{ - // Only handle Twitter status URLs - if (!preg_match('#^https?://(?:mobile\.|www\.)?twitter.com/[^/]+/status/(\d+).*#', $b['url'], $matches)) { - return; - } - - $status = twitter_statuses_show($matches[1]); - - if (empty($status->id)) { - return; - } - - $item = twitter_createpost(0, $status, [], true, false, true); - if (empty($item)) { - return; - } - - if ($b['format'] == 'json') { - $images = []; - foreach ($status->extended_entities->media ?? [] as $media) { - if (!empty($media->media_url_https)) { - $images[] = [ - 'src' => $media->media_url_https, - 'width' => $media->sizes->thumb->w, - 'height' => $media->sizes->thumb->h, - ]; - } - } - - $b['text'] = [ - 'data' => [ - 'type' => 'link', - 'url' => $item['plink'], - 'title' => DI::l10n()->t('%s on Twitter', $status->user->name), - 'text' => BBCode::toPlaintext($item['body'], false), - 'images' => $images, - ], - 'contentType' => 'attachment', - 'success' => true, - ]; - } else { - $b['text'] = BBCode::getShareOpeningTag( - $item['author-name'], - $item['author-link'], - $item['author-avatar'], - $item['plink'], - $item['created'] - ); - $b['text'] .= $item['body'] . '[/share]'; - } -} - - -/********************* - * - * General functions - * - *********************/ - - -/** - * @brief Build the item array for the mirrored post - * - * @param integer $uid User id - * @param object $post Twitter object with the post - * - * @return array item data to be posted - */ -function twitter_do_mirrorpost(int $uid, $post) -{ - $datarray['uid'] = $uid; - $datarray['extid'] = 'twitter::' . $post->id; - $datarray['title'] = ''; - - if (!empty($post->retweeted_status)) { - // We don't support nested shares, so we mustn't show quotes as shares on retweets - $item = twitter_createpost($uid, $post->retweeted_status, ['id' => 0], false, false, true, -1); - - if (empty($item)) { - return []; - } - - $datarray['body'] = "\n" . BBCode::getShareOpeningTag( - $item['author-name'], - $item['author-link'], - $item['author-avatar'], - $item['plink'], - $item['created'] - ); - - $datarray['body'] .= $item['body'] . '[/share]'; - } else { - $item = twitter_createpost($uid, $post, ['id' => 0], false, false, false, -1); - - if (empty($item)) { - return []; - } - - $datarray['body'] = $item['body']; - } - - $datarray['app'] = $item['app']; - $datarray['verb'] = $item['verb']; - - if (isset($item['location'])) { - $datarray['location'] = $item['location']; - } - - if (isset($item['coord'])) { - $datarray['coord'] = $item['coord']; - } - - return $datarray; -} - -/** - * Fetches the Twitter user's own posts - * - * @param int $uid - * @return void - * @throws Exception - */ -function twitter_fetchtimeline(int $uid): void -{ - $ckey = DI::config()->get('twitter', 'consumerkey'); - $csecret = DI::config()->get('twitter', 'consumersecret'); - $otoken = DI::pConfig()->get($uid, 'twitter', 'oauthtoken'); - $osecret = DI::pConfig()->get($uid, 'twitter', 'oauthsecret'); - $lastid = DI::pConfig()->get($uid, 'twitter', 'lastid'); - - $application_name = DI::keyValue()->get('twitter_application_name') ?? ''; - - if ($application_name == '') { - $application_name = DI::baseUrl()->getHost(); - } - - $connection = new TwitterOAuth($ckey, $csecret, $otoken, $osecret); - - // Ensure to have the own contact - try { - twitter_fetch_own_contact($uid); - } catch (TwitterOAuthException $e) { - Logger::notice('Error fetching own contact', ['uid' => $uid, 'message' => $e->getMessage()]); - return; - } - - $parameters = [ - 'exclude_replies' => true, - 'trim_user' => false, - 'contributor_details' => true, - 'include_rts' => true, - 'tweet_mode' => 'extended', - 'include_ext_alt_text' => true, - ]; - - $first_time = ($lastid == ''); - - if ($lastid != '') { - $parameters['since_id'] = $lastid; - } - - try { - $items = $connection->get('statuses/user_timeline', $parameters); - } catch (TwitterOAuthException $e) { - Logger::notice('Error fetching timeline', ['uid' => $uid, 'message' => $e->getMessage()]); - return; - } - - if (!is_array($items)) { - Logger::notice('No items', ['user' => $uid]); - return; - } - - $posts = array_reverse($items); - - Logger::notice('Start processing posts', ['from' => $lastid, 'user' => $uid, 'count' => count($posts)]); - - if (count($posts)) { - foreach ($posts as $post) { - if ($post->id_str > $lastid) { - $lastid = $post->id_str; - DI::pConfig()->set($uid, 'twitter', 'lastid', $lastid); - } - - if ($first_time) { - Logger::notice('First time, continue'); - continue; - } - - if (stristr($post->source, $application_name)) { - Logger::notice('Source is application name', ['source' => $post->source, 'application_name' => $application_name]); - continue; - } - Logger::info('Preparing mirror post', ['twitter-id' => $post->id_str, 'uid' => $uid]); - - $mirrorpost = twitter_do_mirrorpost($uid, $post); - - if (empty($mirrorpost['body'])) { - Logger::notice('Body is empty', ['post' => $post, 'mirrorpost' => $mirrorpost]); - continue; - } - - Logger::info('Posting mirror post', ['twitter-id' => $post->id_str, 'uid' => $uid]); - - Post\Delayed::add($mirrorpost['extid'], $mirrorpost, Worker::PRIORITY_MEDIUM, Post\Delayed::PREPARED); - } - } - DI::pConfig()->set($uid, 'twitter', 'lastid', $lastid); - Logger::info('Last ID for user ' . $uid . ' is now ' . $lastid); -} - -function twitter_fix_avatar($avatar) -{ - $new_avatar = str_replace('_normal.', '_400x400.', $avatar); - - $info = Images::getInfoFromURLCached($new_avatar); - if (!$info) { - $new_avatar = $avatar; - } - - return $new_avatar; -} - -function twitter_get_relation($uid, $target, $contact = []) -{ - if (isset($contact['rel'])) { - $relation = $contact['rel']; - } else { - $relation = 0; - } - - $ckey = DI::config()->get('twitter', 'consumerkey'); - $csecret = DI::config()->get('twitter', 'consumersecret'); - $otoken = DI::pConfig()->get($uid, 'twitter', 'oauthtoken'); - $osecret = DI::pConfig()->get($uid, 'twitter', 'oauthsecret'); - $own_id = DI::pConfig()->get($uid, 'twitter', 'own_id'); - - $connection = new TwitterOAuth($ckey, $csecret, $otoken, $osecret); - $parameters = ['source_id' => $own_id, 'target_screen_name' => $target]; - - try { - $status = $connection->get('friendships/show', $parameters); - if ($connection->getLastHttpCode() !== 200) { - throw new Exception($status->errors[0]->message ?? 'HTTP response code ' . $connection->getLastHttpCode(), $status->errors[0]->code ?? $connection->getLastHttpCode()); - } - - $following = $status->relationship->source->following; - $followed = $status->relationship->source->followed_by; - - if ($following && !$followed) { - $relation = Contact::SHARING; - } elseif (!$following && $followed) { - $relation = Contact::FOLLOWER; - } elseif ($following && $followed) { - $relation = Contact::FRIEND; - } elseif (!$following && !$followed) { - $relation = 0; - } - - Logger::info('Fetched friendship relation', ['user' => $uid, 'target' => $target, 'relation' => $relation]); - } catch (Throwable $e) { - Logger::notice('Error fetching friendship status', ['uid' => $uid, 'target' => $target, 'message' => $e->getMessage()]); - } - - return $relation; -} - -/** - * @param $data - * @return array - */ -function twitter_user_to_contact($data) -{ - if (empty($data->id_str)) { - return []; - } - - $baseurl = 'https://twitter.com'; - $url = $baseurl . '/' . $data->screen_name; - $addr = $data->screen_name . '@twitter.com'; - - $fields = [ - 'url' => $url, - 'nurl' => Strings::normaliseLink($url), - 'uri-id' => ItemURI::getIdByURI($url), - 'network' => Protocol::TWITTER, - 'alias' => 'twitter::' . $data->id_str, - 'baseurl' => $baseurl, - 'name' => $data->name, - 'nick' => $data->screen_name, - 'addr' => $addr, - 'location' => $data->location, - 'about' => $data->description, - 'photo' => twitter_fix_avatar($data->profile_image_url_https), - 'header' => $data->profile_banner_url ?? $data->profile_background_image_url_https, - ]; - - return $fields; -} - -function twitter_get_contact($data, int $uid = 0) -{ - $contact = DBA::selectFirst('contact', ['id'], ['uid' => $uid, 'alias' => 'twitter::' . $data->id_str]); - if (DBA::isResult($contact)) { - return $contact['id']; - } else { - return twitter_fetch_contact($uid, $data, false); - } -} - -function twitter_fetch_contact($uid, $data, $create_user) -{ - $fields = twitter_user_to_contact($data); - - if (empty($fields)) { - return -1; - } - - // photo comes from twitter_user_to_contact but shouldn't be saved directly in the contact row - $avatar = $fields['photo']; - unset($fields['photo']); - - // Update the public contact - $pcontact = DBA::selectFirst('contact', ['id'], ['uid' => 0, 'alias' => 'twitter::' . $data->id_str]); - if (DBA::isResult($pcontact)) { - $cid = $pcontact['id']; - } else { - $cid = Contact::getIdForURL($fields['url'], 0, false, $fields); - } - - if (!empty($cid)) { - Contact::update($fields, ['id' => $cid]); - Contact::updateAvatar($cid, $avatar); - } else { - Logger::notice('No contact found', ['fields' => $fields]); - } - - $contact = DBA::selectFirst('contact', [], ['uid' => $uid, 'alias' => 'twitter::' . $data->id_str]); - if (!DBA::isResult($contact) && empty($cid)) { - Logger::notice('User contact not found', ['uid' => $uid, 'twitter-id' => $data->id_str]); - return 0; - } elseif (!$create_user) { - return $cid; - } - - if (!DBA::isResult($contact)) { - $relation = twitter_get_relation($uid, $data->screen_name); - - // create contact record - $fields['uid'] = $uid; - $fields['created'] = DateTimeFormat::utcNow(); - $fields['poll'] = 'twitter::' . $data->id_str; - $fields['rel'] = $relation; - $fields['priority'] = 1; - $fields['writable'] = true; - $fields['blocked'] = false; - $fields['readonly'] = false; - $fields['pending'] = false; - - if (!Contact::insert($fields)) { - return false; - } - - $contact_id = DBA::lastInsertId(); - - Circle::addMember(User::getDefaultCircle($uid), $contact_id); - } else { - if ($contact['readonly'] || $contact['blocked']) { - Logger::notice('Contact is blocked or readonly.', ['nickname' => $contact['nick']]); - return -1; - } - - $contact_id = $contact['id']; - $update = false; - - // Update the contact relation once per day - if ($contact['updated'] < DateTimeFormat::utc('now -24 hours')) { - $fields['rel'] = twitter_get_relation($uid, $data->screen_name, $contact); - $update = true; - } - - if ($contact['name'] != $data->name) { - $fields['name-date'] = $fields['uri-date'] = DateTimeFormat::utcNow(); - $update = true; - } - - if ($contact['nick'] != $data->screen_name) { - $fields['uri-date'] = DateTimeFormat::utcNow(); - $update = true; - } - - if (($contact['location'] != $data->location) || ($contact['about'] != $data->description)) { - $update = true; - } - - if ($update) { - $fields['updated'] = DateTimeFormat::utcNow(); - Contact::update($fields, ['id' => $contact['id']]); - Logger::info('Updated contact', ['id' => $contact['id'], 'nick' => $data->screen_name]); - } - } - - Contact::updateAvatar($contact_id, $avatar); - - if (Contact::isSharing($contact_id, $uid, true) && DI::pConfig()->get($uid, 'twitter', 'auto_follow')) { - twitter_auto_follow($uid, $data); - } - - return $contact_id; -} - -/** - * Follow a fediverse account that is proived in the name or the profile - * - * @param integer $uid - * @param object $data - */ -function twitter_auto_follow(int $uid, object $data) -{ - $addrpattern = '([A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6})'; - - // Search for user@domain.tld in the name - if (preg_match('#' . $addrpattern . '#', $data->name, $match)) { - if (twitter_add_contact($match[1], true, $uid)) { - return; - } - } - - // Search for @user@domain.tld in the description - if (preg_match('#@' . $addrpattern . '#', $data->description, $match)) { - if (twitter_add_contact($match[1], true, $uid)) { - return; - } - } - - // Search for user@domain.tld in the description - // We don't probe here, since this could be a mail address - if (preg_match('#' . $addrpattern . '#', $data->description, $match)) { - if (twitter_add_contact($match[1], false, $uid)) { - return; - } - } - - // Search for profile links in the description - foreach ($data->entities->description->urls as $url) { - if (!empty($url->expanded_url)) { - // We only probe on Mastodon style URL to reduce the number of unsuccessful probes - twitter_add_contact($url->expanded_url, strpos($url->expanded_url, '@'), $uid); - } - } -} - -/** - * Check if the provided address is a fediverse account and adds it - * - * @param string $addr - * @param boolean $probe - * @param integer $uid - * @return boolean - */ -function twitter_add_contact(string $addr, bool $probe, int $uid): bool -{ - $contact = Contact::getByURL($addr, $probe ? null : false, ['id', 'url', 'network']); - if (empty($contact)) { - Logger::debug('Not a contact address', ['uid' => $uid, 'probe' => $probe, 'addr' => $addr]); - return false; - } - - if (!in_array($contact['network'], Protocol::FEDERATED)) { - Logger::debug('Not a federated network', ['uid' => $uid, 'addr' => $addr, 'contact' => $contact]); - return false; - } - - if (Contact::isSharing($contact['id'], $uid)) { - Logger::debug('Contact has already been added', ['uid' => $uid, 'addr' => $addr, 'contact' => $contact]); - return true; - } - - Logger::info('Add contact', ['uid' => $uid, 'addr' => $addr, 'contact' => $contact]); - Worker::add(Worker::PRIORITY_LOW, 'AddContact', $uid, $contact['url']); - - return true; -} - -/** - * @param string $screen_name - * @return stdClass|null - * @throws Exception - */ -function twitter_fetchuser($screen_name) -{ - $ckey = DI::config()->get('twitter', 'consumerkey'); - $csecret = DI::config()->get('twitter', 'consumersecret'); - - try { - // Fetching user data - $connection = new TwitterOAuth($ckey, $csecret); - $parameters = ['screen_name' => $screen_name]; - $user = $connection->get('users/show', $parameters); - } catch (TwitterOAuthException $e) { - Logger::notice('Error fetching user', ['user' => $screen_name, 'message' => $e->getMessage()]); - return null; - } - - if (!is_object($user)) { - return null; - } - - return $user; -} - -/** - * Replaces Twitter entities with Friendica-friendly links. - * - * The Twitter API gives indices for each entity, which allows for fine-grained replacement. - * - * First, we need to collect everything that needs to be replaced, what we will replace it with, and the start index. - * Then we sort the indices decreasingly, and we replace from the end of the body to the start in order for the next - * index to be correct even after the last replacement. - * - * @param string $body - * @param stdClass $status - * @return array - * @throws \Friendica\Network\HTTPException\InternalServerErrorException - */ -function twitter_expand_entities($body, stdClass $status) -{ - $plain = $body; - $contains_urls = false; - - $taglist = []; - - $replacementList = []; - - foreach ($status->entities->hashtags AS $hashtag) { - $replace = '#[url=' . DI::baseUrl() . '/search?tag=' . $hashtag->text . ']' . $hashtag->text . '[/url]'; - $taglist['#' . $hashtag->text] = ['#', $hashtag->text, '']; - - $replacementList[$hashtag->indices[0]] = [ - 'replace' => $replace, - 'length' => $hashtag->indices[1] - $hashtag->indices[0], - ]; - } - - foreach ($status->entities->user_mentions AS $mention) { - $replace = '@[url=https://twitter.com/' . rawurlencode($mention->screen_name) . ']' . $mention->screen_name . '[/url]'; - $taglist['@' . $mention->screen_name] = ['@', $mention->screen_name, 'https://twitter.com/' . rawurlencode($mention->screen_name)]; - - $replacementList[$mention->indices[0]] = [ - 'replace' => $replace, - 'length' => $mention->indices[1] - $mention->indices[0], - ]; - } - - foreach ($status->entities->urls ?? [] as $url) { - $plain = str_replace($url->url, '', $plain); - - if ($url->url && $url->expanded_url && $url->display_url) { - // Quote tweet, we just remove the quoted tweet URL from the body, the share block will be added later. - if (!empty($status->quoted_status) && isset($status->quoted_status_id_str) - && substr($url->expanded_url, -strlen($status->quoted_status_id_str)) == $status->quoted_status_id_str - ) { - $replacementList[$url->indices[0]] = [ - 'replace' => '', - 'length' => $url->indices[1] - $url->indices[0], - ]; - continue; - } - - $contains_urls = true; - - $expanded_url = $url->expanded_url; - - // Quickfix: Workaround for URL with '[' and ']' in it - if (strpos($expanded_url, '[') || strpos($expanded_url, ']')) { - $expanded_url = $url->url; - } - - $replacementList[$url->indices[0]] = [ - 'replace' => '[url=' . $expanded_url . ']' . $url->display_url . '[/url]', - 'length' => $url->indices[1] - $url->indices[0], - ]; - } - } - - krsort($replacementList); - - foreach ($replacementList as $startIndex => $parameters) { - $body = Strings::substringReplace($body, $parameters['replace'], $startIndex, $parameters['length']); - } - - $body = trim($body); - - return ['body' => trim($body), 'plain' => trim($plain), 'taglist' => $taglist, 'urls' => $contains_urls]; -} - -/** - * Store entity attachments - * - * @param integer $uriId - * @param object $post Twitter object with the post - */ -function twitter_store_attachments(int $uriId, $post) -{ - if (!empty($post->extended_entities->media)) { - foreach ($post->extended_entities->media AS $medium) { - switch ($medium->type) { - case 'photo': - $attachment = ['uri-id' => $uriId, 'type' => Post\Media::IMAGE]; - - $attachment['url'] = $medium->media_url_https . '?name=large'; - $attachment['width'] = $medium->sizes->large->w; - $attachment['height'] = $medium->sizes->large->h; - - if ($medium->sizes->small->w != $attachment['width']) { - $attachment['preview'] = $medium->media_url_https . '?name=small'; - $attachment['preview-width'] = $medium->sizes->small->w; - $attachment['preview-height'] = $medium->sizes->small->h; - } - - $attachment['name'] = $medium->display_url ?? null; - $attachment['description'] = $medium->ext_alt_text ?? null; - Logger::debug('Photo attachment', ['attachment' => $attachment]); - Post\Media::insert($attachment); - break; - case 'video': - case 'animated_gif': - $attachment = ['uri-id' => $uriId, 'type' => Post\Media::VIDEO]; - if (is_array($medium->video_info->variants)) { - $bitrate = 0; - // We take the video with the highest bitrate - foreach ($medium->video_info->variants AS $variant) { - if (($variant->content_type == 'video/mp4') && ($variant->bitrate >= $bitrate)) { - $attachment['url'] = $variant->url; - $bitrate = $variant->bitrate; - } - } - } - - $attachment['name'] = $medium->display_url ?? null; - $attachment['preview'] = $medium->media_url_https . ':small'; - $attachment['preview-width'] = $medium->sizes->small->w; - $attachment['preview-height'] = $medium->sizes->small->h; - $attachment['description'] = $medium->ext_alt_text ?? null; - Logger::debug('Video attachment', ['attachment' => $attachment]); - Post\Media::insert($attachment); - break; - default: - Logger::notice('Unknown media type', ['medium' => $medium]); - } - } - } - - if (!empty($post->entities->urls)) { - foreach ($post->entities->urls as $url) { - $attachment = ['uri-id' => $uriId, 'type' => Post\Media::UNKNOWN, 'url' => $url->expanded_url, 'name' => $url->display_url]; - Logger::debug('Attached link', ['attachment' => $attachment]); - Post\Media::insert($attachment); - } - } -} - -/** - * @brief Fetch media entities and add media links to the body - * - * @param object $post Twitter object with the post - * @param array $postarray Array of the item that is about to be posted - * @param integer $uriId URI Id used to store tags. -1 = don't store tags for this post. - */ -function twitter_media_entities($post, array &$postarray, int $uriId = -1) -{ - // There are no media entities? So we quit. - if (empty($post->extended_entities->media)) { - return; - } - - // This is a pure media post, first search for all media urls - $media = []; - foreach ($post->extended_entities->media AS $medium) { - if (!isset($media[$medium->url])) { - $media[$medium->url] = ''; - } - switch ($medium->type) { - case 'photo': - if (!empty($medium->ext_alt_text)) { - Logger::info('Got text description', ['alt_text' => $medium->ext_alt_text]); - $media[$medium->url] .= "\n[img=" . $medium->media_url_https .']' . $medium->ext_alt_text . '[/img]'; - } else { - $media[$medium->url] .= "\n[img]" . $medium->media_url_https . '[/img]'; - } - - $postarray['object-type'] = Activity\ObjectType::IMAGE; - $postarray['post-type'] = Item::PT_IMAGE; - break; - case 'video': - // Currently deactivated, since this causes the video to be display before the content - // We have to figure out a better way for declaring the post type and the display style. - //$postarray['post-type'] = Item::PT_VIDEO; - case 'animated_gif': - if (!empty($medium->ext_alt_text)) { - Logger::info('Got text description', ['alt_text' => $medium->ext_alt_text]); - $media[$medium->url] .= "\n[img=" . $medium->media_url_https .']' . $medium->ext_alt_text . '[/img]'; - } else { - $media[$medium->url] .= "\n[img]" . $medium->media_url_https . '[/img]'; - } - - $postarray['object-type'] = Activity\ObjectType::VIDEO; - if (is_array($medium->video_info->variants)) { - $bitrate = 0; - // We take the video with the highest bitrate - foreach ($medium->video_info->variants AS $variant) { - if (($variant->content_type == 'video/mp4') && ($variant->bitrate >= $bitrate)) { - $media[$medium->url] = "\n[video]" . $variant->url . '[/video]'; - $bitrate = $variant->bitrate; - } - } - } - break; - } - } - - if ($uriId != -1) { - foreach ($media AS $key => $value) { - $postarray['body'] = str_replace($key, '', $postarray['body']); - } - return; - } - - // Now we replace the media urls. - foreach ($media AS $key => $value) { - $postarray['body'] = str_replace($key, "\n" . $value . "\n", $postarray['body']); - } -} - -/** - * Undocumented function - * - * @param integer $uid User ID - * @param object $post Incoming Twitter post - * @param array $self - * @param bool $create_user Should users be created? - * @param bool $only_existing_contact Only import existing contacts if set to "true" - * @param bool $noquote - * @param integer $uriId URI Id used to store tags. 0 = create a new one; -1 = don't store tags for this post. - * @return array item array - */ -function twitter_createpost(int $uid, $post, array $self, $create_user, bool $only_existing_contact, bool $noquote, int $uriId = 0): array -{ - $postarray = []; - $postarray['network'] = Protocol::TWITTER; - $postarray['uid'] = $uid; - $postarray['wall'] = 0; - $postarray['uri'] = 'twitter::' . $post->id_str; - $postarray['protocol'] = Conversation::PARCEL_TWITTER; - $postarray['source'] = json_encode($post); - $postarray['direction'] = Conversation::PULL; - - if (empty($uriId)) { - $uriId = $postarray['uri-id'] = ItemURI::insert(['uri' => $postarray['uri']]); - } - - // Don't import our own comments - if (Post::exists(['extid' => $postarray['uri'], 'uid' => $uid])) { - Logger::info('Item found', ['extid' => $postarray['uri']]); - return []; - } - - $contactid = 0; - - if ($post->in_reply_to_status_id_str != '') { - $thr_parent = 'twitter::' . $post->in_reply_to_status_id_str; - - $item = Post::selectFirst(['uri'], ['uri' => $thr_parent, 'uid' => $uid]); - if (!DBA::isResult($item)) { - $item = Post::selectFirst(['uri'], ['extid' => $thr_parent, 'uid' => $uid, 'gravity' => Item::GRAVITY_COMMENT]); - } - - if (DBA::isResult($item)) { - $postarray['thr-parent'] = $item['uri']; - $postarray['object-type'] = Activity\ObjectType::COMMENT; - } else { - $postarray['object-type'] = Activity\ObjectType::NOTE; - } - - // Is it me? - $own_id = DI::pConfig()->get($uid, 'twitter', 'own_id'); - - if ($post->user->id_str == $own_id) { - $self = Contact::selectFirst(['id', 'name', 'url', 'photo'], ['self' => true, 'uid' => $uid]); - if (DBA::isResult($self)) { - $contactid = $self['id']; - - $postarray['owner-id'] = Contact::getIdForURL($self['url']); - $postarray['owner-name'] = $self['name']; - $postarray['owner-link'] = $self['url']; - $postarray['owner-avatar'] = $self['photo']; - } else { - Logger::error('No self contact found', ['uid' => $uid]); - return []; - } - } - // Don't create accounts of people who just comment something - $create_user = false; - } else { - $postarray['object-type'] = Activity\ObjectType::NOTE; - } - - if ($contactid == 0) { - $contactid = twitter_fetch_contact($uid, $post->user, $create_user); - - $postarray['owner-id'] = twitter_get_contact($post->user); - $postarray['owner-name'] = $post->user->name; - $postarray['owner-link'] = 'https://twitter.com/' . $post->user->screen_name; - $postarray['owner-avatar'] = twitter_fix_avatar($post->user->profile_image_url_https); - } - - if (($contactid == 0) && !$only_existing_contact) { - $contactid = $self['id']; - } elseif ($contactid <= 0) { - Logger::info('Contact ID is zero or less than zero.'); - return []; - } - - $postarray['contact-id'] = $contactid; - $postarray['verb'] = Activity::POST; - $postarray['author-id'] = $postarray['owner-id']; - $postarray['author-name'] = $postarray['owner-name']; - $postarray['author-link'] = $postarray['owner-link']; - $postarray['author-avatar'] = $postarray['owner-avatar']; - $postarray['plink'] = 'https://twitter.com/' . $post->user->screen_name . '/status/' . $post->id_str; - $postarray['app'] = strip_tags($post->source); - - if ($post->user->protected) { - $postarray['private'] = Item::PRIVATE; - $postarray['allow_cid'] = '<' . $self['id'] . '>'; - } else { - $postarray['private'] = Item::UNLISTED; - $postarray['allow_cid'] = ''; - } - - if (!empty($post->full_text)) { - $postarray['body'] = $post->full_text; - } else { - $postarray['body'] = $post->text; - } - - // When the post contains links then use the correct object type - if (count($post->entities->urls) > 0) { - $postarray['object-type'] = Activity\ObjectType::BOOKMARK; - } - - // Search for media links - twitter_media_entities($post, $postarray, $uriId); - - $converted = twitter_expand_entities($postarray['body'], $post); - - // When the post contains external links then images or videos are just "decorations". - if (!empty($converted['urls'])) { - $postarray['post-type'] = Item::PT_NOTE; - } - - $postarray['body'] = $converted['body']; - $postarray['created'] = DateTimeFormat::utc($post->created_at); - $postarray['edited'] = DateTimeFormat::utc($post->created_at); - - if ($uriId > 0) { - twitter_store_tags($uriId, $converted['taglist']); - twitter_store_attachments($uriId, $post); - } - - if (!empty($post->place->name)) { - $postarray['location'] = $post->place->name; - } - if (!empty($post->place->full_name)) { - $postarray['location'] = $post->place->full_name; - } - if (!empty($post->geo->coordinates)) { - $postarray['coord'] = $post->geo->coordinates[0] . ' ' . $post->geo->coordinates[1]; - } - if (!empty($post->coordinates->coordinates)) { - $postarray['coord'] = $post->coordinates->coordinates[1] . ' ' . $post->coordinates->coordinates[0]; - } - if (!empty($post->retweeted_status)) { - $retweet = twitter_createpost($uid, $post->retweeted_status, $self, false, false, $noquote); - - if (empty($retweet)) { - return []; - } - - if (!$noquote) { - // Store the original tweet - Item::insert($retweet); - - // CHange the other post into a reshare activity - $postarray['verb'] = Activity::ANNOUNCE; - $postarray['gravity'] = Item::GRAVITY_ACTIVITY; - $postarray['object-type'] = Activity\ObjectType::NOTE; - - $postarray['thr-parent'] = $retweet['uri']; - } else { - $retweet['source'] = $postarray['source']; - $retweet['direction'] = $postarray['direction']; - $retweet['private'] = $postarray['private']; - $retweet['allow_cid'] = $postarray['allow_cid']; - $retweet['contact-id'] = $postarray['contact-id']; - $retweet['owner-id'] = $postarray['owner-id']; - $retweet['owner-name'] = $postarray['owner-name']; - $retweet['owner-link'] = $postarray['owner-link']; - $retweet['owner-avatar'] = $postarray['owner-avatar']; - - $postarray = $retweet; - } - } - - if (!empty($post->quoted_status)) { - if ($noquote) { - // To avoid recursive share blocks we just provide the link to avoid removing quote context. - $postarray['body'] .= "\n\nhttps://twitter.com/" . $post->quoted_status->user->screen_name . "/status/" . $post->quoted_status->id_str; - } else { - $quoted = twitter_createpost(0, $post->quoted_status, $self, false, false, true); - if (!empty($quoted)) { - Item::insert($quoted); - $post = Post::selectFirst(['guid', 'uri-id'], ['uri' => $quoted['uri'], 'uid' => 0]); - Logger::info('Stored quoted post', ['uid' => $uid, 'uri-id' => $uriId, 'post' => $post]); - - $postarray['body'] .= "\n" . BBCode::getShareOpeningTag( - $quoted['author-name'], - $quoted['author-link'], - $quoted['author-avatar'], - $quoted['plink'], - $quoted['created'], - $post['guid'] ?? '' - ); - - $postarray['body'] .= $quoted['body'] . '[/share]'; - } else { - // Quoted post author is blocked/ignored, so we just provide the link to avoid removing quote context. - $postarray['body'] .= "\n\nhttps://twitter.com/" . $post->quoted_status->user->screen_name . '/status/' . $post->quoted_status->id_str; - } - } - } - - return $postarray; -} - -/** - * Store tags and mentions - * - * @param integer $uriId - * @param array $taglist - * @return void - */ -function twitter_store_tags(int $uriId, array $taglist) -{ - foreach ($taglist as $tag) { - Tag::storeByHash($uriId, $tag[0], $tag[1], $tag[2]); - } -} - -function twitter_fetchparentposts(int $uid, $post, TwitterOAuth $connection, array $self) -{ - Logger::info('Fetching parent posts', ['user' => $uid, 'post' => $post->id_str]); - - $posts = []; - - while (!empty($post->in_reply_to_status_id_str)) { - try { - $post = twitter_statuses_show($post->in_reply_to_status_id_str, $connection); - } catch (TwitterOAuthException $e) { - Logger::notice('Error fetching parent post', ['uid' => $uid, 'post' => $post->id_str, 'message' => $e->getMessage()]); - break; - } - - if (empty($post)) { - Logger::info("twitter_fetchparentposts: Can't fetch post"); - break; - } - - if (empty($post->id_str)) { - Logger::info('twitter_fetchparentposts: This is not a post', ['post' => $post]); - break; - } - - if (Post::exists(['uri' => 'twitter::' . $post->id_str, 'uid' => $uid])) { - break; - } - - $posts[] = $post; - } - - Logger::info('twitter_fetchparentposts: Fetching ' . count($posts) . ' parents'); - - $posts = array_reverse($posts); - - if (!empty($posts)) { - foreach ($posts as $post) { - $postarray = twitter_createpost($uid, $post, $self, false, !DI::pConfig()->get($uid, 'twitter', 'create_user'), false); - - if (empty($postarray)) { - continue; - } - - $item = Item::insert($postarray); - - $postarray['id'] = $item; - - Logger::notice('twitter_fetchparentpost: User ' . $self['nick'] . ' posted parent timeline item ' . $item); - } - } -} - -/** - * Fetches the posts received by the Twitter user - * - * @param int $uid - * @return void - * @throws Exception - */ -function twitter_fetchhometimeline(int $uid): void -{ - $ckey = DI::config()->get('twitter', 'consumerkey'); - $csecret = DI::config()->get('twitter', 'consumersecret'); - $otoken = DI::pConfig()->get($uid, 'twitter', 'oauthtoken'); - $osecret = DI::pConfig()->get($uid, 'twitter', 'oauthsecret'); - $create_user = DI::pConfig()->get($uid, 'twitter', 'create_user'); - $mirror_posts = DI::pConfig()->get($uid, 'twitter', 'mirror_posts'); - - Logger::info('Fetching timeline', ['uid' => $uid]); - - $application_name = DI::keyValue()->get('twitter_application_name') ?? ''; - - if ($application_name == '') { - $application_name = DI::baseUrl()->getHost(); - } - - $connection = new TwitterOAuth($ckey, $csecret, $otoken, $osecret); - - try { - $own_contact = twitter_fetch_own_contact($uid); - } catch (TwitterOAuthException $e) { - Logger::notice('Error fetching own contact', ['uid' => $uid, 'message' => $e->getMessage()]); - return; - } - - $contact = Contact::selectFirst(['nick'], ['id' => $own_contact, 'uid' => $uid]); - if (DBA::isResult($contact)) { - $own_id = $contact['nick']; - } else { - Logger::notice('Own twitter contact not found', ['uid' => $uid]); - return; - } - - $self = User::getOwnerDataById($uid); - if ($self === false) { - Logger::warning('Own contact not found', ['uid' => $uid]); - return; - } - - $parameters = [ - 'exclude_replies' => false, - 'trim_user' => false, - 'contributor_details' => true, - 'include_rts' => true, - 'tweet_mode' => 'extended', - 'include_ext_alt_text' => true, - //'count' => 200, - ]; - - // Fetching timeline - $lastid = DI::pConfig()->get($uid, 'twitter', 'lasthometimelineid'); - - $first_time = ($lastid == ''); - - if ($lastid != '') { - $parameters['since_id'] = $lastid; - } - - try { - $items = $connection->get('statuses/home_timeline', $parameters); - } catch (TwitterOAuthException $e) { - Logger::notice('Error fetching home timeline', ['uid' => $uid, 'message' => $e->getMessage()]); - return; - } - - if (!is_array($items)) { - Logger::notice('home timeline is no array', ['items' => $items]); - return; - } - - if (empty($items)) { - Logger::info('No new timeline content', ['uid' => $uid]); - return; - } - - $posts = array_reverse($items); - - Logger::notice('Processing timeline', ['lastid' => $lastid, 'uid' => $uid, 'count' => count($posts)]); - - if (count($posts)) { - foreach ($posts as $post) { - if ($post->id_str > $lastid) { - $lastid = $post->id_str; - DI::pConfig()->set($uid, 'twitter', 'lasthometimelineid', $lastid); - } - - if ($first_time) { - continue; - } - - if (stristr($post->source, $application_name) && $post->user->screen_name == $own_id) { - Logger::info('Skip previously sent post'); - continue; - } - - if ($mirror_posts && $post->user->screen_name == $own_id && $post->in_reply_to_status_id_str == '') { - Logger::info('Skip post that will be mirrored'); - continue; - } - - if ($post->in_reply_to_status_id_str != '') { - twitter_fetchparentposts($uid, $post, $connection, $self); - } - - Logger::info('Preparing post ' . $post->id_str . ' for user ' . $uid); - - $postarray = twitter_createpost($uid, $post, $self, $create_user, true, false); - - if (empty($postarray)) { - Logger::info('Empty post ' . $post->id_str . ' and user ' . $uid); - continue; - } - - $notify = false; - - if (empty($postarray['thr-parent'])) { - $contact = DBA::selectFirst('contact', [], ['id' => $postarray['contact-id'], 'self' => false]); - if (DBA::isResult($contact) && Item::isRemoteSelf($contact, $postarray)) { - $notify = Worker::PRIORITY_MEDIUM; - } - } - - $postarray['wall'] = (bool)$notify; - - $item = Item::insert($postarray, $notify); - $postarray['id'] = $item; - - Logger::notice('User ' . $uid . ' posted home timeline item ' . $item); - } - } - DI::pConfig()->set($uid, 'twitter', 'lasthometimelineid', $lastid); - - Logger::info('Last timeline ID for user ' . $uid . ' is now ' . $lastid); - - // Fetching mentions - $lastid = DI::pConfig()->get($uid, 'twitter', 'lastmentionid'); - - $first_time = ($lastid == ''); - - if ($lastid != '') { - $parameters['since_id'] = $lastid; - } - - try { - $items = $connection->get('statuses/mentions_timeline', $parameters); - } catch (TwitterOAuthException $e) { - Logger::notice('Error fetching mentions', ['uid' => $uid, 'message' => $e->getMessage()]); - return; - } - - if (!is_array($items)) { - Logger::notice('mentions are no arrays', ['items' => $items]); - return; - } - - $posts = array_reverse($items); - - Logger::info('Fetching mentions for user ' . $uid . ' ' . sizeof($posts) . ' items'); - - if (count($posts)) { - foreach ($posts as $post) { - if ($post->id_str > $lastid) { - $lastid = $post->id_str; - } - - if ($first_time) { - continue; - } - - if ($post->in_reply_to_status_id_str != '') { - twitter_fetchparentposts($uid, $post, $connection, $self); - } - - $postarray = twitter_createpost($uid, $post, $self, false, !$create_user, false); - - if (empty($postarray)) { - continue; - } - - $item = Item::insert($postarray); - - Logger::notice('User ' . $uid . ' posted mention timeline item ' . $item); - } - } - - DI::pConfig()->set($uid, 'twitter', 'lastmentionid', $lastid); - - Logger::info('Last mentions ID for user ' . $uid . ' is now ' . $lastid); -} - -function twitter_fetch_own_contact(int $uid) -{ - $ckey = DI::config()->get('twitter', 'consumerkey'); - $csecret = DI::config()->get('twitter', 'consumersecret'); - $otoken = DI::pConfig()->get($uid, 'twitter', 'oauthtoken'); - $osecret = DI::pConfig()->get($uid, 'twitter', 'oauthsecret'); - - $own_id = DI::pConfig()->get($uid, 'twitter', 'own_id'); - - $contact_id = 0; - - if ($own_id == '') { - $connection = new TwitterOAuth($ckey, $csecret, $otoken, $osecret); - - // Fetching user data - // get() may throw TwitterOAuthException, but we will catch it later - $user = $connection->get('account/verify_credentials'); - if (empty($user->id_str)) { - return false; - } - - DI::pConfig()->set($uid, 'twitter', 'own_id', $user->id_str); - - $contact_id = twitter_fetch_contact($uid, $user, true); - } else { - $contact = Contact::selectFirst(['id'], ['uid' => $uid, 'alias' => 'twitter::' . $own_id]); - if (DBA::isResult($contact)) { - $contact_id = $contact['id']; - } else { - DI::pConfig()->delete($uid, 'twitter', 'own_id'); - } - } - - return $contact_id; -} - -function twitter_is_retweet(int $uid, string $body): bool -{ - $body = trim($body); - - // Skip if it isn't a pure repeated messages - // Does it start with a share? - if (strpos($body, '[share') > 0) { - return false; - } - - // Does it end with a share? - if (strlen($body) > (strrpos($body, '[/share]') + 8)) { - return false; - } - - $attributes = preg_replace("/\[share(.*?)\]\s?(.*?)\s?\[\/share\]\s?/ism", "$1", $body); - // Skip if there is no shared message in there - if ($body == $attributes) { - return false; - } - - $link = ''; - preg_match("/link='(.*?)'/ism", $attributes, $matches); - if (!empty($matches[1])) { - $link = $matches[1]; - } - - preg_match('/link="(.*?)"/ism', $attributes, $matches); - if (!empty($matches[1])) { - $link = $matches[1]; - } - - $id = preg_replace("=https?://twitter.com/(.*)/status/(.*)=ism", "$2", $link); - if ($id == $link) { - return false; - } - return twitter_retweet($uid, $id); -} - -function twitter_retweet(int $uid, int $id, int $item_id = 0): bool -{ - Logger::info('Retweeting', ['user' => $uid, 'id' => $id]); - - $result = twitter_api_post('statuses/retweet', $id, $uid); - - Logger::info('Retweeted', ['user' => $uid, 'id' => $id, 'result' => $result]); - - if (!empty($item_id) && !empty($result->id_str)) { - Logger::notice('Update extid', ['id' => $item_id, 'extid' => $result->id_str]); - Item::update(['extid' => 'twitter::' . $result->id_str], ['id' => $item_id]); - } - - return !isset($result->errors); -} - -function twitter_update_mentions(string $body): string -{ - $URLSearchString = '^\[\]'; - $return = preg_replace_callback( - "/@\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism", - function ($matches) { - if (strpos($matches[1], 'twitter.com')) { - $return = '@' . substr($matches[1], strrpos($matches[1], '/') + 1); - } else { - $return = $matches[2] . ' (' . $matches[1] . ')'; - } - - return $return; - }, - $body - ); - - return $return; -} - -function twitter_convert_share(array $attributes, array $author_contact, string $content, bool $is_quote_share): string -{ - if (empty($author_contact)) { - return $content . "\n\n" . $attributes['link']; - } - - if (!empty($author_contact['network']) && ($author_contact['network'] == Protocol::TWITTER)) { - $mention = '@' . $author_contact['nick']; - } else { - $mention = $author_contact['addr']; - } - - return ($is_quote_share ? "\n\n" : '' ) . 'RT ' . $mention . ': ' . $content . "\n\n" . $attributes['link']; + + $stack->push($middleware); + + $client = new Client([ + 'handler' => $stack + ]); + + $response = $client->post($url, ['auth' => 'oauth', $type => $data]); + + $content = json_decode($response->getBody()->getContents()) ?? new stdClass; + Logger::debug('Success', ['content' => $content]); + return $content; } diff --git a/twitter/twitter_sync.php b/twitter/twitter_sync.php deleted file mode 100644 index 073793e2d..000000000 --- a/twitter/twitter_sync.php +++ /dev/null @@ -1,31 +0,0 @@ -get('system', 'maxloadavg', 50); - if (intval($load[0]) > $maxload) { - Logger::notice('load too high. Twitter sync deferred to next scheduled run.', ['current' => $load[0], 'max' => $maxload]); - return; - } - } - - if ($argc < 3) { - return; - } - - $mode = intval($argv[1]); - $uid = intval($argv[2]); - - if ($mode == 1) { - twitter_fetchtimeline($uid); - } elseif ($mode == 2) { - twitter_fetchhometimeline($uid); - } -} diff --git a/twitter/vendor/abraham/twitteroauth/.github/dependabot.yml b/twitter/vendor/abraham/twitteroauth/.github/dependabot.yml deleted file mode 100644 index e064c4e0e..000000000 --- a/twitter/vendor/abraham/twitteroauth/.github/dependabot.yml +++ /dev/null @@ -1,14 +0,0 @@ -version: 2 -updates: - - package-ecosystem: npm - directory: '/' - schedule: - interval: daily - time: '11:00' - open-pull-requests-limit: 10 - - package-ecosystem: composer - directory: '/' - schedule: - interval: daily - time: '11:00' - open-pull-requests-limit: 10 diff --git a/twitter/vendor/abraham/twitteroauth/.github/workflows/lint.yaml b/twitter/vendor/abraham/twitteroauth/.github/workflows/lint.yaml deleted file mode 100644 index 6b718cd8e..000000000 --- a/twitter/vendor/abraham/twitteroauth/.github/workflows/lint.yaml +++ /dev/null @@ -1,12 +0,0 @@ -name: Lint -on: push -jobs: - lint: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v1 - with: - node-version: 12 - - run: npm ci - - run: npm run lint diff --git a/twitter/vendor/abraham/twitteroauth/.github/workflows/test.yaml b/twitter/vendor/abraham/twitteroauth/.github/workflows/test.yaml deleted file mode 100644 index 78af4a8fa..000000000 --- a/twitter/vendor/abraham/twitteroauth/.github/workflows/test.yaml +++ /dev/null @@ -1,18 +0,0 @@ -name: Test -on: push -jobs: - run: - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - php-versions: ['7.2', '7.3', '7.4', '8.0'] - name: PHP ${{ matrix.php-versions }} - steps: - - uses: actions/checkout@v2 - - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php-versions }} - - run: composer validate --no-interaction --strict - - run: composer install --no-interaction --prefer-dist - - run: npm test diff --git a/twitter/vendor/abraham/twitteroauth/.gitignore b/twitter/vendor/abraham/twitteroauth/.gitignore deleted file mode 100644 index f018d18ac..000000000 --- a/twitter/vendor/abraham/twitteroauth/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -.DS_Store -vendor -env -*.cache -node_modules diff --git a/twitter/vendor/abraham/twitteroauth/.prettierignore b/twitter/vendor/abraham/twitteroauth/.prettierignore deleted file mode 100644 index fb96e4520..000000000 --- a/twitter/vendor/abraham/twitteroauth/.prettierignore +++ /dev/null @@ -1,3 +0,0 @@ -vendor -composer.lock -tests/fixtures diff --git a/twitter/vendor/abraham/twitteroauth/.prettierrc.json b/twitter/vendor/abraham/twitteroauth/.prettierrc.json deleted file mode 100644 index cf18896b8..000000000 --- a/twitter/vendor/abraham/twitteroauth/.prettierrc.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "singleQuote": true, - "phpVersion": "7.2", - "trailingCommaPHP": true, - "braceStyle": "psr-2" -} diff --git a/twitter/vendor/abraham/twitteroauth/CODE_OF_CONDUCT.md b/twitter/vendor/abraham/twitteroauth/CODE_OF_CONDUCT.md deleted file mode 100644 index 80b423909..000000000 --- a/twitter/vendor/abraham/twitteroauth/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,46 +0,0 @@ -# Contributor Covenant Code of Conduct - -## Our Pledge - -In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. - -## Our Standards - -Examples of behavior that contributes to creating a positive environment include: - -- Using welcoming and inclusive language -- Being respectful of differing viewpoints and experiences -- Gracefully accepting constructive criticism -- Focusing on what is best for the community -- Showing empathy towards other community members - -Examples of unacceptable behavior by participants include: - -- The use of sexualized language or imagery and unwelcome sexual attention or advances -- Trolling, insulting/derogatory comments, and personal or political attacks -- Public or private harassment -- Publishing others' private information, such as a physical or electronic address, without explicit permission -- Other conduct which could reasonably be considered inappropriate in a professional setting - -## Our Responsibilities - -Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. - -Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. - -## Scope - -This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at abraham@abrah.am. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. - -Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] - -[homepage]: http://contributor-covenant.org -[version]: http://contributor-covenant.org/version/1/4/ diff --git a/twitter/vendor/abraham/twitteroauth/CONTRIBUTING.md b/twitter/vendor/abraham/twitteroauth/CONTRIBUTING.md deleted file mode 100644 index d941b2c94..000000000 --- a/twitter/vendor/abraham/twitteroauth/CONTRIBUTING.md +++ /dev/null @@ -1,21 +0,0 @@ -# Contributing to TwitterOAuth - -## 👏 Thanks! - -Thanks for your interest in contributing to TwitterOAuth. We appreciate contributions small and large. - -## 🌱 Grow - -If you have an idea for something new or would like to improve something. Please [open a quick issue](https://github.com/abraham/twitteroauth/issues/new) explaining the changes and the reasons for them. Everyone's time is important and we don't want you duplicating work someone else might already be working on. - -GitHub has [outlined instructions](https://help.github.com/articles/fork-a-repo/) for forking a repo. To work on an update to this repo, you will: - -- Fork the repo -- Make the changes -- Submit a pull request - -Once the [pull request](https://help.github.com/articles/about-pull-requests/) is reviewed, if the changes are approved they will be merged in to the project. - -## 🐛 Bugs - -Please [open a new issue](https://github.com/abraham/twitteroauth/issues/new) and details what you are trying to do, what is happening, and what you expect to happen. Err on the side of providing more details. diff --git a/twitter/vendor/abraham/twitteroauth/LICENSE.md b/twitter/vendor/abraham/twitteroauth/LICENSE.md deleted file mode 100644 index 3a631e0cf..000000000 --- a/twitter/vendor/abraham/twitteroauth/LICENSE.md +++ /dev/null @@ -1,22 +0,0 @@ -Copyright (c) 2009 Abraham Williams - http://abrah.am - abraham@abrah.am - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. diff --git a/twitter/vendor/abraham/twitteroauth/README.md b/twitter/vendor/abraham/twitteroauth/README.md deleted file mode 100644 index 5afe95f09..000000000 --- a/twitter/vendor/abraham/twitteroauth/README.md +++ /dev/null @@ -1,11 +0,0 @@ -TwitterOAuth [![Build Status](https://github.com/abraham/twitteroauth/workflows/Test/badge.svg)](https://github.com/abraham/twitteroauth/actions) [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/abraham/twitteroauth/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/abraham/twitteroauth/?branch=master) [![Issues Count](https://img.shields.io/github/issues/abraham/twitteroauth.svg)](https://github.com/abraham/twitteroauth/issues) [![Latest Version](https://img.shields.io/packagist/v/abraham/twitteroauth.svg)](https://packagist.org/packages/abraham/twitteroauth) [![Downloads this Month](https://img.shields.io/packagist/dm/abraham/twitteroauth.svg)](https://packagist.org/packages/abraham/twitteroauth) - ---- - -

The most popular PHP library for Twitter's OAuth REST API.

- -See documentation at https://twitteroauth.com. - -PHP versions [listed](https://secure.php.net/supported-versions.php) as "active support" or "security fixes only" are supported. - -Twitter bird diff --git a/twitter/vendor/abraham/twitteroauth/autoload.php b/twitter/vendor/abraham/twitteroauth/autoload.php deleted file mode 100644 index 337975455..000000000 --- a/twitter/vendor/abraham/twitteroauth/autoload.php +++ /dev/null @@ -1,35 +0,0 @@ -=6.0.0", - "yoast/phpunit-polyfills": "^0.1.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Assert\\": "lib/Assert" - }, - "files": [ - "lib/Assert/functions.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-2-Clause" - ], - "authors": [ - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de", - "role": "Lead Developer" - }, - { - "name": "Richard Quadling", - "email": "rquadling@gmail.com", - "role": "Collaborator" - } - ], - "description": "Thin assertion library for input validation in business models.", - "keywords": [ - "assert", - "assertion", - "validation" - ], - "time": "2020-11-13T20:02:54+00:00" - }, - { - "name": "composer/xdebug-handler", - "version": "1.4.3", - "source": { - "type": "git", - "url": "https://github.com/composer/xdebug-handler.git", - "reference": "ebd27a9866ae8254e873866f795491f02418c5a5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/ebd27a9866ae8254e873866f795491f02418c5a5", - "reference": "ebd27a9866ae8254e873866f795491f02418c5a5", - "shasum": "" - }, - "require": { - "php": "^5.3.2 || ^7.0 || ^8.0", - "psr/log": "^1.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || 6.5 - 8" - }, - "type": "library", - "autoload": { - "psr-4": { - "Composer\\XdebugHandler\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "John Stevenson", - "email": "john-stevenson@blueyonder.co.uk" - } - ], - "description": "Restarts a process without Xdebug.", - "keywords": [ - "Xdebug", - "performance" - ], - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2020-08-19T10:27:58+00:00" - }, - { - "name": "doctrine/instantiator", - "version": "1.4.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/d56bf6102915de5702778fe20f2de3b2fe570b5b", - "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "doctrine/coding-standard": "^8.0", - "ext-pdo": "*", - "ext-phar": "*", - "phpbench/phpbench": "^0.13 || 1.0.0-alpha2", - "phpstan/phpstan": "^0.12", - "phpstan/phpstan-phpunit": "^0.12", - "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "https://ocramius.github.io/" - } - ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://www.doctrine-project.org/projects/instantiator.html", - "keywords": [ - "constructor", - "instantiate" - ], - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", - "type": "tidelift" - } - ], - "time": "2020-11-10T18:47:58+00:00" - }, - { - "name": "myclabs/deep-copy", - "version": "1.10.2", - "source": { - "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/776f831124e9c62e1a2c601ecc52e776d8bb7220", - "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "replace": { - "myclabs/deep-copy": "self.version" - }, - "require-dev": { - "doctrine/collections": "^1.0", - "doctrine/common": "^2.6", - "phpunit/phpunit": "^7.1" - }, - "type": "library", - "autoload": { - "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - }, - "files": [ - "src/DeepCopy/deep_copy.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Create deep copies (clones) of your objects", - "keywords": [ - "clone", - "copy", - "duplicate", - "object", - "object graph" - ], - "funding": [ - { - "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", - "type": "tidelift" - } - ], - "time": "2020-11-13T09:40:50+00:00" - }, - { - "name": "pdepend/pdepend", - "version": "2.8.0", - "source": { - "type": "git", - "url": "https://github.com/pdepend/pdepend.git", - "reference": "c64472f8e76ca858c79ad9a4cf1e2734b3f8cc38" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/pdepend/pdepend/zipball/c64472f8e76ca858c79ad9a4cf1e2734b3f8cc38", - "reference": "c64472f8e76ca858c79ad9a4cf1e2734b3f8cc38", - "shasum": "" - }, - "require": { - "php": ">=5.3.7", - "symfony/config": "^2.3.0|^3|^4|^5", - "symfony/dependency-injection": "^2.3.0|^3|^4|^5", - "symfony/filesystem": "^2.3.0|^3|^4|^5" - }, - "require-dev": { - "easy-doc/easy-doc": "0.0.0 || ^1.2.3", - "gregwar/rst": "^1.0", - "phpunit/phpunit": "^4.8.35|^5.7", - "squizlabs/php_codesniffer": "^2.0.0" - }, - "bin": [ - "src/bin/pdepend" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.x-dev" - } - }, - "autoload": { - "psr-4": { - "PDepend\\": "src/main/php/PDepend" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Official version of pdepend to be handled with Composer", - "funding": [ - { - "url": "https://tidelift.com/funding/github/packagist/pdepend/pdepend", - "type": "tidelift" - } - ], - "time": "2020-06-20T10:53:13+00:00" - }, - { - "name": "phar-io/manifest", - "version": "2.0.1", - "source": { - "type": "git", - "url": "https://github.com/phar-io/manifest.git", - "reference": "85265efd3af7ba3ca4b2a2c34dbfc5788dd29133" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/85265efd3af7ba3ca4b2a2c34dbfc5788dd29133", - "reference": "85265efd3af7ba3ca4b2a2c34dbfc5788dd29133", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-phar": "*", - "ext-xmlwriter": "*", - "phar-io/version": "^3.0.1", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", - "time": "2020-06-27T14:33:11+00:00" - }, - { - "name": "phar-io/version", - "version": "3.0.3", - "source": { - "type": "git", - "url": "https://github.com/phar-io/version.git", - "reference": "726c026815142e4f8677b7cb7f2249c9ffb7ecae" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/726c026815142e4f8677b7cb7f2249c9ffb7ecae", - "reference": "726c026815142e4f8677b7cb7f2249c9ffb7ecae", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Library for handling version information and constraints", - "time": "2020-11-30T09:21:21+00:00" - }, - { - "name": "php-vcr/php-vcr", - "version": "1.5.1", - "source": { - "type": "git", - "url": "https://github.com/php-vcr/php-vcr.git", - "reference": "c482b6e7da4135a04329ffe1e0528ccc3c082bc6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-vcr/php-vcr/zipball/c482b6e7da4135a04329ffe1e0528ccc3c082bc6", - "reference": "c482b6e7da4135a04329ffe1e0528ccc3c082bc6", - "shasum": "" - }, - "require": { - "beberlei/assert": "^3.2.5", - "ext-curl": "*", - "php": ">=7.2", - "symfony/event-dispatcher": "^2.4|^3.0|^4.0|^5.0", - "symfony/yaml": "~2.1|^3.0|^4.0|^5.0" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^2.16", - "mikey179/vfsstream": "^1.6", - "phpstan/phpstan": "^0.12", - "phpstan/phpstan-beberlei-assert": "^0.12.0", - "phpunit/phpunit": "^7.4.3", - "sebastian/version": "^1.0.3|^2.0", - "thecodingmachine/phpstan-strict-rules": "^0.12" - }, - "type": "library", - "autoload": { - "psr-4": { - "VCR\\": "src/VCR/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Adrian Philipp", - "email": "mail@adrian-philipp.com" - } - ], - "description": "Record your test suite's HTTP interactions and replay them during future test runs for fast, deterministic, accurate tests.", - "time": "2020-11-22T13:11:57+00:00" - }, - { - "name": "php-vcr/phpunit-testlistener-vcr", - "version": "dev-php-8", - "source": { - "type": "git", - "url": "https://github.com/abraham/phpunit-testlistener-vcr", - "reference": "13a0e1213d3415e3c5cdda9450a4979b5867020a" - }, - "require": { - "php": "^7.1 | ^8.0", - "php-vcr/php-vcr": "^1.4" - }, - "require-dev": { - "phpunit/phpunit": "^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "VCR\\PHPUnit\\TestListener\\": "src/" - } - }, - "autoload-dev": { - "psr-4": { - "Tests\\VCR\\PHPUnit\\TestListener\\": "tests/" - } - }, - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Adrian Philipp", - "email": "mail@adrian-philipp.com" - } - ], - "description": "Integrates PHPUnit with PHP-VCR.", - "time": "2020-11-28T17:40:26+00:00" - }, - { - "name": "phpdocumentor/reflection-common", - "version": "2.2.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-2.x": "2.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" - } - ], - "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org", - "keywords": [ - "FQSEN", - "phpDocumentor", - "phpdoc", - "reflection", - "static analysis" - ], - "time": "2020-06-27T09:03:43+00:00" - }, - { - "name": "phpdocumentor/reflection-docblock", - "version": "5.2.2", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/069a785b2141f5bcf49f3e353548dc1cce6df556", - "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556", - "shasum": "" - }, - "require": { - "ext-filter": "*", - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.2", - "phpdocumentor/type-resolver": "^1.3", - "webmozart/assert": "^1.9.1" - }, - "require-dev": { - "mockery/mockery": "~1.3.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - }, - { - "name": "Jaap van Otterdijk", - "email": "account@ijaap.nl" - } - ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2020-09-03T19:13:55+00:00" - }, - { - "name": "phpdocumentor/type-resolver", - "version": "1.4.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0", - "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.0" - }, - "require-dev": { - "ext-tokenizer": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-1.x": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", - "time": "2020-09-17T18:55:26+00:00" - }, - { - "name": "phpmd/phpmd", - "version": "2.9.1", - "source": { - "type": "git", - "url": "https://github.com/phpmd/phpmd.git", - "reference": "ce10831d4ddc2686c1348a98069771dd314534a8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpmd/phpmd/zipball/ce10831d4ddc2686c1348a98069771dd314534a8", - "reference": "ce10831d4ddc2686c1348a98069771dd314534a8", - "shasum": "" - }, - "require": { - "composer/xdebug-handler": "^1.0", - "ext-xml": "*", - "pdepend/pdepend": "^2.7.1", - "php": ">=5.3.9" - }, - "require-dev": { - "easy-doc/easy-doc": "0.0.0 || ^1.3.2", - "ext-json": "*", - "ext-simplexml": "*", - "gregwar/rst": "^1.0", - "mikey179/vfsstream": "^1.6.4", - "phpunit/phpunit": "^4.8.36 || ^5.7.27", - "squizlabs/php_codesniffer": "^2.0" - }, - "bin": [ - "src/bin/phpmd" - ], - "type": "library", - "autoload": { - "psr-0": { - "PHPMD\\": "src/main/php" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Manuel Pichler", - "email": "github@manuel-pichler.de", - "homepage": "https://github.com/manuelpichler", - "role": "Project Founder" - }, - { - "name": "Marc Würth", - "email": "ravage@bluewin.ch", - "homepage": "https://github.com/ravage84", - "role": "Project Maintainer" - }, - { - "name": "Other contributors", - "homepage": "https://github.com/phpmd/phpmd/graphs/contributors", - "role": "Contributors" - } - ], - "description": "PHPMD is a spin-off project of PHP Depend and aims to be a PHP equivalent of the well known Java tool PMD.", - "homepage": "https://phpmd.org/", - "keywords": [ - "mess detection", - "mess detector", - "pdepend", - "phpmd", - "pmd" - ], - "funding": [ - { - "url": "https://tidelift.com/funding/github/packagist/phpmd/phpmd", - "type": "tidelift" - } - ], - "time": "2020-09-23T22:06:32+00:00" - }, - { - "name": "phpspec/prophecy", - "version": "1.12.1", - "source": { - "type": "git", - "url": "https://github.com/phpspec/prophecy.git", - "reference": "8ce87516be71aae9b956f81906aaf0338e0d8a2d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/8ce87516be71aae9b956f81906aaf0338e0d8a2d", - "reference": "8ce87516be71aae9b956f81906aaf0338e0d8a2d", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.2", - "php": "^7.2 || ~8.0, <8.1", - "phpdocumentor/reflection-docblock": "^5.2", - "sebastian/comparator": "^3.0 || ^4.0", - "sebastian/recursion-context": "^3.0 || ^4.0" - }, - "require-dev": { - "phpspec/phpspec": "^6.0", - "phpunit/phpunit": "^8.0 || ^9.0 <9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.11.x-dev" - } - }, - "autoload": { - "psr-4": { - "Prophecy\\": "src/Prophecy" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" - }, - { - "name": "Marcello Duarte", - "email": "marcello.duarte@gmail.com" - } - ], - "description": "Highly opinionated mocking framework for PHP 5.3+", - "homepage": "https://github.com/phpspec/prophecy", - "keywords": [ - "Double", - "Dummy", - "fake", - "mock", - "spy", - "stub" - ], - "time": "2020-09-29T09:10:42+00:00" - }, - { - "name": "phpunit/php-code-coverage", - "version": "7.0.13", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "ad0dcd7b184e76f7198a1fe07685bfbec3ae911a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ad0dcd7b184e76f7198a1fe07685bfbec3ae911a", - "reference": "ad0dcd7b184e76f7198a1fe07685bfbec3ae911a", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-xmlwriter": "*", - "php": ">=7.2", - "phpunit/php-file-iterator": "^2.0.2", - "phpunit/php-text-template": "^1.2.1", - "phpunit/php-token-stream": "^3.1.1", - "sebastian/code-unit-reverse-lookup": "^1.0.1", - "sebastian/environment": "^4.2.2", - "sebastian/version": "^2.0.1", - "theseer/tokenizer": "^1.1.3" - }, - "require-dev": { - "phpunit/phpunit": "^8.2.2" - }, - "suggest": { - "ext-xdebug": "^2.7.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "7.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", - "keywords": [ - "coverage", - "testing", - "xunit" - ], - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-11-30T08:35:22+00:00" - }, - { - "name": "phpunit/php-file-iterator", - "version": "2.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "4b49fb70f067272b659ef0174ff9ca40fdaa6357" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/4b49fb70f067272b659ef0174ff9ca40fdaa6357", - "reference": "4b49fb70f067272b659ef0174ff9ca40fdaa6357", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "require-dev": { - "phpunit/phpunit": "^8.5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" - ], - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-11-30T08:25:21+00:00" - }, - { - "name": "phpunit/php-text-template", - "version": "1.2.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], - "time": "2015-06-21T13:50:34+00:00" - }, - { - "name": "phpunit/php-timer", - "version": "2.1.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "2454ae1765516d20c4ffe103d85a58a9a3bd5662" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/2454ae1765516d20c4ffe103d85a58a9a3bd5662", - "reference": "2454ae1765516d20c4ffe103d85a58a9a3bd5662", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "require-dev": { - "phpunit/phpunit": "^8.5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-11-30T08:20:02+00:00" - }, - { - "name": "phpunit/php-token-stream", - "version": "3.1.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "472b687829041c24b25f475e14c2f38a09edf1c2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/472b687829041c24b25f475e14c2f38a09edf1c2", - "reference": "472b687829041c24b25f475e14c2f38a09edf1c2", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": ">=7.1" - }, - "require-dev": { - "phpunit/phpunit": "^7.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Wrapper around PHP's tokenizer extension.", - "homepage": "https://github.com/sebastianbergmann/php-token-stream/", - "keywords": [ - "tokenizer" - ], - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "abandoned": true, - "time": "2020-11-30T08:38:46+00:00" - }, - { - "name": "phpunit/phpunit", - "version": "8.5.13", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "8e86be391a58104ef86037ba8a846524528d784e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/8e86be391a58104ef86037ba8a846524528d784e", - "reference": "8e86be391a58104ef86037ba8a846524528d784e", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.3.1", - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-xml": "*", - "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.10.0", - "phar-io/manifest": "^2.0.1", - "phar-io/version": "^3.0.2", - "php": ">=7.2", - "phpspec/prophecy": "^1.10.3", - "phpunit/php-code-coverage": "^7.0.12", - "phpunit/php-file-iterator": "^2.0.2", - "phpunit/php-text-template": "^1.2.1", - "phpunit/php-timer": "^2.1.2", - "sebastian/comparator": "^3.0.2", - "sebastian/diff": "^3.0.2", - "sebastian/environment": "^4.2.3", - "sebastian/exporter": "^3.1.2", - "sebastian/global-state": "^3.0.0", - "sebastian/object-enumerator": "^3.0.3", - "sebastian/resource-operations": "^2.0.1", - "sebastian/type": "^1.1.3", - "sebastian/version": "^2.0.1" - }, - "require-dev": { - "ext-pdo": "*" - }, - "suggest": { - "ext-soap": "*", - "ext-xdebug": "*", - "phpunit/php-invoker": "^2.0.0" - }, - "bin": [ - "phpunit" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "8.5-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], - "funding": [ - { - "url": "https://phpunit.de/donate.html", - "type": "custom" - }, - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-12-01T04:53:52+00:00" - }, - { - "name": "psr/container", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", - "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Container\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", - "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" - ], - "time": "2017-02-14T16:28:37+00:00" - }, - { - "name": "psr/log", - "version": "1.1.3", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/0f73288fd15629204f9d42b7055f72dacbe811fc", - "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Log\\": "Psr/Log/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ], - "time": "2020-03-23T09:12:05+00:00" - }, - { - "name": "sebastian/code-unit-reverse-lookup", - "version": "1.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "1de8cd5c010cb153fcd68b8d0f64606f523f7619" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/1de8cd5c010cb153fcd68b8d0f64606f523f7619", - "reference": "1de8cd5c010cb153fcd68b8d0f64606f523f7619", - "shasum": "" - }, - "require": { - "php": ">=5.6" - }, - "require-dev": { - "phpunit/phpunit": "^8.5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Looks up which function or method a line of code belongs to", - "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-11-30T08:15:22+00:00" - }, - { - "name": "sebastian/comparator", - "version": "3.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "1071dfcef776a57013124ff35e1fc41ccd294758" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/1071dfcef776a57013124ff35e1fc41ccd294758", - "reference": "1071dfcef776a57013124ff35e1fc41ccd294758", - "shasum": "" - }, - "require": { - "php": ">=7.1", - "sebastian/diff": "^3.0", - "sebastian/exporter": "^3.1" - }, - "require-dev": { - "phpunit/phpunit": "^8.5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - } - ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "https://github.com/sebastianbergmann/comparator", - "keywords": [ - "comparator", - "compare", - "equality" - ], - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-11-30T08:04:30+00:00" - }, - { - "name": "sebastian/diff", - "version": "3.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "14f72dd46eaf2f2293cbe79c93cc0bc43161a211" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/14f72dd46eaf2f2293cbe79c93cc0bc43161a211", - "reference": "14f72dd46eaf2f2293cbe79c93cc0bc43161a211", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "require-dev": { - "phpunit/phpunit": "^7.5 || ^8.0", - "symfony/process": "^2 || ^3.3 || ^4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - } - ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff", - "udiff", - "unidiff", - "unified diff" - ], - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-11-30T07:59:04+00:00" - }, - { - "name": "sebastian/environment", - "version": "4.2.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "d47bbbad83711771f167c72d4e3f25f7fcc1f8b0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/d47bbbad83711771f167c72d4e3f25f7fcc1f8b0", - "reference": "d47bbbad83711771f167c72d4e3f25f7fcc1f8b0", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "require-dev": { - "phpunit/phpunit": "^7.5" - }, - "suggest": { - "ext-posix": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.2-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" - ], - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-11-30T07:53:42+00:00" - }, - { - "name": "sebastian/exporter", - "version": "3.1.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "6b853149eab67d4da22291d36f5b0631c0fd856e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/6b853149eab67d4da22291d36f5b0631c0fd856e", - "reference": "6b853149eab67d4da22291d36f5b0631c0fd856e", - "shasum": "" - }, - "require": { - "php": ">=7.0", - "sebastian/recursion-context": "^3.0" - }, - "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "^6.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.1.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "http://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" - ], - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-11-30T07:47:53+00:00" - }, - { - "name": "sebastian/global-state", - "version": "3.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "474fb9edb7ab891665d3bfc6317f42a0a150454b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/474fb9edb7ab891665d3bfc6317f42a0a150454b", - "reference": "474fb9edb7ab891665d3bfc6317f42a0a150454b", - "shasum": "" - }, - "require": { - "php": ">=7.2", - "sebastian/object-reflector": "^1.1.1", - "sebastian/recursion-context": "^3.0" - }, - "require-dev": { - "ext-dom": "*", - "phpunit/phpunit": "^8.0" - }, - "suggest": { - "ext-uopz": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", - "keywords": [ - "global state" - ], - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-11-30T07:43:24+00:00" - }, - { - "name": "sebastian/object-enumerator", - "version": "3.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "e67f6d32ebd0c749cf9d1dbd9f226c727043cdf2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/e67f6d32ebd0c749cf9d1dbd9f226c727043cdf2", - "reference": "e67f6d32ebd0c749cf9d1dbd9f226c727043cdf2", - "shasum": "" - }, - "require": { - "php": ">=7.0", - "sebastian/object-reflector": "^1.1.1", - "sebastian/recursion-context": "^3.0" - }, - "require-dev": { - "phpunit/phpunit": "^6.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Traverses array structures and object graphs to enumerate all referenced objects", - "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-11-30T07:40:27+00:00" - }, - { - "name": "sebastian/object-reflector", - "version": "1.1.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "9b8772b9cbd456ab45d4a598d2dd1a1bced6363d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/9b8772b9cbd456ab45d4a598d2dd1a1bced6363d", - "reference": "9b8772b9cbd456ab45d4a598d2dd1a1bced6363d", - "shasum": "" - }, - "require": { - "php": ">=7.0" - }, - "require-dev": { - "phpunit/phpunit": "^6.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Allows reflection of object attributes, including inherited and non-public ones", - "homepage": "https://github.com/sebastianbergmann/object-reflector/", - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-11-30T07:37:18+00:00" - }, - { - "name": "sebastian/recursion-context", - "version": "3.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "367dcba38d6e1977be014dc4b22f47a484dac7fb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/367dcba38d6e1977be014dc4b22f47a484dac7fb", - "reference": "367dcba38d6e1977be014dc4b22f47a484dac7fb", - "shasum": "" - }, - "require": { - "php": ">=7.0" - }, - "require-dev": { - "phpunit/phpunit": "^6.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-11-30T07:34:24+00:00" - }, - { - "name": "sebastian/resource-operations", - "version": "2.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "31d35ca87926450c44eae7e2611d45a7a65ea8b3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/31d35ca87926450c44eae7e2611d45a7a65ea8b3", - "reference": "31d35ca87926450c44eae7e2611d45a7a65ea8b3", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides a list of PHP built-in functions that operate on resources", - "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-11-30T07:30:19+00:00" - }, - { - "name": "sebastian/type", - "version": "1.1.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/type.git", - "reference": "0150cfbc4495ed2df3872fb31b26781e4e077eb4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/0150cfbc4495ed2df3872fb31b26781e4e077eb4", - "reference": "0150cfbc4495ed2df3872fb31b26781e4e077eb4", - "shasum": "" - }, - "require": { - "php": ">=7.2" - }, - "require-dev": { - "phpunit/phpunit": "^8.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Collection of value objects that represent the types of the PHP type system", - "homepage": "https://github.com/sebastianbergmann/type", - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-11-30T07:25:11+00:00" - }, - { - "name": "sebastian/version", - "version": "2.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", - "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", - "shasum": "" - }, - "require": { - "php": ">=5.6" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", - "time": "2016-10-03T07:35:21+00:00" - }, - { - "name": "squizlabs/php_codesniffer", - "version": "3.5.8", - "source": { - "type": "git", - "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "9d583721a7157ee997f235f327de038e7ea6dac4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/9d583721a7157ee997f235f327de038e7ea6dac4", - "reference": "9d583721a7157ee997f235f327de038e7ea6dac4", - "shasum": "" - }, - "require": { - "ext-simplexml": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": ">=5.4.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" - }, - "bin": [ - "bin/phpcs", - "bin/phpcbf" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Greg Sherwood", - "role": "lead" - } - ], - "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", - "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", - "keywords": [ - "phpcs", - "standards" - ], - "time": "2020-10-23T02:01:07+00:00" - }, - { - "name": "symfony/config", - "version": "v4.4.13", - "source": { - "type": "git", - "url": "https://github.com/symfony/config.git", - "reference": "043bf8652c307ebc23ce44047d215eec889d8850" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/043bf8652c307ebc23ce44047d215eec889d8850", - "reference": "043bf8652c307ebc23ce44047d215eec889d8850", - "shasum": "" - }, - "require": { - "php": ">=7.1.3", - "symfony/filesystem": "^3.4|^4.0|^5.0", - "symfony/polyfill-ctype": "~1.8" - }, - "conflict": { - "symfony/finder": "<3.4" - }, - "require-dev": { - "symfony/event-dispatcher": "^3.4|^4.0|^5.0", - "symfony/finder": "^3.4|^4.0|^5.0", - "symfony/messenger": "^4.1|^5.0", - "symfony/service-contracts": "^1.1|^2", - "symfony/yaml": "^3.4|^4.0|^5.0" - }, - "suggest": { - "symfony/yaml": "To use the yaml reference dumper" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.4-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Config\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Config Component", - "homepage": "https://symfony.com", - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2020-08-10T07:27:51+00:00" - }, - { - "name": "symfony/dependency-injection", - "version": "v4.4.13", - "source": { - "type": "git", - "url": "https://github.com/symfony/dependency-injection.git", - "reference": "384c2601e5a6228d60b041911d63f010e0885ffb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/384c2601e5a6228d60b041911d63f010e0885ffb", - "reference": "384c2601e5a6228d60b041911d63f010e0885ffb", - "shasum": "" - }, - "require": { - "php": ">=7.1.3", - "psr/container": "^1.0", - "symfony/service-contracts": "^1.1.6|^2" - }, - "conflict": { - "symfony/config": "<4.3|>=5.0", - "symfony/finder": "<3.4", - "symfony/proxy-manager-bridge": "<3.4", - "symfony/yaml": "<3.4" - }, - "provide": { - "psr/container-implementation": "1.0", - "symfony/service-implementation": "1.0" - }, - "require-dev": { - "symfony/config": "^4.3", - "symfony/expression-language": "^3.4|^4.0|^5.0", - "symfony/yaml": "^3.4|^4.0|^5.0" - }, - "suggest": { - "symfony/config": "", - "symfony/expression-language": "For using expressions in service container configuration", - "symfony/finder": "For using double-star glob patterns or when GLOB_BRACE portability is required", - "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", - "symfony/yaml": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.4-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\DependencyInjection\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony DependencyInjection Component", - "homepage": "https://symfony.com", - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2020-09-01T17:42:15+00:00" - }, - { - "name": "symfony/event-dispatcher", - "version": "v4.4.16", - "source": { - "type": "git", - "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "4204f13d2d0b7ad09454f221bb2195fccdf1fe98" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/4204f13d2d0b7ad09454f221bb2195fccdf1fe98", - "reference": "4204f13d2d0b7ad09454f221bb2195fccdf1fe98", - "shasum": "" - }, - "require": { - "php": ">=7.1.3", - "symfony/event-dispatcher-contracts": "^1.1" - }, - "conflict": { - "symfony/dependency-injection": "<3.4" - }, - "provide": { - "psr/event-dispatcher-implementation": "1.0", - "symfony/event-dispatcher-implementation": "1.1" - }, - "require-dev": { - "psr/log": "~1.0", - "symfony/config": "^3.4|^4.0|^5.0", - "symfony/dependency-injection": "^3.4|^4.0|^5.0", - "symfony/error-handler": "~3.4|~4.4", - "symfony/expression-language": "^3.4|^4.0|^5.0", - "symfony/http-foundation": "^3.4|^4.0|^5.0", - "symfony/service-contracts": "^1.1|^2", - "symfony/stopwatch": "^3.4|^4.0|^5.0" - }, - "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\EventDispatcher\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony EventDispatcher Component", - "homepage": "https://symfony.com", - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2020-10-24T11:50:19+00:00" - }, - { - "name": "symfony/event-dispatcher-contracts", - "version": "v1.1.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "84e23fdcd2517bf37aecbd16967e83f0caee25a7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/84e23fdcd2517bf37aecbd16967e83f0caee25a7", - "reference": "84e23fdcd2517bf37aecbd16967e83f0caee25a7", - "shasum": "" - }, - "require": { - "php": ">=7.1.3" - }, - "suggest": { - "psr/event-dispatcher": "", - "symfony/event-dispatcher-implementation": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\EventDispatcher\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to dispatching event", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2020-07-06T13:19:58+00:00" - }, - { - "name": "symfony/filesystem", - "version": "v4.4.13", - "source": { - "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "27575bcbc68db1f6d06218891296572c9b845704" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/27575bcbc68db1f6d06218891296572c9b845704", - "reference": "27575bcbc68db1f6d06218891296572c9b845704", - "shasum": "" - }, - "require": { - "php": ">=7.1.3", - "symfony/polyfill-ctype": "~1.8" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.4-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Filesystem\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Filesystem Component", - "homepage": "https://symfony.com", - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2020-08-21T17:19:37+00:00" - }, - { - "name": "symfony/polyfill-ctype", - "version": "v1.20.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "f4ba089a5b6366e453971d3aad5fe8e897b37f41" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/f4ba089a5b6366e453971d3aad5fe8e897b37f41", - "reference": "f4ba089a5b6366e453971d3aad5fe8e897b37f41", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-ctype": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.20-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for ctype functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "ctype", - "polyfill", - "portable" - ], - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2020-10-23T14:02:19+00:00" - }, - { - "name": "symfony/service-contracts", - "version": "v1.1.9", - "source": { - "type": "git", - "url": "https://github.com/symfony/service-contracts.git", - "reference": "b776d18b303a39f56c63747bcb977ad4b27aca26" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/b776d18b303a39f56c63747bcb977ad4b27aca26", - "reference": "b776d18b303a39f56c63747bcb977ad4b27aca26", - "shasum": "" - }, - "require": { - "php": ">=7.1.3", - "psr/container": "^1.0" - }, - "suggest": { - "symfony/service-implementation": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\Service\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to writing services", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2020-07-06T13:19:58+00:00" - }, - { - "name": "symfony/yaml", - "version": "v4.4.16", - "source": { - "type": "git", - "url": "https://github.com/symfony/yaml.git", - "reference": "543cb4dbd45ed803f08a9a65f27fb149b5dd20c2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/543cb4dbd45ed803f08a9a65f27fb149b5dd20c2", - "reference": "543cb4dbd45ed803f08a9a65f27fb149b5dd20c2", - "shasum": "" - }, - "require": { - "php": ">=7.1.3", - "symfony/polyfill-ctype": "~1.8" - }, - "conflict": { - "symfony/console": "<3.4" - }, - "require-dev": { - "symfony/console": "^3.4|^4.0|^5.0" - }, - "suggest": { - "symfony/console": "For validating YAML files using the lint command" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Yaml\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Yaml Component", - "homepage": "https://symfony.com", - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2020-10-24T11:50:19+00:00" - }, - { - "name": "theseer/tokenizer", - "version": "1.2.0", - "source": { - "type": "git", - "url": "https://github.com/theseer/tokenizer.git", - "reference": "75a63c33a8577608444246075ea0af0d052e452a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/75a63c33a8577608444246075ea0af0d052e452a", - "reference": "75a63c33a8577608444246075ea0af0d052e452a", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - } - ], - "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", - "funding": [ - { - "url": "https://github.com/theseer", - "type": "github" - } - ], - "time": "2020-07-12T23:59:07+00:00" - }, - { - "name": "webmozart/assert", - "version": "1.9.1", - "source": { - "type": "git", - "url": "https://github.com/webmozart/assert.git", - "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/bafc69caeb4d49c39fd0779086c03a3738cbb389", - "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389", - "shasum": "" - }, - "require": { - "php": "^5.3.3 || ^7.0 || ^8.0", - "symfony/polyfill-ctype": "^1.8" - }, - "conflict": { - "phpstan/phpstan": "<0.12.20", - "vimeo/psalm": "<3.9.1" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.36 || ^7.5.13" - }, - "type": "library", - "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ], - "time": "2020-07-08T17:02:28+00:00" - } - ], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": { - "php-vcr/phpunit-testlistener-vcr": 20 - }, - "prefer-stable": false, - "prefer-lowest": false, - "platform": { - "php": "^7.2 || ^7.3 || ^7.4 || ^8.0", - "ext-curl": "*" - }, - "platform-dev": [], - "plugin-api-version": "2.0.0" -} diff --git a/twitter/vendor/abraham/twitteroauth/package-lock.json b/twitter/vendor/abraham/twitteroauth/package-lock.json deleted file mode 100644 index daafae0c6..000000000 --- a/twitter/vendor/abraham/twitteroauth/package-lock.json +++ /dev/null @@ -1,511 +0,0 @@ -{ - "name": "twitteroauth", - "version": "0.0.0", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@prettier/plugin-php": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/@prettier/plugin-php/-/plugin-php-0.16.0.tgz", - "integrity": "sha512-HG/FamMUtq4/9hZmeuvwy0BWmOr4m9OWacvLSUmmgUrQd4+TRZW7Nqs2MAJkwSNiBIgAKTt2Vw9PK+33Gxxx8g==", - "dev": true, - "requires": { - "linguist-languages": "^7.5.1", - "mem": "^8.0.0", - "php-parser": "3.0.2" - } - }, - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "dependencies": { - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "concurrently": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-5.3.0.tgz", - "integrity": "sha512-8MhqOB6PWlBfA2vJ8a0bSFKATOdWlHiQlk11IfmQBPaHVP8oP2gsh2MObE6UR3hqDHqvaIvLTyceNW6obVuFHQ==", - "dev": true, - "requires": { - "chalk": "^2.4.2", - "date-fns": "^2.0.1", - "lodash": "^4.17.15", - "read-pkg": "^4.0.1", - "rxjs": "^6.5.2", - "spawn-command": "^0.0.2-1", - "supports-color": "^6.1.0", - "tree-kill": "^1.2.2", - "yargs": "^13.3.0" - } - }, - "date-fns": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.15.0.tgz", - "integrity": "sha512-ZCPzAMJZn3rNUvvQIMlXhDr4A+Ar07eLeGsGREoWU19a3Pqf5oYa+ccd+B3F6XVtQY6HANMFdOQ8A+ipFnvJdQ==", - "dev": true - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", - "dev": true - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "linguist-languages": { - "version": "7.11.1", - "resolved": "https://registry.npmjs.org/linguist-languages/-/linguist-languages-7.11.1.tgz", - "integrity": "sha512-+cRUk+1WTbydcdzipXQER2iilX+wMrb1LPkbkGuDP/IcGPJRDmOZH6Olf1iH6sHlHwPnJYiNJH39YsFCVZxvUQ==", - "dev": true - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "lodash": { - "version": "4.17.19", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", - "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", - "dev": true - }, - "map-age-cleaner": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", - "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", - "dev": true, - "requires": { - "p-defer": "^1.0.0" - } - }, - "mem": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-8.0.0.tgz", - "integrity": "sha512-qrcJOe6uD+EW8Wrci1Vdiua/15Xw3n/QnaNXE7varnB6InxSk7nu3/i5jfy3S6kWxr8WYJ6R1o0afMUtvorTsA==", - "dev": true, - "requires": { - "map-age-cleaner": "^0.1.3", - "mimic-fn": "^3.1.0" - } - }, - "mimic-fn": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.1.0.tgz", - "integrity": "sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==", - "dev": true - }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "p-defer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", - "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", - "dev": true - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true - }, - "php-parser": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/php-parser/-/php-parser-3.0.2.tgz", - "integrity": "sha512-a7y1+odEGsceLDLpu7oNyspZ0pK8FMWJOoim4/yd82AtnEZNLdCLZ67arnOQZ9K0lHJiSp4/7lVUpGELVxE14w==", - "dev": true - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - }, - "prettier": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz", - "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==", - "dev": true - }, - "prettier-plugin-package": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/prettier-plugin-package/-/prettier-plugin-package-1.3.0.tgz", - "integrity": "sha512-KPNHR/Jm2zTevBp1SnjzMnooO1BOQW2bixVbOp8flOJoW+dxdDwEncObfsKZdkjwrv6AIH4oWqm5EO/etDmK9Q==", - "dev": true - }, - "read-pkg": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-4.0.1.tgz", - "integrity": "sha1-ljYlN48+HE1IyFhytabsfV0JMjc=", - "dev": true, - "requires": { - "normalize-package-data": "^2.3.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0" - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - }, - "rxjs": { - "version": "6.6.2", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.2.tgz", - "integrity": "sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "spawn-command": { - "version": "0.0.2-1", - "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", - "integrity": "sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A=", - "dev": true - }, - "spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - }, - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "dev": true - }, - "tslib": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", - "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", - "dev": true - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - } - }, - "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true - }, - "yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - } - }, - "yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } -} diff --git a/twitter/vendor/abraham/twitteroauth/package.json b/twitter/vendor/abraham/twitteroauth/package.json deleted file mode 100644 index 81746e3df..000000000 --- a/twitter/vendor/abraham/twitteroauth/package.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "name": "twitteroauth", - "version": "0.0.0", - "description": "The most popular PHP library for use with the Twitter OAuth REST API.", - "license": "MIT", - "repository": { - "type": "git", - "url": "git+https://github.com/abraham/twitteroauth.git" - }, - "author": "Abraham Williams ", - "homepage": "https://github.com/abraham/twitteroauth#readme", - "bugs": { - "url": "https://github.com/abraham/twitteroauth/issues" - }, - "scripts": { - "fix": "concurrently npm:fix:*", - "fix:phpcbf": "./vendor/bin/phpcbf src tests --standard=PSR12", - "fix:prettier": "prettier . --write", - "lint": "concurrently npm:lint:*", - "lint:phpcs": "./vendor/bin/phpcs src tests --standard=PSR12", - "lint:prettier": "prettier . --check", - "postinstall": "composer install --no-interaction", - "test": "./vendor/bin/phpunit" - }, - "keywords": [ - "twitter", - "api", - "oauth", - "rest", - "social", - "twitter-api", - "twitter-oauth" - ], - "dependencies": {}, - "devDependencies": { - "@prettier/plugin-php": "0.16.0", - "concurrently": "^5.3.0", - "prettier": "2.2.1", - "prettier-plugin-package": "1.3.0" - }, - "directories": { - "test": "tests" - } -} diff --git a/twitter/vendor/abraham/twitteroauth/phpmd.xml b/twitter/vendor/abraham/twitteroauth/phpmd.xml deleted file mode 100644 index ef45e75aa..000000000 --- a/twitter/vendor/abraham/twitteroauth/phpmd.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - Keep TwitterOAuth source code clean. - - - - - - - - diff --git a/twitter/vendor/abraham/twitteroauth/phpunit.xml b/twitter/vendor/abraham/twitteroauth/phpunit.xml deleted file mode 100644 index d882f5bde..000000000 --- a/twitter/vendor/abraham/twitteroauth/phpunit.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - ./tests/ - - - - - - - diff --git a/twitter/vendor/abraham/twitteroauth/src/Config.php b/twitter/vendor/abraham/twitteroauth/src/Config.php deleted file mode 100644 index ab7ee2e4a..000000000 --- a/twitter/vendor/abraham/twitteroauth/src/Config.php +++ /dev/null @@ -1,109 +0,0 @@ - - */ -class Config -{ - /** @var int How long to wait for a response from the API */ - protected $timeout = 5; - /** @var int how long to wait while connecting to the API */ - protected $connectionTimeout = 5; - /** @var int How many times we retry request when API is down */ - protected $maxRetries = 0; - /** @var int Delay in seconds before we retry the request */ - protected $retriesDelay = 1; - - /** - * Decode JSON Response as associative Array - * - * @see http://php.net/manual/en/function.json-decode.php - * - * @var bool - */ - protected $decodeJsonAsArray = false; - /** @var string User-Agent header */ - protected $userAgent = 'TwitterOAuth (+https://twitteroauth.com)'; - /** @var array Store proxy connection details */ - protected $proxy = []; - - /** @var bool Whether to encode the curl requests with gzip or not */ - protected $gzipEncoding = true; - - /** @var integer Size for Chunked Uploads */ - protected $chunkSize = 250000; // 0.25 MegaByte - - /** - * Set the connection and response timeouts. - * - * @param int $connectionTimeout - * @param int $timeout - */ - public function setTimeouts(int $connectionTimeout, int $timeout): void - { - $this->connectionTimeout = $connectionTimeout; - $this->timeout = $timeout; - } - - /** - * Set the number of times to retry on error and how long between each. - * - * @param int $maxRetries - * @param int $retriesDelay - */ - public function setRetries(int $maxRetries, int $retriesDelay): void - { - $this->maxRetries = $maxRetries; - $this->retriesDelay = $retriesDelay; - } - - /** - * @param bool $value - */ - public function setDecodeJsonAsArray(bool $value): void - { - $this->decodeJsonAsArray = $value; - } - - /** - * @param string $userAgent - */ - public function setUserAgent(string $userAgent): void - { - $this->userAgent = $userAgent; - } - - /** - * @param array $proxy - */ - public function setProxy(array $proxy): void - { - $this->proxy = $proxy; - } - - /** - * Whether to encode the curl requests with gzip or not. - * - * @param boolean $gzipEncoding - */ - public function setGzipEncoding(bool $gzipEncoding): void - { - $this->gzipEncoding = $gzipEncoding; - } - - /** - * Set the size of each part of file for chunked media upload. - * - * @param int $value - */ - public function setChunkSize(int $value): void - { - $this->chunkSize = $value; - } -} diff --git a/twitter/vendor/abraham/twitteroauth/src/Consumer.php b/twitter/vendor/abraham/twitteroauth/src/Consumer.php deleted file mode 100644 index 3f3797a09..000000000 --- a/twitter/vendor/abraham/twitteroauth/src/Consumer.php +++ /dev/null @@ -1,43 +0,0 @@ -key = $key; - $this->secret = $secret; - $this->callbackUrl = $callbackUrl; - } - - /** - * @return string - */ - public function __toString() - { - return "Consumer[key=$this->key,secret=$this->secret]"; - } -} diff --git a/twitter/vendor/abraham/twitteroauth/src/HmacSha1.php b/twitter/vendor/abraham/twitteroauth/src/HmacSha1.php deleted file mode 100644 index 922b2cf0f..000000000 --- a/twitter/vendor/abraham/twitteroauth/src/HmacSha1.php +++ /dev/null @@ -1,46 +0,0 @@ -getSignatureBaseString(); - - $parts = [$consumer->secret, null !== $token ? $token->secret : '']; - - $parts = Util::urlencodeRfc3986($parts); - $key = implode('&', $parts); - - return base64_encode(hash_hmac('sha1', $signatureBase, $key, true)); - } -} diff --git a/twitter/vendor/abraham/twitteroauth/src/Request.php b/twitter/vendor/abraham/twitteroauth/src/Request.php deleted file mode 100644 index c3e1dc170..000000000 --- a/twitter/vendor/abraham/twitteroauth/src/Request.php +++ /dev/null @@ -1,289 +0,0 @@ -parameters = $parameters; - $this->httpMethod = $httpMethod; - $this->httpUrl = $httpUrl; - } - - /** - * pretty much a helper function to set up the request - * - * @param Consumer $consumer - * @param Token $token - * @param string $httpMethod - * @param string $httpUrl - * @param array $parameters - * - * @return Request - */ - public static function fromConsumerAndToken( - Consumer $consumer, - Token $token = null, - string $httpMethod, - string $httpUrl, - array $parameters = [], - $json = false - ) { - $defaults = [ - 'oauth_version' => Request::$version, - 'oauth_nonce' => Request::generateNonce(), - 'oauth_timestamp' => time(), - 'oauth_consumer_key' => $consumer->key, - ]; - if (null !== $token) { - $defaults['oauth_token'] = $token->key; - } - - // The json payload is not included in the signature on json requests, - // therefore it shouldn't be included in the parameters array. - if ($json) { - $parameters = $defaults; - } else { - $parameters = array_merge($defaults, $parameters); - } - - return new Request($httpMethod, $httpUrl, $parameters); - } - - /** - * @param string $name - * @param string $value - */ - public function setParameter(string $name, string $value) - { - $this->parameters[$name] = $value; - } - - /** - * @param string $name - * - * @return string|null - */ - public function getParameter(string $name): ?string - { - return isset($this->parameters[$name]) - ? $this->parameters[$name] - : null; - } - - /** - * @return array - */ - public function getParameters(): array - { - return $this->parameters; - } - - /** - * @param string $name - */ - public function removeParameter(string $name): void - { - unset($this->parameters[$name]); - } - - /** - * The request parameters, sorted and concatenated into a normalized string. - * - * @return string - */ - public function getSignableParameters(): string - { - // Grab all parameters - $params = $this->parameters; - - // Remove oauth_signature if present - // Ref: Spec: 9.1.1 ("The oauth_signature parameter MUST be excluded.") - if (isset($params['oauth_signature'])) { - unset($params['oauth_signature']); - } - - return Util::buildHttpQuery($params); - } - - /** - * Returns the base string of this request - * - * The base string defined as the method, the url - * and the parameters (normalized), each urlencoded - * and the concated with &. - * - * @return string - */ - public function getSignatureBaseString(): string - { - $parts = [ - $this->getNormalizedHttpMethod(), - $this->getNormalizedHttpUrl(), - $this->getSignableParameters(), - ]; - - $parts = Util::urlencodeRfc3986($parts); - - return implode('&', $parts); - } - - /** - * Returns the HTTP Method in uppercase - * - * @return string - */ - public function getNormalizedHttpMethod(): string - { - return strtoupper($this->httpMethod); - } - - /** - * parses the url and rebuilds it to be - * scheme://host/path - * - * @return string - */ - public function getNormalizedHttpUrl(): string - { - $parts = parse_url($this->httpUrl); - - $scheme = $parts['scheme']; - $host = strtolower($parts['host']); - $path = $parts['path']; - - return "$scheme://$host$path"; - } - - /** - * Builds a url usable for a GET request - * - * @return string - */ - public function toUrl(): string - { - $postData = $this->toPostdata(); - $out = $this->getNormalizedHttpUrl(); - if ($postData) { - $out .= '?' . $postData; - } - return $out; - } - - /** - * Builds the data one would send in a POST request - * - * @return string - */ - public function toPostdata(): string - { - return Util::buildHttpQuery($this->parameters); - } - - /** - * Builds the Authorization: header - * - * @return string - * @throws TwitterOAuthException - */ - public function toHeader(): string - { - $first = true; - $out = 'Authorization: OAuth'; - foreach ($this->parameters as $k => $v) { - if (substr($k, 0, 5) != 'oauth') { - continue; - } - if (is_array($v)) { - throw new TwitterOAuthException( - 'Arrays not supported in headers' - ); - } - $out .= $first ? ' ' : ', '; - $out .= - Util::urlencodeRfc3986($k) . - '="' . - Util::urlencodeRfc3986($v) . - '"'; - $first = false; - } - return $out; - } - - /** - * @return string - */ - public function __toString(): string - { - return $this->toUrl(); - } - - /** - * @param SignatureMethod $signatureMethod - * @param Consumer $consumer - * @param Token $token - */ - public function signRequest( - SignatureMethod $signatureMethod, - Consumer $consumer, - Token $token = null - ) { - $this->setParameter( - 'oauth_signature_method', - $signatureMethod->getName() - ); - $signature = $this->buildSignature($signatureMethod, $consumer, $token); - $this->setParameter('oauth_signature', $signature); - } - - /** - * @param SignatureMethod $signatureMethod - * @param Consumer $consumer - * @param Token $token - * - * @return string - */ - public function buildSignature( - SignatureMethod $signatureMethod, - Consumer $consumer, - Token $token = null - ): string { - return $signatureMethod->buildSignature($this, $consumer, $token); - } - - /** - * @return string - */ - public static function generateNonce(): string - { - return md5(microtime() . mt_rand()); - } -} diff --git a/twitter/vendor/abraham/twitteroauth/src/Response.php b/twitter/vendor/abraham/twitteroauth/src/Response.php deleted file mode 100644 index 1d5af5f0c..000000000 --- a/twitter/vendor/abraham/twitteroauth/src/Response.php +++ /dev/null @@ -1,109 +0,0 @@ - - */ -class Response -{ - /** @var string|null API path from the most recent request */ - private $apiPath; - /** @var int HTTP status code from the most recent request */ - private $httpCode = 0; - /** @var array HTTP headers from the most recent request */ - private $headers = []; - /** @var array|object Response body from the most recent request */ - private $body = []; - /** @var array HTTP headers from the most recent request that start with X */ - private $xHeaders = []; - - /** - * @param string $apiPath - */ - public function setApiPath(string $apiPath): void - { - $this->apiPath = $apiPath; - } - - /** - * @return string|null - */ - public function getApiPath(): ?string - { - return $this->apiPath; - } - - /** - * @param array|object $body - */ - public function setBody($body) - { - $this->body = $body; - } - - /** - * @return array|object|string - */ - public function getBody() - { - return $this->body; - } - - /** - * @param int $httpCode - */ - public function setHttpCode(int $httpCode): void - { - $this->httpCode = $httpCode; - } - - /** - * @return int - */ - public function getHttpCode(): int - { - return $this->httpCode; - } - - /** - * @param array $headers - */ - public function setHeaders(array $headers): void - { - foreach ($headers as $key => $value) { - if (substr($key, 0, 1) == 'x') { - $this->xHeaders[$key] = $value; - } - } - $this->headers = $headers; - } - - /** - * @return array - */ - public function getsHeaders(): array - { - return $this->headers; - } - - /** - * @param array $xHeaders - */ - public function setXHeaders(array $xHeaders = []): void - { - $this->xHeaders = $xHeaders; - } - - /** - * @return array - */ - public function getXHeaders(): array - { - return $this->xHeaders; - } -} diff --git a/twitter/vendor/abraham/twitteroauth/src/SignatureMethod.php b/twitter/vendor/abraham/twitteroauth/src/SignatureMethod.php deleted file mode 100644 index 9d726e8b5..000000000 --- a/twitter/vendor/abraham/twitteroauth/src/SignatureMethod.php +++ /dev/null @@ -1,78 +0,0 @@ -buildSignature($request, $consumer, $token); - - // Check for zero length, although unlikely here - if (strlen($built) == 0 || strlen($signature) == 0) { - return false; - } - - if (strlen($built) != strlen($signature)) { - return false; - } - - // Avoid a timing leak with a (hopefully) time insensitive compare - $result = 0; - for ($i = 0; $i < strlen($signature); $i++) { - $result |= ord($built[$i]) ^ ord($signature[$i]); - } - - return $result == 0; - } -} diff --git a/twitter/vendor/abraham/twitteroauth/src/Token.php b/twitter/vendor/abraham/twitteroauth/src/Token.php deleted file mode 100644 index 2e87aad77..000000000 --- a/twitter/vendor/abraham/twitteroauth/src/Token.php +++ /dev/null @@ -1,43 +0,0 @@ -key = $key; - $this->secret = $secret; - } - - /** - * Generates the basic string serialization of a token that a server - * would respond to request_token and access_token calls with - * - * @return string - */ - public function __toString(): string - { - return sprintf( - 'oauth_token=%s&oauth_token_secret=%s', - Util::urlencodeRfc3986($this->key), - Util::urlencodeRfc3986($this->secret) - ); - } -} diff --git a/twitter/vendor/abraham/twitteroauth/src/TwitterOAuth.php b/twitter/vendor/abraham/twitteroauth/src/TwitterOAuth.php deleted file mode 100644 index 9303d3daa..000000000 --- a/twitter/vendor/abraham/twitteroauth/src/TwitterOAuth.php +++ /dev/null @@ -1,727 +0,0 @@ - - */ -class TwitterOAuth extends Config -{ - private const API_VERSION = '1.1'; - private const API_HOST = 'https://api.twitter.com'; - private const UPLOAD_HOST = 'https://upload.twitter.com'; - - /** @var Response details about the result of the last request */ - private $response; - /** @var string|null Application bearer token */ - private $bearer; - /** @var Consumer Twitter application details */ - private $consumer; - /** @var Token|null User access token details */ - private $token; - /** @var HmacSha1 OAuth 1 signature type used by Twitter */ - private $signatureMethod; - /** @var int Number of attempts we made for the request */ - private $attempts = 0; - - /** - * Constructor - * - * @param string $consumerKey The Application Consumer Key - * @param string $consumerSecret The Application Consumer Secret - * @param string|null $oauthToken The Client Token (optional) - * @param string|null $oauthTokenSecret The Client Token Secret (optional) - */ - public function __construct( - string $consumerKey, - string $consumerSecret, - ?string $oauthToken = null, - ?string $oauthTokenSecret = null - ) { - $this->resetLastResponse(); - $this->signatureMethod = new HmacSha1(); - $this->consumer = new Consumer($consumerKey, $consumerSecret); - if (!empty($oauthToken) && !empty($oauthTokenSecret)) { - $this->setOauthToken($oauthToken, $oauthTokenSecret); - } - if (empty($oauthToken) && !empty($oauthTokenSecret)) { - $this->setBearer($oauthTokenSecret); - } - } - - /** - * @param string $oauthToken - * @param string $oauthTokenSecret - */ - public function setOauthToken( - string $oauthToken, - string $oauthTokenSecret - ): void { - $this->token = new Token($oauthToken, $oauthTokenSecret); - $this->bearer = null; - } - - /** - * @param string $oauthTokenSecret - */ - public function setBearer(string $oauthTokenSecret): void - { - $this->bearer = $oauthTokenSecret; - $this->token = null; - } - - /** - * @return string|null - */ - public function getLastApiPath(): ?string - { - return $this->response->getApiPath(); - } - - /** - * @return int - */ - public function getLastHttpCode(): int - { - return $this->response->getHttpCode(); - } - - /** - * @return array - */ - public function getLastXHeaders(): array - { - return $this->response->getXHeaders(); - } - - /** - * @return array|object|null - */ - public function getLastBody() - { - return $this->response->getBody(); - } - - /** - * Resets the last response cache. - */ - public function resetLastResponse(): void - { - $this->response = new Response(); - } - - /** - * Resets the attempts number. - */ - private function resetAttemptsNumber(): void - { - $this->attempts = 0; - } - - /** - * Delays the retries when they're activated. - */ - private function sleepIfNeeded(): void - { - if ($this->maxRetries && $this->attempts) { - sleep($this->retriesDelay); - } - } - - /** - * Make URLs for user browser navigation. - * - * @param string $path - * @param array $parameters - * - * @return string - */ - public function url(string $path, array $parameters): string - { - $this->resetLastResponse(); - $this->response->setApiPath($path); - $query = http_build_query($parameters); - return sprintf('%s/%s?%s', self::API_HOST, $path, $query); - } - - /** - * Make /oauth/* requests to the API. - * - * @param string $path - * @param array $parameters - * - * @return array - * @throws TwitterOAuthException - */ - public function oauth(string $path, array $parameters = []): array - { - $response = []; - $this->resetLastResponse(); - $this->response->setApiPath($path); - $url = sprintf('%s/%s', self::API_HOST, $path); - $result = $this->oAuthRequest($url, 'POST', $parameters); - - if ($this->getLastHttpCode() != 200) { - throw new TwitterOAuthException($result); - } - - parse_str($result, $response); - $this->response->setBody($response); - - return $response; - } - - /** - * Make /oauth2/* requests to the API. - * - * @param string $path - * @param array $parameters - * - * @return array|object - */ - public function oauth2(string $path, array $parameters = []) - { - $method = 'POST'; - $this->resetLastResponse(); - $this->response->setApiPath($path); - $url = sprintf('%s/%s', self::API_HOST, $path); - $request = Request::fromConsumerAndToken( - $this->consumer, - $this->token, - $method, - $url, - $parameters - ); - $authorization = - 'Authorization: Basic ' . - $this->encodeAppAuthorization($this->consumer); - $result = $this->request( - $request->getNormalizedHttpUrl(), - $method, - $authorization, - $parameters - ); - $response = JsonDecoder::decode($result, $this->decodeJsonAsArray); - $this->response->setBody($response); - return $response; - } - - /** - * Make GET requests to the API. - * - * @param string $path - * @param array $parameters - * - * @return array|object - */ - public function get(string $path, array $parameters = []) - { - return $this->http('GET', self::API_HOST, $path, $parameters, false); - } - - /** - * Make POST requests to the API. - * - * @param string $path - * @param array $parameters - * @param bool $json - * - * @return array|object - */ - public function post( - string $path, - array $parameters = [], - bool $json = false - ) { - return $this->http('POST', self::API_HOST, $path, $parameters, $json); - } - - /** - * Make DELETE requests to the API. - * - * @param string $path - * @param array $parameters - * - * @return array|object - */ - public function delete(string $path, array $parameters = []) - { - return $this->http('DELETE', self::API_HOST, $path, $parameters, false); - } - - /** - * Make PUT requests to the API. - * - * @param string $path - * @param array $parameters - * - * @return array|object - */ - public function put(string $path, array $parameters = []) - { - return $this->http('PUT', self::API_HOST, $path, $parameters, false); - } - - /** - * Upload media to upload.twitter.com. - * - * @param string $path - * @param array $parameters - * @param boolean $chunked - * - * @return array|object - */ - public function upload( - string $path, - array $parameters = [], - bool $chunked = false - ) { - if ($chunked) { - return $this->uploadMediaChunked($path, $parameters); - } else { - return $this->uploadMediaNotChunked($path, $parameters); - } - } - - /** - * Progression of media upload - * - * @param string $media_id - * - * @return array|object - */ - public function mediaStatus(string $media_id) - { - return $this->http( - 'GET', - self::UPLOAD_HOST, - 'media/upload', - [ - 'command' => 'STATUS', - 'media_id' => $media_id, - ], - false - ); - } - - /** - * Private method to upload media (not chunked) to upload.twitter.com. - * - * @param string $path - * @param array $parameters - * - * @return array|object - */ - private function uploadMediaNotChunked(string $path, array $parameters) - { - if ( - !is_readable($parameters['media']) || - ($file = file_get_contents($parameters['media'])) === false - ) { - throw new \InvalidArgumentException( - 'You must supply a readable file' - ); - } - $parameters['media'] = base64_encode($file); - return $this->http( - 'POST', - self::UPLOAD_HOST, - $path, - $parameters, - false - ); - } - - /** - * Private method to upload media (chunked) to upload.twitter.com. - * - * @param string $path - * @param array $parameters - * - * @return array|object - */ - private function uploadMediaChunked(string $path, array $parameters) - { - $init = $this->http( - 'POST', - self::UPLOAD_HOST, - $path, - $this->mediaInitParameters($parameters), - false - ); - // Append - $segmentIndex = 0; - $media = fopen($parameters['media'], 'rb'); - while (!feof($media)) { - $this->http( - 'POST', - self::UPLOAD_HOST, - 'media/upload', - [ - 'command' => 'APPEND', - 'media_id' => $init->media_id_string, - 'segment_index' => $segmentIndex++, - 'media_data' => base64_encode( - fread($media, $this->chunkSize) - ), - ], - false - ); - } - fclose($media); - // Finalize - $finalize = $this->http( - 'POST', - self::UPLOAD_HOST, - 'media/upload', - [ - 'command' => 'FINALIZE', - 'media_id' => $init->media_id_string, - ], - false - ); - return $finalize; - } - - /** - * Private method to get params for upload media chunked init. - * Twitter docs: https://dev.twitter.com/rest/reference/post/media/upload-init.html - * - * @param array $parameters - * - * @return array - */ - private function mediaInitParameters(array $parameters): array - { - $allowed_keys = [ - 'media_type', - 'additional_owners', - 'media_category', - 'shared', - ]; - $base = [ - 'command' => 'INIT', - 'total_bytes' => filesize($parameters['media']), - ]; - $allowed_parameters = array_intersect_key( - $parameters, - array_flip($allowed_keys) - ); - return array_merge($base, $allowed_parameters); - } - - /** - * Cleanup any parameters that are known not to work. - * - * @param array $parameters - * - * @return array - */ - private function cleanUpParameters(array $parameters) - { - foreach ($parameters as $key => $value) { - // PHP coerces `true` to `"1"` which some Twitter APIs don't like. - if (is_bool($value)) { - $parameters[$key] = var_export($value, true); - } - } - return $parameters; - } - - /** - * @param string $method - * @param string $host - * @param string $path - * @param array $parameters - * @param bool $json - * - * @return array|object - */ - private function http( - string $method, - string $host, - string $path, - array $parameters, - bool $json - ) { - $this->resetLastResponse(); - $this->resetAttemptsNumber(); - $url = sprintf('%s/%s/%s.json', $host, self::API_VERSION, $path); - $this->response->setApiPath($path); - if (!$json) { - $parameters = $this->cleanUpParameters($parameters); - } - return $this->makeRequests($url, $method, $parameters, $json); - } - - /** - * - * Make requests and retry them (if enabled) in case of Twitter's problems. - * - * @param string $method - * @param string $url - * @param string $method - * @param array $parameters - * @param bool $json - * - * @return array|object - */ - private function makeRequests( - string $url, - string $method, - array $parameters, - bool $json - ) { - do { - $this->sleepIfNeeded(); - $result = $this->oAuthRequest($url, $method, $parameters, $json); - $response = JsonDecoder::decode($result, $this->decodeJsonAsArray); - $this->response->setBody($response); - $this->attempts++; - // Retry up to our $maxRetries number if we get errors greater than 500 (over capacity etc) - } while ($this->requestsAvailable()); - - return $response; - } - - /** - * Checks if we have to retry request if API is down. - * - * @return bool - */ - private function requestsAvailable(): bool - { - return $this->maxRetries && - $this->attempts <= $this->maxRetries && - $this->getLastHttpCode() >= 500; - } - - /** - * Format and sign an OAuth / API request - * - * @param string $url - * @param string $method - * @param array $parameters - * @param bool $json - * - * @return string - * @throws TwitterOAuthException - */ - private function oAuthRequest( - string $url, - string $method, - array $parameters, - bool $json = false - ) { - $request = Request::fromConsumerAndToken( - $this->consumer, - $this->token, - $method, - $url, - $parameters, - $json - ); - if (array_key_exists('oauth_callback', $parameters)) { - // Twitter doesn't like oauth_callback as a parameter. - unset($parameters['oauth_callback']); - } - if ($this->bearer === null) { - $request->signRequest( - $this->signatureMethod, - $this->consumer, - $this->token - ); - $authorization = $request->toHeader(); - if (array_key_exists('oauth_verifier', $parameters)) { - // Twitter doesn't always work with oauth in the body and in the header - // and it's already included in the $authorization header - unset($parameters['oauth_verifier']); - } - } else { - $authorization = 'Authorization: Bearer ' . $this->bearer; - } - return $this->request( - $request->getNormalizedHttpUrl(), - $method, - $authorization, - $parameters, - $json - ); - } - - /** - * Set Curl options. - * - * @return array - */ - private function curlOptions(): array - { - $bundlePath = CaBundle::getSystemCaRootBundlePath(); - $options = [ - // CURLOPT_VERBOSE => true, - CURLOPT_CONNECTTIMEOUT => $this->connectionTimeout, - CURLOPT_HEADER => true, - CURLOPT_RETURNTRANSFER => true, - CURLOPT_SSL_VERIFYHOST => 2, - CURLOPT_SSL_VERIFYPEER => true, - CURLOPT_TIMEOUT => $this->timeout, - CURLOPT_USERAGENT => $this->userAgent, - $this->curlCaOpt($bundlePath) => $bundlePath, - ]; - - if ($this->gzipEncoding) { - $options[CURLOPT_ENCODING] = 'gzip'; - } - - if (!empty($this->proxy)) { - $options[CURLOPT_PROXY] = $this->proxy['CURLOPT_PROXY']; - $options[CURLOPT_PROXYUSERPWD] = - $this->proxy['CURLOPT_PROXYUSERPWD']; - $options[CURLOPT_PROXYPORT] = $this->proxy['CURLOPT_PROXYPORT']; - $options[CURLOPT_PROXYAUTH] = CURLAUTH_BASIC; - $options[CURLOPT_PROXYTYPE] = CURLPROXY_HTTP; - } - - return $options; - } - - /** - * Make an HTTP request - * - * @param string $url - * @param string $method - * @param string $authorization - * @param array $postfields - * @param bool $json - * - * @return string - * @throws TwitterOAuthException - */ - private function request( - string $url, - string $method, - string $authorization, - array $postfields, - bool $json = false - ): string { - $options = $this->curlOptions(); - $options[CURLOPT_URL] = $url; - $options[CURLOPT_HTTPHEADER] = [ - 'Accept: application/json', - $authorization, - 'Expect:', - ]; - - switch ($method) { - case 'GET': - break; - case 'POST': - $options[CURLOPT_POST] = true; - if ($json) { - $options[CURLOPT_HTTPHEADER][] = - 'Content-type: application/json'; - $options[CURLOPT_POSTFIELDS] = json_encode($postfields); - } else { - $options[CURLOPT_POSTFIELDS] = Util::buildHttpQuery( - $postfields - ); - } - break; - case 'DELETE': - $options[CURLOPT_CUSTOMREQUEST] = 'DELETE'; - break; - case 'PUT': - $options[CURLOPT_CUSTOMREQUEST] = 'PUT'; - break; - } - - if ( - in_array($method, ['GET', 'PUT', 'DELETE']) && - !empty($postfields) - ) { - $options[CURLOPT_URL] .= '?' . Util::buildHttpQuery($postfields); - } - - $curlHandle = curl_init(); - curl_setopt_array($curlHandle, $options); - $response = curl_exec($curlHandle); - - // Throw exceptions on cURL errors. - if (curl_errno($curlHandle) > 0) { - $error = curl_error($curlHandle); - $errorNo = curl_errno($curlHandle); - curl_close($curlHandle); - throw new TwitterOAuthException($error, $errorNo); - } - - $this->response->setHttpCode( - curl_getinfo($curlHandle, CURLINFO_HTTP_CODE) - ); - $parts = explode("\r\n\r\n", $response); - $responseBody = array_pop($parts); - $responseHeader = array_pop($parts); - $this->response->setHeaders($this->parseHeaders($responseHeader)); - - curl_close($curlHandle); - - return $responseBody; - } - - /** - * Get the header info to store. - * - * @param string $header - * - * @return array - */ - private function parseHeaders(string $header): array - { - $headers = []; - foreach (explode("\r\n", $header) as $line) { - if (strpos($line, ':') !== false) { - [$key, $value] = explode(': ', $line); - $key = str_replace('-', '_', strtolower($key)); - $headers[$key] = trim($value); - } - } - return $headers; - } - - /** - * Encode application authorization header with base64. - * - * @param Consumer $consumer - * - * @return string - */ - private function encodeAppAuthorization(Consumer $consumer): string - { - $key = rawurlencode($consumer->key); - $secret = rawurlencode($consumer->secret); - return base64_encode($key . ':' . $secret); - } - - /** - * Get Curl CA option based on whether the given path is a directory or file. - * - * @param string $path - * @return int - */ - private function curlCaOpt(string $path): int - { - return is_dir($path) ? CURLOPT_CAPATH : CURLOPT_CAINFO; - } -} diff --git a/twitter/vendor/abraham/twitteroauth/src/TwitterOAuthException.php b/twitter/vendor/abraham/twitteroauth/src/TwitterOAuthException.php deleted file mode 100644 index 03b8e3e98..000000000 --- a/twitter/vendor/abraham/twitteroauth/src/TwitterOAuthException.php +++ /dev/null @@ -1,12 +0,0 @@ - - */ -class TwitterOAuthException extends \Exception -{ -} diff --git a/twitter/vendor/abraham/twitteroauth/src/Util.php b/twitter/vendor/abraham/twitteroauth/src/Util.php deleted file mode 100644 index b1c09a950..000000000 --- a/twitter/vendor/abraham/twitteroauth/src/Util.php +++ /dev/null @@ -1,122 +0,0 @@ - array('b','c'), 'd' => 'e') - * - * @param string $input - * - * @return array - */ - public static function parseParameters($input): array - { - if (!is_string($input)) { - return []; - } - - $pairs = explode('&', $input); - - $parameters = []; - foreach ($pairs as $pair) { - $split = explode('=', $pair, 2); - $parameter = Util::urldecodeRfc3986($split[0]); - $value = isset($split[1]) ? Util::urldecodeRfc3986($split[1]) : ''; - - if (isset($parameters[$parameter])) { - // We have already recieved parameter(s) with this name, so add to the list - // of parameters with this name - - if (is_scalar($parameters[$parameter])) { - // This is the first duplicate, so transform scalar (string) into an array - // so we can add the duplicates - $parameters[$parameter] = [$parameters[$parameter]]; - } - - $parameters[$parameter][] = $value; - } else { - $parameters[$parameter] = $value; - } - } - return $parameters; - } - - /** - * @param array $params - * - * @return string - */ - public static function buildHttpQuery(array $params): string - { - if (empty($params)) { - return ''; - } - - // Urlencode both keys and values - $keys = Util::urlencodeRfc3986(array_keys($params)); - $values = Util::urlencodeRfc3986(array_values($params)); - $params = array_combine($keys, $values); - - // Parameters are sorted by name, using lexicographical byte value ordering. - // Ref: Spec: 9.1.1 (1) - uksort($params, 'strcmp'); - - $pairs = []; - foreach ($params as $parameter => $value) { - if (is_array($value)) { - // If two or more parameters share the same name, they are sorted by their value - // Ref: Spec: 9.1.1 (1) - // June 12th, 2010 - changed to sort because of issue 164 by hidetaka - sort($value, SORT_STRING); - foreach ($value as $duplicateValue) { - $pairs[] = $parameter . '=' . $duplicateValue; - } - } else { - $pairs[] = $parameter . '=' . $value; - } - } - // For each parameter, the name is separated from the corresponding value by an '=' character (ASCII code 61) - // Each name-value pair is separated by an '&' character (ASCII code 38) - return implode('&', $pairs); - } -} diff --git a/twitter/vendor/abraham/twitteroauth/src/Util/JsonDecoder.php b/twitter/vendor/abraham/twitteroauth/src/Util/JsonDecoder.php deleted file mode 100644 index 989f34068..000000000 --- a/twitter/vendor/abraham/twitteroauth/src/Util/JsonDecoder.php +++ /dev/null @@ -1,29 +0,0 @@ - - */ -class JsonDecoder -{ - /** - * Decodes a JSON string to stdObject or associative array - * - * @param string $string - * @param bool $asArray - * - * @return array|object - */ - public static function decode(string $string, bool $asArray) - { - if ( - version_compare(PHP_VERSION, '5.4.0', '>=') && - !(defined('JSON_C_VERSION') && PHP_INT_SIZE > 4) - ) { - return json_decode($string, $asArray, 512, JSON_BIGINT_AS_STRING); - } - - return json_decode($string, $asArray); - } -} diff --git a/twitter/vendor/abraham/twitteroauth/tests/AbstractSignatureMethodTest.php b/twitter/vendor/abraham/twitteroauth/tests/AbstractSignatureMethodTest.php deleted file mode 100644 index b390620ec..000000000 --- a/twitter/vendor/abraham/twitteroauth/tests/AbstractSignatureMethodTest.php +++ /dev/null @@ -1,60 +0,0 @@ -assertEquals($this->name, $this->getClass()->getName()); - } - - /** - * @dataProvider signatureDataProvider - */ - public function testBuildSignature($expected, $request, $consumer, $token) - { - $this->assertEquals( - $expected, - $this->getClass()->buildSignature($request, $consumer, $token) - ); - } - - protected function getRequest() - { - return $this->getMockBuilder('Abraham\TwitterOAuth\Request') - ->disableOriginalConstructor() - ->getMock(); - } - - protected function getConsumer( - $key = null, - $secret = null, - $callbackUrl = null - ) { - return $this->getMockBuilder('Abraham\TwitterOAuth\Consumer') - ->setConstructorArgs([$key, $secret, $callbackUrl]) - ->getMock(); - } - - protected function getToken($key = null, $secret = null) - { - return $this->getMockBuilder('Abraham\TwitterOAuth\Token') - ->setConstructorArgs([$key, $secret]) - ->getMock(); - } -} diff --git a/twitter/vendor/abraham/twitteroauth/tests/ConsumerTest.php b/twitter/vendor/abraham/twitteroauth/tests/ConsumerTest.php deleted file mode 100644 index 18a1de01b..000000000 --- a/twitter/vendor/abraham/twitteroauth/tests/ConsumerTest.php +++ /dev/null @@ -1,23 +0,0 @@ -assertEquals( - "Consumer[key=$key,secret=$secret]", - $consumer->__toString() - ); - } -} diff --git a/twitter/vendor/abraham/twitteroauth/tests/HmacSha1Test.php b/twitter/vendor/abraham/twitteroauth/tests/HmacSha1Test.php deleted file mode 100644 index cd7887ed8..000000000 --- a/twitter/vendor/abraham/twitteroauth/tests/HmacSha1Test.php +++ /dev/null @@ -1,47 +0,0 @@ -getRequest(), - $this->getConsumer(), - $this->getToken(), - ], - [ - 'EBw0gHngam3BTx8kfPfNNSyKem4=', - $this->getRequest(), - $this->getConsumer('key', 'secret'), - $this->getToken(), - ], - [ - 'kDsHFZzws2a5M6cAQjfpdNBo+v8=', - $this->getRequest(), - $this->getConsumer('key', 'secret'), - $this->getToken('key', 'secret'), - ], - [ - 'EBw0gHngam3BTx8kfPfNNSyKem4=', - $this->getRequest(), - $this->getConsumer('key', 'secret'), - null, - ], - ]; - } -} diff --git a/twitter/vendor/abraham/twitteroauth/tests/TokenTest.php b/twitter/vendor/abraham/twitteroauth/tests/TokenTest.php deleted file mode 100644 index 1863676e8..000000000 --- a/twitter/vendor/abraham/twitteroauth/tests/TokenTest.php +++ /dev/null @@ -1,38 +0,0 @@ -assertEquals($expected, $token->__toString()); - } - - public function tokenProvider() - { - return [ - ['oauth_token=key&oauth_token_secret=secret', 'key', 'secret'], - [ - 'oauth_token=key%2Bkey&oauth_token_secret=secret', - 'key+key', - 'secret', - ], - [ - 'oauth_token=key~key&oauth_token_secret=secret', - 'key~key', - 'secret', - ], - ]; - } -} diff --git a/twitter/vendor/abraham/twitteroauth/tests/TwitterOAuthTest.php b/twitter/vendor/abraham/twitteroauth/tests/TwitterOAuthTest.php deleted file mode 100644 index 00244e1fd..000000000 --- a/twitter/vendor/abraham/twitteroauth/tests/TwitterOAuthTest.php +++ /dev/null @@ -1,397 +0,0 @@ -twitter = new TwitterOAuth( - CONSUMER_KEY, - CONSUMER_SECRET, - ACCESS_TOKEN, - ACCESS_TOKEN_SECRET - ); - $this->userId = explode('-', ACCESS_TOKEN)[0]; - } - - public function testBuildClient() - { - $this->assertObjectHasAttribute('consumer', $this->twitter); - $this->assertObjectHasAttribute('token', $this->twitter); - } - - /** - * @vcr testSetOauthToken.json - */ - public function testSetOauthToken() - { - $twitter = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET); - $twitter->setOauthToken(ACCESS_TOKEN, ACCESS_TOKEN_SECRET); - $this->assertObjectHasAttribute('consumer', $twitter); - $this->assertObjectHasAttribute('token', $twitter); - $twitter->get('friendships/show', [ - 'target_screen_name' => 'twitterapi', - ]); - $this->assertEquals(200, $twitter->getLastHttpCode()); - } - - /** - * @vcr testOauth2Token.json - */ - public function testOauth2Token() - { - $twitter = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET); - $result = $twitter->oauth2('oauth2/token', [ - 'grant_type' => 'client_credentials', - ]); - $this->assertEquals(200, $twitter->getLastHttpCode()); - $this->assertObjectHasAttribute('token_type', $result); - $this->assertObjectHasAttribute('access_token', $result); - $this->assertEquals('bearer', $result->token_type); - return $result; - } - - /** - * @depends testOauth2Token - * @vcr testOauth2BearerToken.json - */ - public function testOauth2BearerToken($accessToken) - { - $twitter = new TwitterOAuth( - CONSUMER_KEY, - CONSUMER_SECRET, - null, - $accessToken->access_token - ); - $result = $twitter->get('statuses/user_timeline', [ - 'screen_name' => 'twitterapi', - ]); - $this->assertEquals(200, $twitter->getLastHttpCode()); - return $accessToken; - } - - /** - * @depends testOauth2BearerToken - * @vcr testOauth2TokenInvalidate.json - */ - public function testOauth2TokenInvalidate($accessToken) - { - $twitter = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET); - // HACK: access_token is already urlencoded but gets urlencoded again breaking the invalidate request. - $result = $twitter->oauth2('oauth2/invalidate_token', [ - 'access_token' => urldecode($accessToken->access_token), - ]); - $this->assertEquals(200, $twitter->getLastHttpCode()); - $this->assertObjectHasAttribute('access_token', $result); - } - - /** - * @vcr testOauthRequestToken.json - */ - public function testOauthRequestToken() - { - $twitter = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET); - $result = $twitter->oauth('oauth/request_token', [ - 'oauth_callback' => OAUTH_CALLBACK, - ]); - $this->assertEquals(200, $twitter->getLastHttpCode()); - $this->assertArrayHasKey('oauth_token', $result); - $this->assertArrayHasKey('oauth_token_secret', $result); - $this->assertArrayHasKey('oauth_callback_confirmed', $result); - $this->assertEquals('true', $result['oauth_callback_confirmed']); - return $result; - } - - /** - * @vcr testOauthRequestTokenException.json - */ - public function testOauthRequestTokenException() - { - $this->expectException( - \Abraham\TwitterOAuth\TwitterOAuthException::class - ); - $this->expectErrorMessage('Could not authenticate you'); - $twitter = new TwitterOAuth('CONSUMER_KEY', 'CONSUMER_SECRET'); - $result = $twitter->oauth('oauth/request_token', [ - 'oauth_callback' => OAUTH_CALLBACK, - ]); - } - - /** - * @depends testOauthRequestToken - * @vcr testOauthAccessTokenTokenException.json - */ - public function testOauthAccessTokenTokenException(array $requestToken) - { - // Can't test this without a browser logging into Twitter so check for the correct error instead. - $this->expectException( - \Abraham\TwitterOAuth\TwitterOAuthException::class - ); - $this->expectErrorMessage('Invalid oauth_verifier parameter'); - $twitter = new TwitterOAuth( - CONSUMER_KEY, - CONSUMER_SECRET, - $requestToken['oauth_token'], - $requestToken['oauth_token_secret'] - ); - $twitter->oauth('oauth/access_token', [ - 'oauth_verifier' => 'fake_oauth_verifier', - ]); - } - - public function testUrl() - { - $url = $this->twitter->url('oauth/authorize', [ - 'foo' => 'bar', - 'baz' => 'qux', - ]); - $this->assertEquals( - 'https://api.twitter.com/oauth/authorize?foo=bar&baz=qux', - $url - ); - } - - /** - * @vcr testGetAccountVerifyCredentials.json - */ - public function testGetAccountVerifyCredentials() - { - $user = $this->twitter->get('account/verify_credentials', [ - 'include_entities' => false, - 'include_email' => true, - ]); - $this->assertEquals(200, $this->twitter->getLastHttpCode()); - $this->assertObjectHasAttribute('email', $user); - } - - /** - * @vcr testSetProxy.json - */ - public function testSetProxy() - { - $this->twitter->setProxy([ - 'CURLOPT_PROXY' => PROXY, - 'CURLOPT_PROXYUSERPWD' => PROXYUSERPWD, - 'CURLOPT_PROXYPORT' => PROXYPORT, - ]); - $this->twitter->setTimeouts(60, 60); - $result = $this->twitter->get('account/verify_credentials'); - $this->assertEquals(200, $this->twitter->getLastHttpCode()); - $this->assertObjectHasAttribute('id', $result); - } - - /** - * @vcr testGetStatusesMentionsTimeline.json - */ - public function testGetStatusesMentionsTimeline() - { - $this->twitter->get('statuses/mentions_timeline'); - $this->assertEquals(200, $this->twitter->getLastHttpCode()); - } - - /** - * @vcr testGetSearchTweets.json - */ - public function testGetSearchTweets() - { - $result = $this->twitter->get('search/tweets', ['q' => 'twitter']); - $this->assertEquals(200, $this->twitter->getLastHttpCode()); - return $result->statuses; - } - - /** - * @depends testGetSearchTweets - * @vcr testGetSearchTweetsWithMaxId.json - */ - public function testGetSearchTweetsWithMaxId($statuses) - { - $maxId = array_pop($statuses)->id_str; - $this->twitter->get('search/tweets', [ - 'q' => 'twitter', - 'max_id' => $maxId, - ]); - $this->assertEquals(200, $this->twitter->getLastHttpCode()); - } - - /** - * @vcr testPostFavoritesCreate.json - */ - public function testPostFavoritesCreate() - { - $result = $this->twitter->post('favorites/create', [ - 'id' => '6242973112', - ]); - $this->assertEquals(200, $this->twitter->getLastHttpCode()); - } - - /** - * @depends testPostFavoritesCreate - * @vcr testPostFavoritesDestroy.json - */ - public function testPostFavoritesDestroy() - { - $this->twitter->post('favorites/destroy', ['id' => '6242973112']); - $this->assertEquals(200, $this->twitter->getLastHttpCode()); - } - - /** - * @vcr testPostDirectMessagesEventsNew.json - */ - public function testPostDirectMessagesEventsNew() - { - $data = [ - 'event' => [ - 'type' => 'message_create', - 'message_create' => [ - 'target' => [ - 'recipient_id' => $this->userId, - ], - 'message_data' => [ - 'text' => 'Hello World!', - ], - ], - ], - ]; - $result = $this->twitter->post( - 'direct_messages/events/new', - $data, - true - ); - $this->assertEquals(200, $this->twitter->getLastHttpCode()); - return $result; - } - - /** - * @depends testPostDirectMessagesEventsNew - * @vcr testDeleteDirectMessagesEventsDestroy.json - */ - public function testDeleteDirectMessagesEventsDestroy($message) - { - $this->twitter->delete('direct_messages/events/destroy', [ - 'id' => $message->event->id, - ]); - $this->assertEquals(204, $this->twitter->getLastHttpCode()); - } - - /** - * @vcr testPostStatusesUpdateWithMedia.json - */ - public function testPostStatusesUpdateWithMedia() - { - $this->twitter->setTimeouts(60, 60); - // Image source https://www.flickr.com/photos/titrans/8548825587/ - $file_path = __DIR__ . '/kitten.jpg'; - $result = $this->twitter->upload('media/upload', [ - 'media' => $file_path, - ]); - $this->assertEquals(200, $this->twitter->getLastHttpCode()); - $this->assertObjectHasAttribute('media_id_string', $result); - $parameters = [ - 'status' => 'Hello World ' . MOCK_TIME, - 'media_ids' => $result->media_id_string, - ]; - $result = $this->twitter->post('statuses/update', $parameters); - $this->assertEquals(200, $this->twitter->getLastHttpCode()); - $result = $this->twitter->post('statuses/destroy/' . $result->id_str); - return $result; - } - - /** - * @vcr testPostStatusUpdateWithInvalidMediaThrowsException.json - */ - public function testPostStatusUpdateWithInvalidMediaThrowsException() - { - $this->expectException(\InvalidArgumentException::class); - $file_path = __DIR__ . '/12345678900987654321.jpg'; - $this->assertFalse(\is_readable($file_path)); - $result = $this->twitter->upload('media/upload', [ - 'media' => $file_path, - ]); - } - - /** - * @vcr testPostStatusesUpdateWithMediaChunked.json - */ - public function testPostStatusesUpdateWithMediaChunked() - { - $this->twitter->setTimeouts(60, 30); - // Video source http://www.sample-videos.com/ - $file_path = __DIR__ . '/video.mp4'; - $result = $this->twitter->upload( - 'media/upload', - ['media' => $file_path, 'media_type' => 'video/mp4'], - true - ); - $this->assertEquals(201, $this->twitter->getLastHttpCode()); - $this->assertObjectHasAttribute('media_id_string', $result); - $parameters = [ - 'status' => 'Hello World ' . MOCK_TIME, - 'media_ids' => $result->media_id_string, - ]; - $result = $this->twitter->post('statuses/update', $parameters); - $this->assertEquals(200, $this->twitter->getLastHttpCode()); - $result = $this->twitter->post('statuses/destroy/' . $result->id_str); - return $result; - } - - /** - * @vcr testPostStatusesUpdateUtf8.json - */ - public function testPostStatusesUpdateUtf8() - { - $result = $this->twitter->post('statuses/update', [ - 'status' => 'xこんにちは世界 ' . MOCK_TIME, - ]); - $this->assertEquals(200, $this->twitter->getLastHttpCode()); - return $result; - } - - /** - * @depends testPostStatusesUpdateUtf8 - * @vcr testPostStatusesDestroy.json - */ - public function testPostStatusesDestroy($status) - { - $this->twitter->post('statuses/destroy/' . $status->id_str); - $this->assertEquals(200, $this->twitter->getLastHttpCode()); - } - - /** - * @vcr testLastResult.json - */ - public function testLastResult() - { - $this->twitter->get('search/tweets', ['q' => 'twitter']); - $this->assertEquals('search/tweets', $this->twitter->getLastApiPath()); - $this->assertEquals(200, $this->twitter->getLastHttpCode()); - $this->assertObjectHasAttribute( - 'statuses', - $this->twitter->getLastBody() - ); - } - - /** - * @depends testLastResult - * @vcr testResetLastResponse.json - */ - public function testResetLastResponse() - { - $this->twitter->resetLastResponse(); - $this->assertEquals('', $this->twitter->getLastApiPath()); - $this->assertEquals(0, $this->twitter->getLastHttpCode()); - $this->assertEquals([], $this->twitter->getLastBody()); - } -} diff --git a/twitter/vendor/abraham/twitteroauth/tests/Util/JsonDecoderTest.php b/twitter/vendor/abraham/twitteroauth/tests/Util/JsonDecoderTest.php deleted file mode 100644 index dc6fa9707..000000000 --- a/twitter/vendor/abraham/twitteroauth/tests/Util/JsonDecoderTest.php +++ /dev/null @@ -1,54 +0,0 @@ -assertEquals($expected, JsonDecoder::decode($input, $asArray)); - } - - public function jsonProvider() - { - return [ - ['[]', true, []], - ['[1,2,3]', true, [1, 2, 3]], - [ - '[{"id": 556179961825226750}]', - true, - [['id' => 556179961825226750]], - ], - ['[]', false, []], - ['[1,2,3]', false, [1, 2, 3]], - [ - '[{"id": 556179961825226750}]', - false, - [ - $this->getClass(function ($object) { - $object->id = 556179961825226750; - return $object; - }), - ], - ], - ]; - } - - /** - * @param callable $callable - * - * @return stdClass - */ - private function getClass(\Closure $callable) - { - $object = new \stdClass(); - - return $callable($object); - } -} diff --git a/twitter/vendor/abraham/twitteroauth/tests/bootstrap.php b/twitter/vendor/abraham/twitteroauth/tests/bootstrap.php deleted file mode 100644 index 23653e049..000000000 --- a/twitter/vendor/abraham/twitteroauth/tests/bootstrap.php +++ /dev/null @@ -1,10 +0,0 @@ -setStorage('json'); -\VCR\VCR::turnOn(); diff --git a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testDeleteDirectMessagesEventsDestroy.json b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testDeleteDirectMessagesEventsDestroy.json deleted file mode 100644 index b592bc87f..000000000 --- a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testDeleteDirectMessagesEventsDestroy.json +++ /dev/null @@ -1,40 +0,0 @@ -[{ - "request": { - "method": "DELETE", - "url": "https:\/\/api.twitter.com\/1.1\/direct_messages\/events\/destroy.json?id=1254206523385032714", - "headers": { - "Host": "api.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"dY4KEaTg5Y6Bv4JlofNCjoArx%2F4%3D\"", - "Expect": null - } - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=NVQWGYLXFVSG2%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:31:52 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:31:52 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_asAbLVWtv6V2+ARemo0VNA==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:52 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786111220677678; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:52 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "5cbff6bc4105c0040c4738daac7adcf4", - "x-content-type-options": "nosniff", - "x-frame-options": "SAMEORIGIN", - "x-response-time": "37", - "x-transaction": "00f02f6c00e12e76", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "0" - } - } -}] \ No newline at end of file diff --git a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testGetAccountVerifyCredentials.json b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testGetAccountVerifyCredentials.json deleted file mode 100644 index f18db6b3a..000000000 --- a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testGetAccountVerifyCredentials.json +++ /dev/null @@ -1,46 +0,0 @@ -[{ - "request": { - "method": "GET", - "url": "https:\/\/api.twitter.com\/1.1\/account\/verify_credentials.json?include_email=true&include_entities=false", - "headers": { - "Host": "api.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"k8h8edFh9R2W3DCNJy5Nb07tWo0%3D\"", - "Expect": null - } - }, - "response": { - "status": { - "http_version": "2", - "code": "200", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-disposition": "attachment; filename=json.json", - "content-encoding": "gzip", - "content-length": "773", - "content-type": "application\/json;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:31:11 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:31:11 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_PPOKPD3f\/ek9QM3+ySQxjw==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:11 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786107181888587; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:11 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "200 OK", - "strict-transport-security": "max-age=631138519", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "7509696bc24b6d9d09d283b844a3c232", - "x-content-type-options": "nosniff", - "x-frame-options": "SAMEORIGIN", - "x-rate-limit-limit": "75", - "x-rate-limit-remaining": "73", - "x-rate-limit-reset": "1587861613", - "x-response-time": "46", - "x-transaction": "00cd4f6300163d67", - "x-twitter-response-tags": "BouncerExempt, BouncerCompliant", - "x-xss-protection": "0" - }, - "body": "{\"id\":93915746,\"id_str\":\"93915746\",\"name\":\"OAuth Library Test\",\"screen_name\":\"oauthlibtest\",\"location\":\"\",\"description\":\"\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":58,\"friends_count\":2,\"listed_count\":6,\"created_at\":\"Tue Dec 01 18:37:44 +0000 2009\",\"favourites_count\":0,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":5,\"lang\":null,\"status\":{\"created_at\":\"Tue Dec 01 18:38:07 +0000 2009\",\"id\":6242973112,\"id_str\":\"6242973112\",\"text\":\"Test!\",\"truncated\":false,\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web Client\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":2258,\"favorite_count\":75,\"favorited\":false,\"retweeted\":false,\"lang\":\"en\"},\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/sticky\\\/default_profile_images\\\/default_profile_normal.png\",\"profile_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/sticky\\\/default_profile_images\\\/default_profile_normal.png\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":true,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\",\"suspended\":false,\"needs_phone_verification\":false,\"email\":\"4braham+oauthlibtest@gmail.com\"}" - } -}] \ No newline at end of file diff --git a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testGetSearchTweets.json b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testGetSearchTweets.json deleted file mode 100644 index ba77e8826..000000000 --- a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testGetSearchTweets.json +++ /dev/null @@ -1,46 +0,0 @@ -[{ - "request": { - "method": "GET", - "url": "https:\/\/api.twitter.com\/1.1\/search\/tweets.json?q=twitter", - "headers": { - "Host": "api.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"qWYQHV5qw8biySQjoR59V9%2BDvOQ%3D\"", - "Expect": null - } - }, - "response": { - "status": { - "http_version": "2", - "code": "200", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-disposition": "attachment; filename=json.json", - "content-encoding": "gzip", - "content-length": "14711", - "content-type": "application\/json;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:31:50 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:31:50 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_vWXo\/ERa4hzA0P4KdPAVsQ==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:50 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786111008359713; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:50 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "200 OK", - "strict-transport-security": "max-age=631138519", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "79ad7f269cccf2e20522870f41e8f396", - "x-content-type-options": "nosniff", - "x-frame-options": "SAMEORIGIN", - "x-rate-limit-limit": "180", - "x-rate-limit-remaining": "176", - "x-rate-limit-reset": "1587861623", - "x-response-time": "150", - "x-transaction": "0030f8b1004d314d", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "0" - }, - "body": "{\"statuses\":[{\"created_at\":\"Sun Apr 26 00:31:49 +0000 2020\",\"id\":1254206512068734977,\"id_str\":\"1254206512068734977\",\"text\":\"RT @a_albander: \\u0635\\u0648\\u0631\\u0629 \\u062a\\u062d\\u0643\\u064a \\u0627\\u0644\\u0643\\u062b\\u064a\\u0631 .. \\u0641\\u0645\\u0627 \\u0647\\u0648 \\u0627\\u0644\\u062a\\u0639\\u0644\\u064a\\u0642 \\u0627\\u0644\\u0623\\u062c\\u0645\\u0644\\u061f https:\\\/\\\/t.co\\\/GC8VzmAhVs\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"a_albander\",\"name\":\"\\u0639\\u0628\\u062f\\u0627\\u0644\\u0644\\u0647 \\u0627\\u0644\\u0628\\u0646\\u062f\\u0631\",\"id\":248141082,\"id_str\":\"248141082\",\"indices\":[3,14]}],\"urls\":[],\"media\":[{\"id\":1253870173766983690,\"id_str\":\"1253870173766983690\",\"indices\":[59,82],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWakR53WoAo9cdq.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWakR53WoAo9cdq.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/GC8VzmAhVs\",\"display_url\":\"pic.twitter.com\\\/GC8VzmAhVs\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/a_albander\\\/status\\\/1253870189361364994\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"medium\":{\"w\":1127,\"h\":750,\"resize\":\"fit\"},\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"large\":{\"w\":1127,\"h\":750,\"resize\":\"fit\"},\"small\":{\"w\":680,\"h\":453,\"resize\":\"fit\"}},\"source_status_id\":1253870189361364994,\"source_status_id_str\":\"1253870189361364994\",\"source_user_id\":248141082,\"source_user_id_str\":\"248141082\"}]},\"extended_entities\":{\"media\":[{\"id\":1253870173766983690,\"id_str\":\"1253870173766983690\",\"indices\":[59,82],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWakR53WoAo9cdq.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWakR53WoAo9cdq.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/GC8VzmAhVs\",\"display_url\":\"pic.twitter.com\\\/GC8VzmAhVs\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/a_albander\\\/status\\\/1253870189361364994\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"medium\":{\"w\":1127,\"h\":750,\"resize\":\"fit\"},\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"large\":{\"w\":1127,\"h\":750,\"resize\":\"fit\"},\"small\":{\"w\":680,\"h\":453,\"resize\":\"fit\"}},\"source_status_id\":1253870189361364994,\"source_status_id_str\":\"1253870189361364994\",\"source_user_id\":248141082,\"source_user_id_str\":\"248141082\"}]},\"metadata\":{\"iso_language_code\":\"ar\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":2918893818,\"id_str\":\"2918893818\",\"name\":\"Nawaf\",\"screen_name\":\"ff3h1\",\"location\":\"\\u0627\\u0644\\u0645\\u0645\\u0644\\u0643\\u0629 \\u0627\\u0644\\u0639\\u0631\\u0628\\u064a\\u0629 \\u0627\\u0644\\u0633\\u0639\\u0648\\u062f\\u064a\\u0629\",\"description\":\"\\u0641\\u064a \\u0642\\u0627\\u0646\\u0648\\u0646 \\u0643\\u0628\\u0631\\u064a\\u0627\\u0626\\u064a \\u0644\\u0627 \\u0627\\u062d\\u0628 \\u0623\\u0645\\u062a\\u0644\\u0627\\u0643 \\u0627\\u0644\\u0627\\u0634\\u064a\\u0627\\u0621 \\u0627\\u0644\\u0645\\u062a\\u0627\\u062d\\u0629 \\u0644\\u0644\\u062c\\u0645\\u064a\\u0639\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":139,\"friends_count\":483,\"listed_count\":0,\"created_at\":\"Thu Dec 04 19:03:08 +0000 2014\",\"favourites_count\":164,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":3875,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1136978136598552576\\\/j2Xkn-ZI_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1136978136598552576\\\/j2Xkn-ZI_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/2918893818\\\/1575300039\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Sat Apr 25 02:15:23 +0000 2020\",\"id\":1253870189361364994,\"id_str\":\"1253870189361364994\",\"text\":\"\\u0635\\u0648\\u0631\\u0629 \\u062a\\u062d\\u0643\\u064a \\u0627\\u0644\\u0643\\u062b\\u064a\\u0631 .. \\u0641\\u0645\\u0627 \\u0647\\u0648 \\u0627\\u0644\\u062a\\u0639\\u0644\\u064a\\u0642 \\u0627\\u0644\\u0623\\u062c\\u0645\\u0644\\u061f https:\\\/\\\/t.co\\\/GC8VzmAhVs\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[],\"media\":[{\"id\":1253870173766983690,\"id_str\":\"1253870173766983690\",\"indices\":[43,66],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWakR53WoAo9cdq.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWakR53WoAo9cdq.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/GC8VzmAhVs\",\"display_url\":\"pic.twitter.com\\\/GC8VzmAhVs\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/a_albander\\\/status\\\/1253870189361364994\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"medium\":{\"w\":1127,\"h\":750,\"resize\":\"fit\"},\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"large\":{\"w\":1127,\"h\":750,\"resize\":\"fit\"},\"small\":{\"w\":680,\"h\":453,\"resize\":\"fit\"}}}]},\"extended_entities\":{\"media\":[{\"id\":1253870173766983690,\"id_str\":\"1253870173766983690\",\"indices\":[43,66],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWakR53WoAo9cdq.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWakR53WoAo9cdq.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/GC8VzmAhVs\",\"display_url\":\"pic.twitter.com\\\/GC8VzmAhVs\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/a_albander\\\/status\\\/1253870189361364994\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"medium\":{\"w\":1127,\"h\":750,\"resize\":\"fit\"},\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"large\":{\"w\":1127,\"h\":750,\"resize\":\"fit\"},\"small\":{\"w\":680,\"h\":453,\"resize\":\"fit\"}}}]},\"metadata\":{\"iso_language_code\":\"ar\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":248141082,\"id_str\":\"248141082\",\"name\":\"\\u0639\\u0628\\u062f\\u0627\\u0644\\u0644\\u0647 \\u0627\\u0644\\u0628\\u0646\\u062f\\u0631\",\"screen_name\":\"a_albander\",\"location\":\"\",\"description\":\"\\u0645\\u0642\\u062f\\u0645 \\u0633\\u0639\\u0648\\u062f\\u064a \\u0648\\u0635\\u0627\\u0646\\u0639 \\u0645\\u062d\\u062a\\u0648\\u0649 \\u0641\\u064a @SkyNewsArabia\",\"url\":\"https:\\\/\\\/t.co\\\/7oZvCGmDJ8\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/7oZvCGmDJ8\",\"expanded_url\":\"https:\\\/\\\/www.snapchat.com\\\/add\\\/a_albander\",\"display_url\":\"snapchat.com\\\/add\\\/a_albander\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":233052,\"friends_count\":785,\"listed_count\":439,\"created_at\":\"Sun Feb 06 10:17:43 +0000 2011\",\"favourites_count\":472,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":true,\"statuses_count\":8246,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"709397\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme6\\\/bg.gif\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme6\\\/bg.gif\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1252038061355143168\\\/vxQX5Uzc_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1252038061355143168\\\/vxQX5Uzc_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/248141082\\\/1587760417\",\"profile_link_color\":\"FF3300\",\"profile_sidebar_border_color\":\"86A4A6\",\"profile_sidebar_fill_color\":\"A0C5C7\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":1801,\"favorite_count\":3914,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"ar\"},\"is_quote_status\":false,\"retweet_count\":1801,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"ar\"},{\"created_at\":\"Sun Apr 26 00:31:49 +0000 2020\",\"id\":1254206512018440200,\"id_str\":\"1254206512018440200\",\"text\":\"RT @czarnepazury: szczere o\\u015bwiadczyny z mi\\u0142o\\u015bci?\\nnieeeeeeeee\\nchallenge 200k na ig i o\\u015bwiadczyny z tego powodu?\\ntaaaaaaaaak https:\\\/\\\/t.co\\\/3LN\\u2026\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"czarnepazury\",\"name\":\"charlie\",\"id\":1170717318160293888,\"id_str\":\"1170717318160293888\",\"indices\":[3,16]}],\"urls\":[]},\"metadata\":{\"iso_language_code\":\"pl\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":765089605087535104,\"id_str\":\"765089605087535104\",\"name\":\"golden rose\",\"screen_name\":\"goldenrosexoxo\",\"location\":\"Los Angeles, CA\",\"description\":\"better to be disliked for who you are than to be loved for who you are not\\ud83d\\ude42\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":1391,\"friends_count\":801,\"listed_count\":9,\"created_at\":\"Mon Aug 15 07:35:51 +0000 2016\",\"favourites_count\":18227,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":24443,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"000000\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1231352110639390722\\\/iua73CVa_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1231352110639390722\\\/iua73CVa_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/765089605087535104\\\/1582412196\",\"profile_link_color\":\"ABB8C2\",\"profile_sidebar_border_color\":\"000000\",\"profile_sidebar_fill_color\":\"000000\",\"profile_text_color\":\"000000\",\"profile_use_background_image\":false,\"has_extended_profile\":false,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Sat Apr 25 17:46:20 +0000 2020\",\"id\":1254104469421375488,\"id_str\":\"1254104469421375488\",\"text\":\"szczere o\\u015bwiadczyny z mi\\u0142o\\u015bci?\\nnieeeeeeeee\\nchallenge 200k na ig i o\\u015bwiadczyny z tego powodu?\\ntaaaaaaaaak https:\\\/\\\/t.co\\\/3LNPi3Hjm1\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[],\"media\":[{\"id\":1254103953920360449,\"id_str\":\"1254103953920360449\",\"indices\":[105,128],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254103953920360449\\\/pu\\\/img\\\/qDPP9qENdCSMX8Lv.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254103953920360449\\\/pu\\\/img\\\/qDPP9qENdCSMX8Lv.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/3LNPi3Hjm1\",\"display_url\":\"pic.twitter.com\\\/3LNPi3Hjm1\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/czarnepazury\\\/status\\\/1254104469421375488\\\/video\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"medium\":{\"w\":540,\"h\":960,\"resize\":\"fit\"},\"small\":{\"w\":383,\"h\":680,\"resize\":\"fit\"},\"large\":{\"w\":540,\"h\":960,\"resize\":\"fit\"}}}]},\"extended_entities\":{\"media\":[{\"id\":1254103953920360449,\"id_str\":\"1254103953920360449\",\"indices\":[105,128],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254103953920360449\\\/pu\\\/img\\\/qDPP9qENdCSMX8Lv.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254103953920360449\\\/pu\\\/img\\\/qDPP9qENdCSMX8Lv.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/3LNPi3Hjm1\",\"display_url\":\"pic.twitter.com\\\/3LNPi3Hjm1\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/czarnepazury\\\/status\\\/1254104469421375488\\\/video\\\/1\",\"type\":\"video\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"medium\":{\"w\":540,\"h\":960,\"resize\":\"fit\"},\"small\":{\"w\":383,\"h\":680,\"resize\":\"fit\"},\"large\":{\"w\":540,\"h\":960,\"resize\":\"fit\"}},\"video_info\":{\"aspect_ratio\":[9,16],\"duration_millis\":22633,\"variants\":[{\"bitrate\":832000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254103953920360449\\\/pu\\\/vid\\\/360x640\\\/ktAHBz-gKCvmq_hU.mp4?tag=10\"},{\"bitrate\":2176000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254103953920360449\\\/pu\\\/vid\\\/540x960\\\/wRH0cIrDyP0vCII8.mp4?tag=10\"},{\"content_type\":\"application\\\/x-mpegURL\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254103953920360449\\\/pu\\\/pl\\\/_VqskdApBVQQMRhB.m3u8?tag=10\"},{\"bitrate\":632000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254103953920360449\\\/pu\\\/vid\\\/320x568\\\/9DGpCwh-deks4BME.mp4?tag=10\"}]},\"additional_media_info\":{\"monetizable\":false}}]},\"metadata\":{\"iso_language_code\":\"pl\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/android\\\" rel=\\\"nofollow\\\"\\u003eTwitter for Android\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":1170717318160293888,\"id_str\":\"1170717318160293888\",\"name\":\"charlie\",\"screen_name\":\"czarnepazury\",\"location\":\"\",\"description\":\"she wears a chain and destroyed my heart\\ndon't know how to tell my mom that it's you\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":4401,\"friends_count\":4087,\"listed_count\":43,\"created_at\":\"Sun Sep 08 15:15:47 +0000 2019\",\"favourites_count\":20946,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":9757,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1245471451303510033\\\/aZ06Lbpc_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1245471451303510033\\\/aZ06Lbpc_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/1170717318160293888\\\/1574942236\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":49,\"favorite_count\":378,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"pl\"},\"is_quote_status\":false,\"retweet_count\":49,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"pl\"},{\"created_at\":\"Sun Apr 26 00:31:49 +0000 2020\",\"id\":1254206511880056837,\"id_str\":\"1254206511880056837\",\"text\":\"RT @NazareAmarga: *25 de abril*\\n\\neu: https:\\\/\\\/t.co\\\/g5WrhWuyLU\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"NazareAmarga\",\"name\":\"Nazar\\u00e9 Amarga\",\"id\":1072573028,\"id_str\":\"1072573028\",\"indices\":[3,16]}],\"urls\":[],\"media\":[{\"id\":1254098292553777152,\"id_str\":\"1254098292553777152\",\"indices\":[37,60],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWdzwKkXgAAhCMx.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWdzwKkXgAAhCMx.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/g5WrhWuyLU\",\"display_url\":\"pic.twitter.com\\\/g5WrhWuyLU\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/NazareAmarga\\\/status\\\/1254098297557602304\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"medium\":{\"w\":1080,\"h\":810,\"resize\":\"fit\"},\"large\":{\"w\":1080,\"h\":810,\"resize\":\"fit\"},\"small\":{\"w\":680,\"h\":510,\"resize\":\"fit\"}},\"source_status_id\":1254098297557602304,\"source_status_id_str\":\"1254098297557602304\",\"source_user_id\":1072573028,\"source_user_id_str\":\"1072573028\"}]},\"extended_entities\":{\"media\":[{\"id\":1254098292553777152,\"id_str\":\"1254098292553777152\",\"indices\":[37,60],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWdzwKkXgAAhCMx.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWdzwKkXgAAhCMx.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/g5WrhWuyLU\",\"display_url\":\"pic.twitter.com\\\/g5WrhWuyLU\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/NazareAmarga\\\/status\\\/1254098297557602304\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"medium\":{\"w\":1080,\"h\":810,\"resize\":\"fit\"},\"large\":{\"w\":1080,\"h\":810,\"resize\":\"fit\"},\"small\":{\"w\":680,\"h\":510,\"resize\":\"fit\"}},\"source_status_id\":1254098297557602304,\"source_status_id_str\":\"1254098297557602304\",\"source_user_id\":1072573028,\"source_user_id_str\":\"1072573028\"}]},\"metadata\":{\"iso_language_code\":\"pt\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/android\\\" rel=\\\"nofollow\\\"\\u003eTwitter for Android\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":1245833334984527875,\"id_str\":\"1245833334984527875\",\"name\":\"Elis\\ud83d\\udc3e\\u2661\",\"screen_name\":\"elis_fferri\",\"location\":\"\",\"description\":\"Metamorfose... borbolete-se!\\ud83c\\udf37\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":15,\"friends_count\":187,\"listed_count\":0,\"created_at\":\"Thu Apr 02 21:59:57 +0000 2020\",\"favourites_count\":214,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":102,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1245833483966177286\\\/Z__Ipnaf_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1245833483966177286\\\/Z__Ipnaf_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/1245833334984527875\\\/1585875170\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Sat Apr 25 17:21:48 +0000 2020\",\"id\":1254098297557602304,\"id_str\":\"1254098297557602304\",\"text\":\"*25 de abril*\\n\\neu: https:\\\/\\\/t.co\\\/g5WrhWuyLU\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[],\"media\":[{\"id\":1254098292553777152,\"id_str\":\"1254098292553777152\",\"indices\":[19,42],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWdzwKkXgAAhCMx.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWdzwKkXgAAhCMx.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/g5WrhWuyLU\",\"display_url\":\"pic.twitter.com\\\/g5WrhWuyLU\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/NazareAmarga\\\/status\\\/1254098297557602304\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"medium\":{\"w\":1080,\"h\":810,\"resize\":\"fit\"},\"large\":{\"w\":1080,\"h\":810,\"resize\":\"fit\"},\"small\":{\"w\":680,\"h\":510,\"resize\":\"fit\"}}}]},\"extended_entities\":{\"media\":[{\"id\":1254098292553777152,\"id_str\":\"1254098292553777152\",\"indices\":[19,42],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWdzwKkXgAAhCMx.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWdzwKkXgAAhCMx.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/g5WrhWuyLU\",\"display_url\":\"pic.twitter.com\\\/g5WrhWuyLU\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/NazareAmarga\\\/status\\\/1254098297557602304\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"medium\":{\"w\":1080,\"h\":810,\"resize\":\"fit\"},\"large\":{\"w\":1080,\"h\":810,\"resize\":\"fit\"},\"small\":{\"w\":680,\"h\":510,\"resize\":\"fit\"}}}]},\"metadata\":{\"iso_language_code\":\"pt\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":1072573028,\"id_str\":\"1072573028\",\"name\":\"Nazar\\u00e9 Amarga\",\"screen_name\":\"NazareAmarga\",\"location\":\"\",\"description\":\"loirona gostosa do twitter nazare.amarga@mynd8.com.br\",\"url\":\"https:\\\/\\\/t.co\\\/J2ScZ6Orzt\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/J2ScZ6Orzt\",\"expanded_url\":\"http:\\\/\\\/instagram.com\\\/NazareAmarga\",\"display_url\":\"instagram.com\\\/NazareAmarga\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":751542,\"friends_count\":311,\"listed_count\":128,\"created_at\":\"Wed Jan 09 01:59:48 +0000 2013\",\"favourites_count\":575,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":5823,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"000000\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/580446627695038464\\\/iV5737Qs_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/580446627695038464\\\/iV5737Qs_normal.jpg\",\"profile_link_color\":\"DD2E44\",\"profile_sidebar_border_color\":\"000000\",\"profile_sidebar_fill_color\":\"000000\",\"profile_text_color\":\"000000\",\"profile_use_background_image\":false,\"has_extended_profile\":false,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":879,\"favorite_count\":3433,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"pt\"},\"is_quote_status\":false,\"retweet_count\":879,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"pt\"},{\"created_at\":\"Sun Apr 26 00:31:49 +0000 2020\",\"id\":1254206511749816321,\"id_str\":\"1254206511749816321\",\"text\":\"RT @tbEsnlhUJDDaIG9: \\u0e44\\u0e21\\u0e48\\u0e21\\u0e35\\u0e2d\\u0e35\\u0e01\\u0e41\\u0e25\\u0e49\\u0e27\\u0e21\\u0e31\\u0e19\\u0e08\\u0e1a\\u0e44\\u0e1b\\u0e15\\u0e31\\u0e49\\u0e07\\u0e41\\u0e15\\u0e48\\u0e40\\u0e21\\u0e37\\u0e48\\u0e2d\\u0e27\\u0e32\\u0e19\\u0e41\\u0e25\\u0e49\\u0e27 \\u0e22\\u0e31\\u0e07\\u0e44\\u0e07\\u0e01\\u0e47\\u0e23\\u0e31\\u0e01\\u0e41\\u0e25\\u0e30\\u0e04\\u0e34\\u0e14\\u0e16\\u0e36\\u0e07\\u0e40\\u0e2b\\u0e21\\u0e37\\u0e2d\\u0e19\\u0e40\\u0e14\\u0e34\\u0e21 \\u0e21\\u0e31\\u0e19\\u0e04\\u0e37\\u0e2d\\u0e04\\u0e27\\u0e32\\u0e21\\u0e17\\u0e23\\u0e07\\u0e08\\u0e33\\u0e17\\u0e35\\u0e48\\u0e14\\u0e35\\u0e17\\u0e35\\u0e48\\u0e2a\\u0e38\\u0e14\\u0e02\\u0e2d\\u0e07\\u0e2b\\u0e19\\u0e39\\u0e19\\u0e30\\u0e04\\u0e30300363\\ud83d\\ude2d\\n.\\n.\\n.\\u2026\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"tbEsnlhUJDDaIG9\",\"name\":\"\\u0e04\\u0e27\\u0e32\\u0e21\\u0e17\\u0e23\\u0e07\\u0e08\\u0e33 |\\u0e25\\u0e34\\u0e21\\u0e34\\u0e15\\u0e1f\\u0e2d\\u0e25\",\"id\":1243314857253859328,\"id_str\":\"1243314857253859328\",\"indices\":[3,19]}],\"urls\":[]},\"metadata\":{\"iso_language_code\":\"th\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/android\\\" rel=\\\"nofollow\\\"\\u003eTwitter for Android\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":1253687691935281152,\"id_str\":\"1253687691935281152\",\"name\":\"\\u0e17\\u0e48\\u0e32\\u0e40\\u0e23\\u0e37\\u0e2d\",\"screen_name\":\"Thareux90\",\"location\":\"\\ud83d\\udd87\\ufe0f\",\"description\":\"\\u0e1c\\u0e21\\u0e21\\u0e32\\u0e15\\u0e32\\u0e21\\u0e2b\\u0e32\\u0e1c\\u0e39\\u0e49\\u0e2b\\u0e0d\\u0e34\\u0e07\\u200b\\u0e04\\u0e19\\u0e19\\u0e36\\u0e07\\u200b\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":122,\"friends_count\":45,\"listed_count\":2,\"created_at\":\"Fri Apr 24 14:10:25 +0000 2020\",\"favourites_count\":58,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":693,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1253860559633563648\\\/6LMU_KUb_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1253860559633563648\\\/6LMU_KUb_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/1253687691935281152\\\/1587778627\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Sat Apr 25 23:39:19 +0000 2020\",\"id\":1254193301424467968,\"id_str\":\"1254193301424467968\",\"text\":\"\\u0e44\\u0e21\\u0e48\\u0e21\\u0e35\\u0e2d\\u0e35\\u0e01\\u0e41\\u0e25\\u0e49\\u0e27\\u0e21\\u0e31\\u0e19\\u0e08\\u0e1a\\u0e44\\u0e1b\\u0e15\\u0e31\\u0e49\\u0e07\\u0e41\\u0e15\\u0e48\\u0e40\\u0e21\\u0e37\\u0e48\\u0e2d\\u0e27\\u0e32\\u0e19\\u0e41\\u0e25\\u0e49\\u0e27 \\u0e22\\u0e31\\u0e07\\u0e44\\u0e07\\u0e01\\u0e47\\u0e23\\u0e31\\u0e01\\u0e41\\u0e25\\u0e30\\u0e04\\u0e34\\u0e14\\u0e16\\u0e36\\u0e07\\u0e40\\u0e2b\\u0e21\\u0e37\\u0e2d\\u0e19\\u0e40\\u0e14\\u0e34\\u0e21 \\u0e21\\u0e31\\u0e19\\u0e04\\u0e37\\u0e2d\\u0e04\\u0e27\\u0e32\\u0e21\\u0e17\\u0e23\\u0e07\\u0e08\\u0e33\\u0e17\\u0e35\\u0e48\\u0e14\\u0e35\\u0e17\\u0e35\\u0e48\\u0e2a\\u0e38\\u0e14\\u0e02\\u0e2d\\u0e07\\u0e2b\\u0e19\\u0e39\\u0e19\\u0e30\\u0e04\\u0e30300363\\ud83d\\ude2d\\n.\\u2026 https:\\\/\\\/t.co\\\/tDN8lxtvs2\",\"truncated\":true,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/tDN8lxtvs2\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/i\\\/web\\\/status\\\/1254193301424467968\",\"display_url\":\"twitter.com\\\/i\\\/web\\\/status\\\/1\\u2026\",\"indices\":[116,139]}]},\"metadata\":{\"iso_language_code\":\"th\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/android\\\" rel=\\\"nofollow\\\"\\u003eTwitter for Android\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":1243314857253859328,\"id_str\":\"1243314857253859328\",\"name\":\"\\u0e04\\u0e27\\u0e32\\u0e21\\u0e17\\u0e23\\u0e07\\u0e08\\u0e33 |\\u0e25\\u0e34\\u0e21\\u0e34\\u0e15\\u0e1f\\u0e2d\\u0e25\",\"screen_name\":\"tbEsnlhUJDDaIG9\",\"location\":\"\",\"description\":\"30.03.63\\u2764\\ufe0f \\u0e41\\u0e04\\u0e48\\u0e04\\u0e27\\u0e32\\u0e21\\u0e17\\u0e23\\u0e07\\u0e08\\u0e33\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":28,\"friends_count\":1196,\"listed_count\":0,\"created_at\":\"Thu Mar 26 23:12:32 +0000 2020\",\"favourites_count\":0,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":22,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1243315119410393088\\\/uYlCNC8s_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1243315119410393088\\\/uYlCNC8s_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/1243314857253859328\\\/1585264521\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":15,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"th\"},\"is_quote_status\":false,\"retweet_count\":15,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"th\"},{\"created_at\":\"Sun Apr 26 00:31:49 +0000 2020\",\"id\":1254206511649357824,\"id_str\":\"1254206511649357824\",\"text\":\"RT @escritosrame: https:\\\/\\\/t.co\\\/WNNMRHf2G0\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"escritosrame\",\"name\":\"\\ud835\\udc93\\ud835\\udc82\\ud835\\udc8e\\ud835\\udc86\",\"id\":1032743790761705472,\"id_str\":\"1032743790761705472\",\"indices\":[3,16]}],\"urls\":[],\"media\":[{\"id\":1254140985191301121,\"id_str\":\"1254140985191301121\",\"indices\":[18,41],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWealNCWAAEVQIV.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWealNCWAAEVQIV.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/WNNMRHf2G0\",\"display_url\":\"pic.twitter.com\\\/WNNMRHf2G0\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/escritosrame\\\/status\\\/1254140992330096640\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":680,\"h\":382,\"resize\":\"fit\"},\"large\":{\"w\":1125,\"h\":632,\"resize\":\"fit\"},\"medium\":{\"w\":1125,\"h\":632,\"resize\":\"fit\"}},\"source_status_id\":1254140992330096640,\"source_status_id_str\":\"1254140992330096640\",\"source_user_id\":1032743790761705472,\"source_user_id_str\":\"1032743790761705472\"}]},\"extended_entities\":{\"media\":[{\"id\":1254140985191301121,\"id_str\":\"1254140985191301121\",\"indices\":[18,41],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWealNCWAAEVQIV.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWealNCWAAEVQIV.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/WNNMRHf2G0\",\"display_url\":\"pic.twitter.com\\\/WNNMRHf2G0\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/escritosrame\\\/status\\\/1254140992330096640\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":680,\"h\":382,\"resize\":\"fit\"},\"large\":{\"w\":1125,\"h\":632,\"resize\":\"fit\"},\"medium\":{\"w\":1125,\"h\":632,\"resize\":\"fit\"}},\"source_status_id\":1254140992330096640,\"source_status_id_str\":\"1254140992330096640\",\"source_user_id\":1032743790761705472,\"source_user_id_str\":\"1032743790761705472\"}]},\"metadata\":{\"iso_language_code\":\"und\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":4097079975,\"id_str\":\"4097079975\",\"name\":\"Alma Pino\",\"screen_name\":\"apinof95\",\"location\":\"Merida,Espa\\u00f1a.\",\"description\":\"where there is love, there is life \\u00a9\\u2764\\ufe0f\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":188,\"friends_count\":182,\"listed_count\":0,\"created_at\":\"Mon Nov 02 12:17:07 +0000 2015\",\"favourites_count\":517,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":1587,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1253844466949070858\\\/mRZ1N0IU_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1253844466949070858\\\/mRZ1N0IU_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/4097079975\\\/1585421884\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Sat Apr 25 20:11:28 +0000 2020\",\"id\":1254140992330096640,\"id_str\":\"1254140992330096640\",\"text\":\"https:\\\/\\\/t.co\\\/WNNMRHf2G0\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[],\"media\":[{\"id\":1254140985191301121,\"id_str\":\"1254140985191301121\",\"indices\":[0,23],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWealNCWAAEVQIV.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWealNCWAAEVQIV.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/WNNMRHf2G0\",\"display_url\":\"pic.twitter.com\\\/WNNMRHf2G0\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/escritosrame\\\/status\\\/1254140992330096640\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":680,\"h\":382,\"resize\":\"fit\"},\"large\":{\"w\":1125,\"h\":632,\"resize\":\"fit\"},\"medium\":{\"w\":1125,\"h\":632,\"resize\":\"fit\"}}}]},\"extended_entities\":{\"media\":[{\"id\":1254140985191301121,\"id_str\":\"1254140985191301121\",\"indices\":[0,23],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWealNCWAAEVQIV.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWealNCWAAEVQIV.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/WNNMRHf2G0\",\"display_url\":\"pic.twitter.com\\\/WNNMRHf2G0\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/escritosrame\\\/status\\\/1254140992330096640\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":680,\"h\":382,\"resize\":\"fit\"},\"large\":{\"w\":1125,\"h\":632,\"resize\":\"fit\"},\"medium\":{\"w\":1125,\"h\":632,\"resize\":\"fit\"}}}]},\"metadata\":{\"iso_language_code\":\"und\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":1032743790761705472,\"id_str\":\"1032743790761705472\",\"name\":\"\\ud835\\udc93\\ud835\\udc82\\ud835\\udc8e\\ud835\\udc86\",\"screen_name\":\"escritosrame\",\"location\":\"\",\"description\":\"\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":316811,\"friends_count\":3,\"listed_count\":158,\"created_at\":\"Thu Aug 23 21:38:01 +0000 2018\",\"favourites_count\":105,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":206,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1150110888596299778\\\/37fGmlV1_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1150110888596299778\\\/37fGmlV1_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/1032743790761705472\\\/1586981394\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":3518,\"favorite_count\":9656,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"und\"},\"is_quote_status\":false,\"retweet_count\":3518,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"und\"},{\"created_at\":\"Sun Apr 26 00:31:49 +0000 2020\",\"id\":1254206511536054275,\"id_str\":\"1254206511536054275\",\"text\":\"RT @NessaAdlerXO: I only use Twitter for viewing and screenshotting funny tweets, but since I\\u2019m here, I\\u2019d like to expose a racist \\ud83d\\ude0c He said\\u2026\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"NessaAdlerXO\",\"name\":\"ness\",\"id\":1219156139339853824,\"id_str\":\"1219156139339853824\",\"indices\":[3,16]}],\"urls\":[]},\"metadata\":{\"iso_language_code\":\"en\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":2997792061,\"id_str\":\"2997792061\",\"name\":\"karrington airelle\\u2019 \\ud83c\\udf3b\",\"screen_name\":\"__beautyfordays\",\"location\":\"Atlanta, GA\",\"description\":\"Psalms 46:5\\u2728Alabama State University 21\\u2019 \\ud83d\\udc1d HA2 C8 \\u2764\\ufe0f\\ud83d\\udc9b\\ud83d\\udd25\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":1769,\"friends_count\":1139,\"listed_count\":3,\"created_at\":\"Tue Jan 27 03:43:24 +0000 2015\",\"favourites_count\":36312,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":18287,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"94D487\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme18\\\/bg.gif\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme18\\\/bg.gif\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1246586001042149376\\\/dML0aB5m_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1246586001042149376\\\/dML0aB5m_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/2997792061\\\/1579990609\",\"profile_link_color\":\"3B94D9\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Sat Apr 25 01:46:58 +0000 2020\",\"id\":1253863037561421828,\"id_str\":\"1253863037561421828\",\"text\":\"I only use Twitter for viewing and screenshotting funny tweets, but since I\\u2019m here, I\\u2019d like to expose a racist \\ud83d\\ude0c H\\u2026 https:\\\/\\\/t.co\\\/WkHG544YUe\",\"truncated\":true,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/WkHG544YUe\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/i\\\/web\\\/status\\\/1253863037561421828\",\"display_url\":\"twitter.com\\\/i\\\/web\\\/status\\\/1\\u2026\",\"indices\":[117,140]}]},\"metadata\":{\"iso_language_code\":\"en\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":1219156139339853824,\"id_str\":\"1219156139339853824\",\"name\":\"ness\",\"screen_name\":\"NessaAdlerXO\",\"location\":\"\",\"description\":\"\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":25,\"friends_count\":24,\"listed_count\":0,\"created_at\":\"Mon Jan 20 07:14:16 +0000 2020\",\"favourites_count\":44,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":14,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1254137661280915457\\\/c7jK6SWr_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1254137661280915457\\\/c7jK6SWr_normal.jpg\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":2777,\"favorite_count\":4529,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"en\"},\"is_quote_status\":false,\"retweet_count\":2777,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"en\"},{\"created_at\":\"Sun Apr 26 00:31:49 +0000 2020\",\"id\":1254206511473061891,\"id_str\":\"1254206511473061891\",\"text\":\"RT @sakata_77: GW\\u3082\\u5bb6\\u3067\\u3084\\u308b\\u3053\\u3068\\u306a\\u304f\\u306a\\u3063\\u3066\\u304d\\u305f\\u304b\\u3089\\u5199\\u771f\\u30d5\\u30a9\\u30eb\\u30c0\\u3042\\u3055\\u3063\\u3066\\u305f\\u3089\\u5b8c\\u74a7\\u306a\\u62f3\\u6cd5\\u306e\\u69cb\\u3048\\u304b\\u3089\\u8e8d\\u52d5\\u3059\\u308b\\u732b\\u306e\\u5199\\u771f\\u3042\\u3063\\u305f\\u304b\\u3089\\u898b\\u3066 https:\\\/\\\/t.co\\\/YuXzj43xwf\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"sakata_77\",\"name\":\"\\u4e45\\u65b9 \\u5e83\\u4e4b\\u300c\\u306e\\u3089\\u732b\\u62f3\\u300d\",\"id\":3306955640,\"id_str\":\"3306955640\",\"indices\":[3,13]}],\"urls\":[],\"media\":[{\"id\":1254204964605325314,\"id_str\":\"1254204964605325314\",\"indices\":[71,94],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfUxS7U8AIFCk1.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfUxS7U8AIFCk1.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/YuXzj43xwf\",\"display_url\":\"pic.twitter.com\\\/YuXzj43xwf\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/sakata_77\\\/status\\\/1254205590668062720\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":680,\"h\":453,\"resize\":\"fit\"},\"large\":{\"w\":2048,\"h\":1366,\"resize\":\"fit\"},\"medium\":{\"w\":1200,\"h\":800,\"resize\":\"fit\"}},\"source_status_id\":1254205590668062720,\"source_status_id_str\":\"1254205590668062720\",\"source_user_id\":3306955640,\"source_user_id_str\":\"3306955640\"}]},\"extended_entities\":{\"media\":[{\"id\":1254204964605325314,\"id_str\":\"1254204964605325314\",\"indices\":[71,94],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfUxS7U8AIFCk1.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfUxS7U8AIFCk1.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/YuXzj43xwf\",\"display_url\":\"pic.twitter.com\\\/YuXzj43xwf\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/sakata_77\\\/status\\\/1254205590668062720\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":680,\"h\":453,\"resize\":\"fit\"},\"large\":{\"w\":2048,\"h\":1366,\"resize\":\"fit\"},\"medium\":{\"w\":1200,\"h\":800,\"resize\":\"fit\"}},\"source_status_id\":1254205590668062720,\"source_status_id_str\":\"1254205590668062720\",\"source_user_id\":3306955640,\"source_user_id_str\":\"3306955640\"},{\"id\":1254204976353521664,\"id_str\":\"1254204976353521664\",\"indices\":[71,94],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfUx-sUMAAi1h5.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfUx-sUMAAi1h5.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/YuXzj43xwf\",\"display_url\":\"pic.twitter.com\\\/YuXzj43xwf\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/sakata_77\\\/status\\\/1254205590668062720\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":510,\"h\":680,\"resize\":\"fit\"},\"medium\":{\"w\":900,\"h\":1200,\"resize\":\"fit\"},\"large\":{\"w\":1536,\"h\":2048,\"resize\":\"fit\"}},\"source_status_id\":1254205590668062720,\"source_status_id_str\":\"1254205590668062720\",\"source_user_id\":3306955640,\"source_user_id_str\":\"3306955640\"},{\"id\":1254204986143043586,\"id_str\":\"1254204986143043586\",\"indices\":[71,94],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfUyjKUcAIAao-.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfUyjKUcAIAao-.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/YuXzj43xwf\",\"display_url\":\"pic.twitter.com\\\/YuXzj43xwf\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/sakata_77\\\/status\\\/1254205590668062720\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"large\":{\"w\":1536,\"h\":2048,\"resize\":\"fit\"},\"medium\":{\"w\":900,\"h\":1200,\"resize\":\"fit\"},\"small\":{\"w\":510,\"h\":680,\"resize\":\"fit\"}},\"source_status_id\":1254205590668062720,\"source_status_id_str\":\"1254205590668062720\",\"source_user_id\":3306955640,\"source_user_id_str\":\"3306955640\"},{\"id\":1254204997614465024,\"id_str\":\"1254204997614465024\",\"indices\":[71,94],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfUzN5UcAAQ6Li.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfUzN5UcAAQ6Li.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/YuXzj43xwf\",\"display_url\":\"pic.twitter.com\\\/YuXzj43xwf\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/sakata_77\\\/status\\\/1254205590668062720\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"large\":{\"w\":2048,\"h\":1366,\"resize\":\"fit\"},\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":680,\"h\":453,\"resize\":\"fit\"},\"medium\":{\"w\":1200,\"h\":800,\"resize\":\"fit\"}},\"source_status_id\":1254205590668062720,\"source_status_id_str\":\"1254205590668062720\",\"source_user_id\":3306955640,\"source_user_id_str\":\"3306955640\"}]},\"metadata\":{\"iso_language_code\":\"ja\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/android\\\" rel=\\\"nofollow\\\"\\u003eTwitter for Android\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":900746954463784961,\"id_str\":\"900746954463784961\",\"name\":\"\\u30b5\\u30de\\u30f3\\u30b5\",\"screen_name\":\"samantha_globe3\",\"location\":\"HIROSHIMA\\u2764\\ufe0f\\u2194HIGASHIHIROSHIMA\\u2764\\ufe0f\",\"description\":\"\\u30d7\\u30e9\\u30b9\\u30b5\\u30a4\\u30ba\\u30e2\\u30c7\\u30eb\\u306b\\u61a7\\u308c\\u308b\\u73fe\\u5f79\\u307d\\u3061\\u3083\\u30cd\\u30b3\\u30ca\\u30fc\\u30b9\\ud83d\\ude3d\\ud83d\\udc95\\n5\\u6b73\\u306e\\u606f\\u5b50\\ud83d\\ude83#QAJF \\u5f8c\\u65b9\\u652f\\u63f4\\u3061\\u3085\\ud83d\\ude18\\u7686\\u69d8\\u3082\\u3046\\u3001\\u6d41\\u77f3\\u306b\\u899a\\u9192\\u3057\\u7948\\u308a\\u307e\\u3057\\u3087\\ud83d\\ude4f\\u2728\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":375,\"friends_count\":2326,\"listed_count\":2,\"created_at\":\"Thu Aug 24 15:49:43 +0000 2017\",\"favourites_count\":71089,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":30712,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/958228394243575808\\\/cVcNKl_I_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/958228394243575808\\\/cVcNKl_I_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/900746954463784961\\\/1503591735\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Sun Apr 26 00:28:09 +0000 2020\",\"id\":1254205590668062720,\"id_str\":\"1254205590668062720\",\"text\":\"GW\\u3082\\u5bb6\\u3067\\u3084\\u308b\\u3053\\u3068\\u306a\\u304f\\u306a\\u3063\\u3066\\u304d\\u305f\\u304b\\u3089\\u5199\\u771f\\u30d5\\u30a9\\u30eb\\u30c0\\u3042\\u3055\\u3063\\u3066\\u305f\\u3089\\u5b8c\\u74a7\\u306a\\u62f3\\u6cd5\\u306e\\u69cb\\u3048\\u304b\\u3089\\u8e8d\\u52d5\\u3059\\u308b\\u732b\\u306e\\u5199\\u771f\\u3042\\u3063\\u305f\\u304b\\u3089\\u898b\\u3066 https:\\\/\\\/t.co\\\/YuXzj43xwf\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[],\"media\":[{\"id\":1254204964605325314,\"id_str\":\"1254204964605325314\",\"indices\":[56,79],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfUxS7U8AIFCk1.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfUxS7U8AIFCk1.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/YuXzj43xwf\",\"display_url\":\"pic.twitter.com\\\/YuXzj43xwf\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/sakata_77\\\/status\\\/1254205590668062720\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":680,\"h\":453,\"resize\":\"fit\"},\"large\":{\"w\":2048,\"h\":1366,\"resize\":\"fit\"},\"medium\":{\"w\":1200,\"h\":800,\"resize\":\"fit\"}}}]},\"extended_entities\":{\"media\":[{\"id\":1254204964605325314,\"id_str\":\"1254204964605325314\",\"indices\":[56,79],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfUxS7U8AIFCk1.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfUxS7U8AIFCk1.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/YuXzj43xwf\",\"display_url\":\"pic.twitter.com\\\/YuXzj43xwf\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/sakata_77\\\/status\\\/1254205590668062720\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":680,\"h\":453,\"resize\":\"fit\"},\"large\":{\"w\":2048,\"h\":1366,\"resize\":\"fit\"},\"medium\":{\"w\":1200,\"h\":800,\"resize\":\"fit\"}}},{\"id\":1254204976353521664,\"id_str\":\"1254204976353521664\",\"indices\":[56,79],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfUx-sUMAAi1h5.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfUx-sUMAAi1h5.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/YuXzj43xwf\",\"display_url\":\"pic.twitter.com\\\/YuXzj43xwf\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/sakata_77\\\/status\\\/1254205590668062720\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":510,\"h\":680,\"resize\":\"fit\"},\"medium\":{\"w\":900,\"h\":1200,\"resize\":\"fit\"},\"large\":{\"w\":1536,\"h\":2048,\"resize\":\"fit\"}}},{\"id\":1254204986143043586,\"id_str\":\"1254204986143043586\",\"indices\":[56,79],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfUyjKUcAIAao-.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfUyjKUcAIAao-.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/YuXzj43xwf\",\"display_url\":\"pic.twitter.com\\\/YuXzj43xwf\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/sakata_77\\\/status\\\/1254205590668062720\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"large\":{\"w\":1536,\"h\":2048,\"resize\":\"fit\"},\"medium\":{\"w\":900,\"h\":1200,\"resize\":\"fit\"},\"small\":{\"w\":510,\"h\":680,\"resize\":\"fit\"}}},{\"id\":1254204997614465024,\"id_str\":\"1254204997614465024\",\"indices\":[56,79],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfUzN5UcAAQ6Li.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfUzN5UcAAQ6Li.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/YuXzj43xwf\",\"display_url\":\"pic.twitter.com\\\/YuXzj43xwf\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/sakata_77\\\/status\\\/1254205590668062720\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"large\":{\"w\":2048,\"h\":1366,\"resize\":\"fit\"},\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":680,\"h\":453,\"resize\":\"fit\"},\"medium\":{\"w\":1200,\"h\":800,\"resize\":\"fit\"}}}]},\"metadata\":{\"iso_language_code\":\"ja\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/mobile.twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web App\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":3306955640,\"id_str\":\"3306955640\",\"name\":\"\\u4e45\\u65b9 \\u5e83\\u4e4b\\u300c\\u306e\\u3089\\u732b\\u62f3\\u300d\",\"screen_name\":\"sakata_77\",\"location\":\"\",\"description\":\"hisakata hiroyuki cat photographer \\u65e7\\u540d\\u30a2\\u30af\\u30bb\\u30f3\\u30c8 \\u5199\\u771f\\u96c6\\u300c\\u306e\\u3089\\u732b\\u62f3\\u300d\\u30d5\\u30a9\\u30ed\\u30fc\\u304a\\u6c17\\u8efd\\u306b \\u4e5d\\u5dde\\u5728\\u4f4f\\u3001\\u732b\\u3058\\u3083\\u3089\\u3057\\u3092\\u4f7f\\u3063\\u305f\\u64ae\\u5f71\\u304c\\u5f97\\u610f\\u3067\\u3059 \\u5199\\u771f\\u306e\\u7121\\u65ad\\u8ee2\\u8f09\\u53ca\\u3073\\u4f7f\\u7528\\u306f\\u7981\\u6b62 \\u8b1b\\u6f14\\u4f9d\\u983c\\u3042\\u308c\\u3070\\u3054\\u76f8\\u8ac7\\u304f\\u3060\\u3055\\u3044 \\u4f7f\\u7528\\u6a5f\\u7a2e\\uff1aOlympus E-M1Mk2 \\u9023\\u7d61\\u5148 sakata_77@hotmail.com\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":80561,\"friends_count\":708,\"listed_count\":1180,\"created_at\":\"Wed Aug 05 13:21:20 +0000 2015\",\"favourites_count\":2835,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":2385,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"000000\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1117280420414943232\\\/y6ZDhbQm_normal.png\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1117280420414943232\\\/y6ZDhbQm_normal.png\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/3306955640\\\/1539213231\",\"profile_link_color\":\"FF691F\",\"profile_sidebar_border_color\":\"000000\",\"profile_sidebar_fill_color\":\"000000\",\"profile_text_color\":\"000000\",\"profile_use_background_image\":false,\"has_extended_profile\":false,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":48,\"favorite_count\":121,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"ja\"},\"is_quote_status\":false,\"retweet_count\":48,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"ja\"},{\"created_at\":\"Sun Apr 26 00:31:49 +0000 2020\",\"id\":1254206511460618240,\"id_str\":\"1254206511460618240\",\"text\":\"RT @oubrisado: pessoal do meu wpp esperando eu responder \\\/ eu de boa no twitter https:\\\/\\\/t.co\\\/HHEIJZwrMm\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"oubrisado\",\"name\":\"brisado\",\"id\":1224850562123997185,\"id_str\":\"1224850562123997185\",\"indices\":[3,13]}],\"urls\":[],\"media\":[{\"id\":1210301618455023616,\"id_str\":\"1210301618455023616\",\"indices\":[80,103],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EMva6NcXkAAAKa9.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EMva6NcXkAAAKa9.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/HHEIJZwrMm\",\"display_url\":\"pic.twitter.com\\\/HHEIJZwrMm\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/sincerojesuis\\\/status\\\/1210301628651364352\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"small\":{\"w\":530,\"h\":680,\"resize\":\"fit\"},\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"large\":{\"w\":798,\"h\":1024,\"resize\":\"fit\"},\"medium\":{\"w\":798,\"h\":1024,\"resize\":\"fit\"}},\"source_status_id\":1210301628651364352,\"source_status_id_str\":\"1210301628651364352\",\"source_user_id\":927680014627241984,\"source_user_id_str\":\"927680014627241984\"}]},\"extended_entities\":{\"media\":[{\"id\":1210301618455023616,\"id_str\":\"1210301618455023616\",\"indices\":[80,103],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EMva6NcXkAAAKa9.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EMva6NcXkAAAKa9.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/HHEIJZwrMm\",\"display_url\":\"pic.twitter.com\\\/HHEIJZwrMm\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/sincerojesuis\\\/status\\\/1210301628651364352\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"small\":{\"w\":530,\"h\":680,\"resize\":\"fit\"},\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"large\":{\"w\":798,\"h\":1024,\"resize\":\"fit\"},\"medium\":{\"w\":798,\"h\":1024,\"resize\":\"fit\"}},\"source_status_id\":1210301628651364352,\"source_status_id_str\":\"1210301628651364352\",\"source_user_id\":927680014627241984,\"source_user_id_str\":\"927680014627241984\"},{\"id\":1210301623312044032,\"id_str\":\"1210301623312044032\",\"indices\":[80,103],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EMva6fiX0AAmnHI.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EMva6fiX0AAmnHI.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/HHEIJZwrMm\",\"display_url\":\"pic.twitter.com\\\/HHEIJZwrMm\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/sincerojesuis\\\/status\\\/1210301628651364352\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":680,\"h\":669,\"resize\":\"fit\"},\"large\":{\"w\":952,\"h\":937,\"resize\":\"fit\"},\"medium\":{\"w\":952,\"h\":937,\"resize\":\"fit\"}},\"source_status_id\":1210301628651364352,\"source_status_id_str\":\"1210301628651364352\",\"source_user_id\":927680014627241984,\"source_user_id_str\":\"927680014627241984\"}]},\"metadata\":{\"iso_language_code\":\"pt\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/mobile.twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web App\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":1104425682640228353,\"id_str\":\"1104425682640228353\",\"name\":\"pav\\u00e3o :)\",\"screen_name\":\"leeonexx\",\"location\":\"\",\"description\":\"ig: ___.its.leonor.__\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":160,\"friends_count\":363,\"listed_count\":0,\"created_at\":\"Sat Mar 09 16:56:16 +0000 2019\",\"favourites_count\":4884,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":14316,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"000000\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1251952533280612353\\\/DYZ4Yx5-_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1251952533280612353\\\/DYZ4Yx5-_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/1104425682640228353\\\/1587327294\",\"profile_link_color\":\"1B95E0\",\"profile_sidebar_border_color\":\"000000\",\"profile_sidebar_fill_color\":\"000000\",\"profile_text_color\":\"000000\",\"profile_use_background_image\":false,\"has_extended_profile\":false,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Sat Apr 25 15:01:11 +0000 2020\",\"id\":1254062910847975424,\"id_str\":\"1254062910847975424\",\"text\":\"pessoal do meu wpp esperando eu responder \\\/ eu de boa no twitter https:\\\/\\\/t.co\\\/HHEIJZwrMm\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[],\"media\":[{\"id\":1210301618455023616,\"id_str\":\"1210301618455023616\",\"indices\":[65,88],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EMva6NcXkAAAKa9.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EMva6NcXkAAAKa9.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/HHEIJZwrMm\",\"display_url\":\"pic.twitter.com\\\/HHEIJZwrMm\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/sincerojesuis\\\/status\\\/1210301628651364352\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"small\":{\"w\":530,\"h\":680,\"resize\":\"fit\"},\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"large\":{\"w\":798,\"h\":1024,\"resize\":\"fit\"},\"medium\":{\"w\":798,\"h\":1024,\"resize\":\"fit\"}},\"source_status_id\":1210301628651364352,\"source_status_id_str\":\"1210301628651364352\",\"source_user_id\":927680014627241984,\"source_user_id_str\":\"927680014627241984\"}]},\"extended_entities\":{\"media\":[{\"id\":1210301618455023616,\"id_str\":\"1210301618455023616\",\"indices\":[65,88],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EMva6NcXkAAAKa9.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EMva6NcXkAAAKa9.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/HHEIJZwrMm\",\"display_url\":\"pic.twitter.com\\\/HHEIJZwrMm\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/sincerojesuis\\\/status\\\/1210301628651364352\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"small\":{\"w\":530,\"h\":680,\"resize\":\"fit\"},\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"large\":{\"w\":798,\"h\":1024,\"resize\":\"fit\"},\"medium\":{\"w\":798,\"h\":1024,\"resize\":\"fit\"}},\"source_status_id\":1210301628651364352,\"source_status_id_str\":\"1210301628651364352\",\"source_user_id\":927680014627241984,\"source_user_id_str\":\"927680014627241984\"},{\"id\":1210301623312044032,\"id_str\":\"1210301623312044032\",\"indices\":[65,88],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EMva6fiX0AAmnHI.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EMva6fiX0AAmnHI.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/HHEIJZwrMm\",\"display_url\":\"pic.twitter.com\\\/HHEIJZwrMm\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/sincerojesuis\\\/status\\\/1210301628651364352\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":680,\"h\":669,\"resize\":\"fit\"},\"large\":{\"w\":952,\"h\":937,\"resize\":\"fit\"},\"medium\":{\"w\":952,\"h\":937,\"resize\":\"fit\"}},\"source_status_id\":1210301628651364352,\"source_status_id_str\":\"1210301628651364352\",\"source_user_id\":927680014627241984,\"source_user_id_str\":\"927680014627241984\"}]},\"metadata\":{\"iso_language_code\":\"pt\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/android\\\" rel=\\\"nofollow\\\"\\u003eTwitter for Android\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":1224850562123997185,\"id_str\":\"1224850562123997185\",\"name\":\"brisado\",\"screen_name\":\"oubrisado\",\"location\":\"\",\"description\":\"o mais brisado desse site\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":37347,\"friends_count\":2,\"listed_count\":12,\"created_at\":\"Wed Feb 05 00:21:59 +0000 2020\",\"favourites_count\":0,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":293,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1247598226791858184\\\/DHOMTvrj_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1247598226791858184\\\/DHOMTvrj_normal.jpg\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":2309,\"favorite_count\":4939,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"pt\"},\"is_quote_status\":false,\"retweet_count\":2309,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"pt\"},{\"created_at\":\"Sun Apr 26 00:31:49 +0000 2020\",\"id\":1254206511431196678,\"id_str\":\"1254206511431196678\",\"text\":\"RT @DistinCray_: I\\u2019m crying he said yall gon see this WAIST \\ud83d\\ude2d\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"DistinCray_\",\"name\":\"AK\",\"id\":180398421,\"id_str\":\"180398421\",\"indices\":[3,15]}],\"urls\":[]},\"metadata\":{\"iso_language_code\":\"en\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":303139504,\"id_str\":\"303139504\",\"name\":\"koshie\",\"screen_name\":\"bethellana_\",\"location\":\"london\",\"description\":\"\\ud83c\\uddec\\ud83c\\udded\\ud83d\\udc78\\ud83c\\udffe\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":208,\"friends_count\":93,\"listed_count\":0,\"created_at\":\"Sun May 22 10:59:13 +0000 2011\",\"favourites_count\":5392,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":19373,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"FCEBB6\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme4\\\/bg.gif\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme4\\\/bg.gif\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1215383177281310720\\\/uESNsmy0_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1215383177281310720\\\/uESNsmy0_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/303139504\\\/1578604905\",\"profile_link_color\":\"CE7834\",\"profile_sidebar_border_color\":\"F0A830\",\"profile_sidebar_fill_color\":\"78C0A8\",\"profile_text_color\":\"5E412F\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Sat Apr 25 21:07:31 +0000 2020\",\"id\":1254155098160279553,\"id_str\":\"1254155098160279553\",\"text\":\"I\\u2019m crying he said yall gon see this WAIST \\ud83d\\ude2d https:\\\/\\\/t.co\\\/4RAOYyntaH\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/4RAOYyntaH\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/gloriaolembo\\\/status\\\/1254136568417259521\",\"display_url\":\"twitter.com\\\/gloriaolembo\\\/s\\u2026\",\"indices\":[45,68]}]},\"metadata\":{\"iso_language_code\":\"en\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":180398421,\"id_str\":\"180398421\",\"name\":\"AK\",\"screen_name\":\"DistinCray_\",\"location\":\"\",\"description\":\"patterner | R2R\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":2850,\"friends_count\":459,\"listed_count\":53,\"created_at\":\"Thu Aug 19 14:56:56 +0000 2010\",\"favourites_count\":19893,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":217009,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"642D8B\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1254168218601652233\\\/dq4evs0i_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1254168218601652233\\\/dq4evs0i_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/180398421\\\/1579979760\",\"profile_link_color\":\"FF0000\",\"profile_sidebar_border_color\":\"65B0DA\",\"profile_sidebar_fill_color\":\"7AC3EE\",\"profile_text_color\":\"3D1957\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":true,\"quoted_status_id\":1254136568417259521,\"quoted_status_id_str\":\"1254136568417259521\",\"quoted_status\":{\"created_at\":\"Sat Apr 25 19:53:53 +0000 2020\",\"id\":1254136568417259521,\"id_str\":\"1254136568417259521\",\"text\":\"Il n\\u2019a pas comprit le concept \\ud83d\\ude05\\n#confinement https:\\\/\\\/t.co\\\/j0pvvaXqF2\",\"truncated\":false,\"entities\":{\"hashtags\":[{\"text\":\"confinement\",\"indices\":[32,44]}],\"symbols\":[],\"user_mentions\":[],\"urls\":[],\"media\":[{\"id\":1254136503258808321,\"id_str\":\"1254136503258808321\",\"indices\":[45,68],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254136503258808321\\\/pu\\\/img\\\/F6zOsn8Id0qYrRNO.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254136503258808321\\\/pu\\\/img\\\/F6zOsn8Id0qYrRNO.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/j0pvvaXqF2\",\"display_url\":\"pic.twitter.com\\\/j0pvvaXqF2\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/GloriaOlembo\\\/status\\\/1254136568417259521\\\/video\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"medium\":{\"w\":540,\"h\":960,\"resize\":\"fit\"},\"small\":{\"w\":383,\"h\":680,\"resize\":\"fit\"},\"large\":{\"w\":540,\"h\":960,\"resize\":\"fit\"}}}]},\"extended_entities\":{\"media\":[{\"id\":1254136503258808321,\"id_str\":\"1254136503258808321\",\"indices\":[45,68],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254136503258808321\\\/pu\\\/img\\\/F6zOsn8Id0qYrRNO.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254136503258808321\\\/pu\\\/img\\\/F6zOsn8Id0qYrRNO.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/j0pvvaXqF2\",\"display_url\":\"pic.twitter.com\\\/j0pvvaXqF2\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/GloriaOlembo\\\/status\\\/1254136568417259521\\\/video\\\/1\",\"type\":\"video\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"medium\":{\"w\":540,\"h\":960,\"resize\":\"fit\"},\"small\":{\"w\":383,\"h\":680,\"resize\":\"fit\"},\"large\":{\"w\":540,\"h\":960,\"resize\":\"fit\"}},\"video_info\":{\"aspect_ratio\":[9,16],\"duration_millis\":13078,\"variants\":[{\"bitrate\":632000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254136503258808321\\\/pu\\\/vid\\\/320x568\\\/AVnszQa6W9q7c04O.mp4?tag=10\"},{\"bitrate\":832000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254136503258808321\\\/pu\\\/vid\\\/360x640\\\/Xy2jSsmTHBHeOUUi.mp4?tag=10\"},{\"content_type\":\"application\\\/x-mpegURL\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254136503258808321\\\/pu\\\/pl\\\/OKaz96Nq0Hw-jSDL.m3u8?tag=10\"},{\"bitrate\":2176000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254136503258808321\\\/pu\\\/vid\\\/540x960\\\/2pgtZuZG3AfQD02w.mp4?tag=10\"}]},\"additional_media_info\":{\"monetizable\":false}}]},\"metadata\":{\"iso_language_code\":\"en\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":1164591021008834563,\"id_str\":\"1164591021008834563\",\"name\":\"ITS MY BDAY\\ud83e\\udd73\",\"screen_name\":\"GloriaOlembo\",\"location\":\"Bruxelles, Belgique\",\"description\":\"1m66 de douceur insta: gloriaolembo\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":381,\"friends_count\":87,\"listed_count\":0,\"created_at\":\"Thu Aug 22 17:32:01 +0000 2019\",\"favourites_count\":611,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":588,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1251225268817137670\\\/E5x_QB1R_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1251225268817137670\\\/E5x_QB1R_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/1164591021008834563\\\/1584457034\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":17716,\"favorite_count\":38440,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":true,\"lang\":\"fr\"},\"retweet_count\":8577,\"favorite_count\":30825,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"en\"},\"is_quote_status\":true,\"quoted_status_id\":1254136568417259521,\"quoted_status_id_str\":\"1254136568417259521\",\"retweet_count\":8577,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"en\"},{\"created_at\":\"Sun Apr 26 00:31:49 +0000 2020\",\"id\":1254206511397531648,\"id_str\":\"1254206511397531648\",\"text\":\"RT @TomoccoryShow: #tmcckor\",\"truncated\":false,\"entities\":{\"hashtags\":[{\"text\":\"tmcckor\",\"indices\":[19,27]}],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"TomoccoryShow\",\"name\":\"TomoccoryShow\",\"id\":1230575068989681664,\"id_str\":\"1230575068989681664\",\"indices\":[3,17]}],\"urls\":[]},\"metadata\":{\"iso_language_code\":\"und\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":720932439892238337,\"id_str\":\"720932439892238337\",\"name\":\"\\u3080\\u304e\\u306e\\u3053\\u3080\\u304e\",\"screen_name\":\"hironet1215\",\"location\":\"\\u65e5\\u672c\",\"description\":\"\\u3080\\u304e\\u306e\\u306f\\u6c38\\u9060\\u306e\\u76f8\\u65b9\\u3002\\u30d3\\u30fc10\\u30ea\\u30b9\\u30ca\\u30fc\\u3053\\u3068\\u30c6\\u30f3\\u30c0\\u30fc\\u3002\\u97f3\\u697d\\u306f\\u52ff\\u8ad6\\u3001\\u6620\\u753b\\u3001\\u672c\\u3001\\u30a2\\u30cb\\u30e1\\u3001\\u5b50\\u3069\\u3082\\u305f\\u3061\\u3068\\u793e\\u4f1a\\u306e\\u3053\\u3068\\u306a\\u3069\\u3001\\u6c17\\u7d1b\\u308c\\u306b\\u545f\\u304d\\u307e\\u3059\\u3002\\u57fa\\u672c\\u306f\\u30ce\\u30ea\\u30c4\\u30c3\\u30b3\\u30df\\u62c5\\u5f53\\u3067\\u3059\\u3002\\u3088\\u308d\\u3057\\u304f\\u304a\\u9858\\u3044\\u3057\\u307e\\u3059\\u3002\\u3053\\u3080\\u304e\\u3068\\u304a\\u547c\\u3073\\u4e0b\\u3055\\u3044\\u3002\\u30df\\u30e5\\u30fc\\u30c8\\u3001\\u30ea\\u30e0\\u3001\\u30d6\\u30ed\\u306f\\u3054\\u81ea\\u7531\\u306b\\u9858\\u3044\\u307e\\u3059\\u3002\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":113,\"friends_count\":149,\"listed_count\":5,\"created_at\":\"Fri Apr 15 11:11:02 +0000 2016\",\"favourites_count\":20307,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":13310,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1247744690700476417\\\/_u3TUqxg_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1247744690700476417\\\/_u3TUqxg_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/720932439892238337\\\/1587232671\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Sun Apr 26 00:25:57 +0000 2020\",\"id\":1254205036227203072,\"id_str\":\"1254205036227203072\",\"text\":\"#tmcckor https:\\\/\\\/t.co\\\/qc2mjHqTar\",\"truncated\":false,\"entities\":{\"hashtags\":[{\"text\":\"tmcckor\",\"indices\":[0,8]}],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/qc2mjHqTar\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/t_moco2\\\/status\\\/1254204582508429312\",\"display_url\":\"twitter.com\\\/t_moco2\\\/status\\u2026\",\"indices\":[9,32]}]},\"metadata\":{\"iso_language_code\":\"und\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":1230575068989681664,\"id_str\":\"1230575068989681664\",\"name\":\"TomoccoryShow\",\"screen_name\":\"TomoccoryShow\",\"location\":\"\",\"description\":\"@t_moco2\\u304c\\u61d0\\u304b\\u3057\\u3044\\u3068\\u601d\\u3046\\u66f2\\u3060\\u3051\\u304b\\u3051\\u7d9a\\u3051\\u308b\\u300c\\u30c8\\u30e2\\u30c3\\u30b3\\u30ea\\u30fc\\u30fb\\u30b7\\u30e7\\u30fc\\u300d\\u3002\\u653e\\u9001\\u5c40\\u7d9a\\u3005\\u8ffd\\u52a0\\u4e2d\\u3002\\u653e\\u9001\\u30b9\\u30b1\\u30b8\\u30e5\\u30fc\\u30eb\\u306fhttps:\\\/\\\/t.co\\\/AgT1KK4Y2H \\u3067\\u30c1\\u30a7\\u30c3\\u30af\\u3002#tmcckor\",\"url\":null,\"entities\":{\"description\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/AgT1KK4Y2H\",\"expanded_url\":\"http:\\\/\\\/radiomagazine.amebaownd.com\",\"display_url\":\"radiomagazine.amebaownd.com\",\"indices\":[55,78]}]}},\"protected\":false,\"followers_count\":252,\"friends_count\":543,\"listed_count\":1,\"created_at\":\"Thu Feb 20 19:29:10 +0000 2020\",\"favourites_count\":219,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":634,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1240274193385533440\\\/KyD_wuBz_normal.png\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1240274193385533440\\\/KyD_wuBz_normal.png\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/1230575068989681664\\\/1582364243\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":true,\"quoted_status_id\":1254204582508429312,\"quoted_status_id_str\":\"1254204582508429312\",\"quoted_status\":{\"created_at\":\"Sun Apr 26 00:24:09 +0000 2020\",\"id\":1254204582508429312,\"id_str\":\"1254204582508429312\",\"text\":\"\\u3053\\u306e\\u5f8c10\\u6642\\u304b\\u3089\\u301c\\uff01#tmcckor https:\\\/\\\/t.co\\\/J4G9Drx4eU\",\"truncated\":false,\"entities\":{\"hashtags\":[{\"text\":\"tmcckor\",\"indices\":[10,18]}],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/J4G9Drx4eU\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/mikeintokyo2004\\\/status\\\/1254204363582521347\",\"display_url\":\"twitter.com\\\/mikeintokyo200\\u2026\",\"indices\":[19,42]}]},\"metadata\":{\"iso_language_code\":\"und\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":29117715,\"id_str\":\"29117715\",\"name\":\"\\ud835\\ude9d\\ud835\\ude8a\\ud835\\ude90\\ud835\\ude9e\\ud835\\ude8c\\ud835\\ude91\\ud835\\ude92 \\ud835\\udd65\\ud835\\udd60\\ud835\\udd5e\\ud835\\udd60\\ud835\\udd5c\\ud835\\udd60\",\"screen_name\":\"t_moco2\",\"location\":\"\\u30d5\\u30a1\\u30f3\\u30bf\\u30b8\\u30fc\\u306e\\u753a\\u3001\\u5ddd\\u5d0e\",\"description\":\"\\u7530\\u53e3\\u667a\\u5b50\\u3002\\u5ddd\\u5d0e\\u5e02\\u6c11\\u3002\\u30e9\\u30b8\\u30aa\\u756a\\u7d44\\u5236\\u4f5c\\u3092\\u4e2d\\u5fc3\\u3068\\u3057\\u305f\\u81ea\\u55b6\\u696d\\u3002\\u597d\\u304d\\u306a\\u306e\\u306f\\u6cf3\\u3050\\u4e8b\\u3001\\u30c9\\u30e9\\u30a4\\u30d6\\u3001\\u5c0f\\u7b20\\u539f\\u9053\\u5927\\u3001\\u6d77\\u5916\\u30c9\\u30e9\\u30de\\u3001\\u30d1\\u30f3\\u3001\\u5bd2\\u5929\\u3001\\u300c\\u30ab\\u30c3\\u30b3\\u3044\\u3044\\u300d\\u7269\\u3002\\u300c\\u304b\\u308f\\u3044\\u3044\\u300d\\u4eba\\u3002tomoko\\u306e\\u8cea\\u554f\\u7bb1\\u2192 https:\\\/\\\/t.co\\\/cCAlxTN9Yi\",\"url\":\"https:\\\/\\\/t.co\\\/LkqhNiLYNt\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/LkqhNiLYNt\",\"expanded_url\":\"https:\\\/\\\/radiomagazine.amebaownd.com\\\/\",\"display_url\":\"radiomagazine.amebaownd.com\",\"indices\":[0,23]}]},\"description\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/cCAlxTN9Yi\",\"expanded_url\":\"https:\\\/\\\/peing.net\\\/t_moco2\",\"display_url\":\"peing.net\\\/t_moco2\",\"indices\":[88,111]}]}},\"protected\":false,\"followers_count\":798,\"friends_count\":452,\"listed_count\":29,\"created_at\":\"Mon Apr 06 01:46:48 +0000 2009\",\"favourites_count\":4098,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":27121,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"E80743\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme3\\\/bg.gif\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme3\\\/bg.gif\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/770680258982928384\\\/t9gkXR9j_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/770680258982928384\\\/t9gkXR9j_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/29117715\\\/1409324949\",\"profile_link_color\":\"B50164\",\"profile_sidebar_border_color\":\"B7195B\",\"profile_sidebar_fill_color\":\"AA0645\",\"profile_text_color\":\"F21365\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":true,\"quoted_status_id\":1254204363582521347,\"quoted_status_id_str\":\"1254204363582521347\",\"retweet_count\":3,\"favorite_count\":4,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"ja\"},\"retweet_count\":1,\"favorite_count\":1,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"und\"},\"is_quote_status\":true,\"quoted_status_id\":1254204582508429312,\"quoted_status_id_str\":\"1254204582508429312\",\"retweet_count\":1,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"und\"},{\"created_at\":\"Sun Apr 26 00:31:48 +0000 2020\",\"id\":1254206511355592704,\"id_str\":\"1254206511355592704\",\"text\":\"RT @kantanlife2019: \\ud83d\\udce2\\u304a\\u3046\\u3061\\u3067\\u98df\\u3079\\u308b\\u30ad\\u30e3\\u30f3\\u30da\\u30fc\\u30f3\\uff01\\uff01\\n #\\u81ea\\u7c9b\\n\\ud83d\\udc9c\\u5bb6\\u306b\\u3044\\u308b\\u6a5f\\u4f1a\\u304c\\u5897\\u3048\\u308b\\u3068 \\u30b9\\u30c8\\u30ec\\u30b9\\u6e9c\\u307e\\u3063\\u3066\\u7518\\u3044\\u3082\\u306e\\u6b32\\u3057\\u304f\\u306a\\u308a\\u307e\\u305b\\u3093\\uff1f\\n#\\u30b3\\u30ed\\u30ca\\u306b\\u8ca0\\u3051\\u308b\\u306a \\n\\ud83c\\udf69\\u62bd\\u9078\\u30673\\u540d\\u69d8\\u306b\\u30d7\\u30ec\\u30bc\\u30f3\\u30c8 \\u2b07\\ufe0f\\n\\u30d6\\u30eb\\u30dc\\u30f3 35\\u888b\\u5165\\n#\\u304a\\u304b\\u3057\\u3064\\u306a\\u304e \\u306b\\u53c2\\u52a0\\u3055\\u305b\\u3066\\u3044\\u305f\\u3060\\u304d\\u307e\\u3059\\uff01\\n\\u2728\\u5fdc\\u2026\",\"truncated\":false,\"entities\":{\"hashtags\":[{\"text\":\"\\u81ea\\u7c9b\",\"indices\":[38,41]},{\"text\":\"\\u30b3\\u30ed\\u30ca\\u306b\\u8ca0\\u3051\\u308b\\u306a\",\"indices\":[77,86]},{\"text\":\"\\u304a\\u304b\\u3057\\u3064\\u306a\\u304e\",\"indices\":[115,122]}],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"kantanlife2019\",\"name\":\"Kantanlife\",\"id\":1163377400081612800,\"id_str\":\"1163377400081612800\",\"indices\":[3,18]}],\"urls\":[]},\"metadata\":{\"iso_language_code\":\"ja\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":752359744111714304,\"id_str\":\"752359744111714304\",\"name\":\"\\u3072\\u308d\\u307d\\u307d\\u3061\\u301c\\u305f\\u3093\",\"screen_name\":\"jbfzfSGmzd2WTsL\",\"location\":\"\\u65e5\\u672c\\u3001\\u795e\\u5948\\u5ddd\\u770c\\u6a2a\\u6d5c\",\"description\":\"2017\\u5e741\\u6708\\u304b\\u3089\\u7bc0\\u7d04\\u3092\\u517c\\u306d\\u61f8\\u8cde\\u5fdc\\u52df\\u3092\\u59cb\\u3081\\u3066\\u307f\\u307e\\u3057\\u305f\\u2728\\u3068\\u3053\\u308d\\u304c\\u3001Twitter\\u61f8\\u8cde\\u2026\\u4e2d\\u3005\\u5f53\\u305f\\u3089\\u306a\\u3044\\u3067\\u3059\\u306d\\ud83d\\ude22\\u6804\\u990a\\u58eb\\u306e\\u52c9\\u5f37\\u3002\\u6bcd\\u306e\\u30ea\\u30cf\\u30d3\\u30ea\\u30fb\\u5728\\u5b85\\u4ecb\\u8b77\\u306b\\u65e5\\u3005\\u596e\\u95d8\\u3057\\u3066\\u307e\\u3059\\u3002\\u75db\\u307f\\u3092\\u62b1\\u3048\\u306a\\u304c\\u3089\\u3082\\u5171\\u306b\\u524d\\u5411\\u304d\\u306b\\u6b69\\u3093\\u3067\\u304f\\u308c\\u308b\\u6bcd\\u3068\\u4e00\\u7dd2\\u306b\\u3044\\u3064\\u307e\\u3067\\u904e\\u3054\\u305b\\u308b\\u304b\\u2026 \\u3002\\u611b\\u732bPua\\u541b\\u3001\\u611b\\u72acJAZZ\\u541b\\u306e\\u6210\\u9577\\u8a18\\u9332\\u3068\\u3057\\u3066\\u3082\\u5229\\u7528\\u3092\\u3055\\u305b\\u3066\\u9802\\u3044\\u3066\\u304a\\u308a\\u307e\\u3059\\u3002\",\"url\":\"https:\\\/\\\/t.co\\\/4DKgjYvApe\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/4DKgjYvApe\",\"expanded_url\":\"https:\\\/\\\/www.instagram.com\\\/ikumihiropopo\",\"display_url\":\"instagram.com\\\/ikumihiropopo\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":134,\"friends_count\":2103,\"listed_count\":1,\"created_at\":\"Mon Jul 11 04:31:55 +0000 2016\",\"favourites_count\":3093,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":10958,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/940231026038661120\\\/wBNpUy9N_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/940231026038661120\\\/wBNpUy9N_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/752359744111714304\\\/1509239794\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Fri Apr 24 09:23:10 +0000 2020\",\"id\":1253615456675495936,\"id_str\":\"1253615456675495936\",\"text\":\"\\ud83d\\udce2\\u304a\\u3046\\u3061\\u3067\\u98df\\u3079\\u308b\\u30ad\\u30e3\\u30f3\\u30da\\u30fc\\u30f3\\uff01\\uff01\\n #\\u81ea\\u7c9b\\n\\ud83d\\udc9c\\u5bb6\\u306b\\u3044\\u308b\\u6a5f\\u4f1a\\u304c\\u5897\\u3048\\u308b\\u3068 \\u30b9\\u30c8\\u30ec\\u30b9\\u6e9c\\u307e\\u3063\\u3066\\u7518\\u3044\\u3082\\u306e\\u6b32\\u3057\\u304f\\u306a\\u308a\\u307e\\u305b\\u3093\\uff1f\\n#\\u30b3\\u30ed\\u30ca\\u306b\\u8ca0\\u3051\\u308b\\u306a \\n\\ud83c\\udf69\\u62bd\\u9078\\u30673\\u540d\\u69d8\\u306b\\u30d7\\u30ec\\u30bc\\u30f3\\u30c8 \\u2b07\\ufe0f\\n\\u30d6\\u30eb\\u30dc\\u30f3 35\\u888b\\u5165\\n#\\u304a\\u304b\\u3057\\u3064\\u306a\\u304e \\u306b\\u53c2\\u52a0\\u3055\\u305b\\u3066\\u3044\\u305f\\u3060\\u304d\\u307e\\u3059\\u2026 https:\\\/\\\/t.co\\\/Ce2yCK3tj1\",\"truncated\":true,\"entities\":{\"hashtags\":[{\"text\":\"\\u81ea\\u7c9b\",\"indices\":[18,21]},{\"text\":\"\\u30b3\\u30ed\\u30ca\\u306b\\u8ca0\\u3051\\u308b\\u306a\",\"indices\":[57,66]},{\"text\":\"\\u304a\\u304b\\u3057\\u3064\\u306a\\u304e\",\"indices\":[95,102]}],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/Ce2yCK3tj1\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/i\\\/web\\\/status\\\/1253615456675495936\",\"display_url\":\"twitter.com\\\/i\\\/web\\\/status\\\/1\\u2026\",\"indices\":[117,140]}]},\"metadata\":{\"iso_language_code\":\"ja\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/mobile.twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web App\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":1163377400081612800,\"id_str\":\"1163377400081612800\",\"name\":\"Kantanlife\",\"screen_name\":\"kantanlife2019\",\"location\":\"\",\"description\":\"\\ud83c\\udf81\\u30d7\\u30ec\\u30bc\\u30f3\\u30c8\\u4f01\\u753b\\u958b\\u50ac\\u4e2d~ \\ud83d\\udde3\\u30c4\\u30a4\\u30bf\\u3067\\u8272\\u3093\\u306a\\u30ad\\u30e3\\u30f3\\u30da\\u30f3\\u30fc\\u3084\\u62bd\\u9078\\u3092\\u884c\\u3063\\u3066\\u3044\\u307e\\u3059\\u3001\\u305c\\u3072\\u30d5\\u30a9\\u30ed\\u30fc\\u3057\\u3066\\u304f\\u3060\\u3055\\u3044\\ud83e\\uddd8\\u200d\\u2640\\ufe0f \\ud83d\\udc9d\\u7121\\u6599\\u8a66\\u4f9b\\u54c1\\u63d0\\u4f9b\\u4e2d \\u203b\\u571f\\u66dc\\u30fb\\u65e5\\u66dc\\u30fb\\u795d\\u796d\\u65e5\\u306f\\u304a\\u4f11\\u307f\\u3092\\u3044\\u305f\\u3060\\u3044\\u3066\\u304a\\u308a\\u307e\\u3059\\u3002 \\u30e1\\u30fc\\u30eb\\u3001\\u304a\\u554f\\u3044\\u5408\\u308f\\u305b\\u306e\\u304a\\u8fd4\\u4e8b\\u306f\\u7fcc\\u55b6\\u696d\\u65e5\\u3068\\u306a\\u308a\\u307e\\u3059\\u3002 \\u2764\\u30b3\\u30e9\\u30dc\\u306f\\u5927\\u6b53\\u8fce!\\uff01 #8000\\u30d5\\u30a9\\u30ed\\u30fc\\u30ef\\u306e\\u304a\\u9858\\u3044 #\\u62e1\\u6563\\u5e0c\\u671b\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":6691,\"friends_count\":30,\"listed_count\":13,\"created_at\":\"Mon Aug 19 09:09:28 +0000 2019\",\"favourites_count\":527,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":209,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1236235021934977025\\\/aYI9CgxV_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1236235021934977025\\\/aYI9CgxV_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/1163377400081612800\\\/1583576667\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":2224,\"favorite_count\":550,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"ja\"},\"is_quote_status\":false,\"retweet_count\":2224,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"ja\"},{\"created_at\":\"Sun Apr 26 00:31:48 +0000 2020\",\"id\":1254206511288590338,\"id_str\":\"1254206511288590338\",\"text\":\"RT @RiZzyUTD: There are still some Chelsea fans who say \\\"Lampard > Ole\\\". Let me remind you, Lampard faced Ole 3 times (2x at home) this sea\\u2026\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"RiZzyUTD\",\"name\":\"RiZzy\\ud83d\\udd34\",\"id\":1113785724975890435,\"id_str\":\"1113785724975890435\",\"indices\":[3,12]}],\"urls\":[]},\"metadata\":{\"iso_language_code\":\"en\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/android\\\" rel=\\\"nofollow\\\"\\u003eTwitter for Android\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":942008384,\"id_str\":\"942008384\",\"name\":\"NwabuKing Alfonso\",\"screen_name\":\"AlfonsoNwab\",\"location\":\"Lagos\",\"description\":\"\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":514,\"friends_count\":2063,\"listed_count\":1,\"created_at\":\"Sun Nov 11 19:15:25 +0000 2012\",\"favourites_count\":26641,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":27703,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1178184591544336384\\\/jXp8EFVQ_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1178184591544336384\\\/jXp8EFVQ_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/942008384\\\/1442338235\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Sat Apr 25 15:51:27 +0000 2020\",\"id\":1254075557697986562,\"id_str\":\"1254075557697986562\",\"text\":\"There are still some Chelsea fans who say \\\"Lampard > Ole\\\". Let me remind you, Lampard faced Ole 3 times (2x at home\\u2026 https:\\\/\\\/t.co\\\/OZZHocU4ZE\",\"truncated\":true,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/OZZHocU4ZE\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/i\\\/web\\\/status\\\/1254075557697986562\",\"display_url\":\"twitter.com\\\/i\\\/web\\\/status\\\/1\\u2026\",\"indices\":[120,143]}]},\"metadata\":{\"iso_language_code\":\"en\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/android\\\" rel=\\\"nofollow\\\"\\u003eTwitter for Android\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":1113785724975890435,\"id_str\":\"1113785724975890435\",\"name\":\"RiZzy\\ud83d\\udd34\",\"screen_name\":\"RiZzyUTD\",\"location\":\"\",\"description\":\"@ManUtd Fan account | Private acc:@PrivRiz | \\ud83c\\uddf8\\ud83c\\uddf4\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":42282,\"friends_count\":2589,\"listed_count\":228,\"created_at\":\"Thu Apr 04 12:49:44 +0000 2019\",\"favourites_count\":121877,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":41101,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1253155559098003456\\\/FAM_cCLX_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1253155559098003456\\\/FAM_cCLX_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/1113785724975890435\\\/1586841143\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":281,\"favorite_count\":2766,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"en\"},\"is_quote_status\":false,\"retweet_count\":281,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"en\"},{\"created_at\":\"Sun Apr 26 00:31:48 +0000 2020\",\"id\":1254206511217143811,\"id_str\":\"1254206511217143811\",\"text\":\"RT @qootaro7: \\u5b54\\u660e\\u306f\\u7d46\\u30ec\\u30d9\\u30eb\\u4e0a\\u304c\\u308b\\u306e\\u3081\\u3063\\u3061\\u3083\\u9045\\u3044\\u3067\\u3059\\u304c\\u3001\\u5f7c\\u3092\\u77e5\\u308c\\u3070\\u77e5\\u308b\\u307b\\u3069\\u300e\\u3082\\u3063\\u3068\\u2026\\u9045\\u304f\\u3066\\u3044\\u3044\\u306e\\u3088\\u2026\\uff01\\uff01\\uff01\\u305d\\u308c\\u3067\\u3053\\u305d\\u2026\\u541b\\u3060\\u2026\\uff01\\u30a2\\u30e9\\u30e9\\u30a4\\u2026\\uff01\\u300f\\u3063\\u3066\\u306a\\u308a\\u307e\\u3059\\u3002\\n\\u3067\\u3082\\u4eca\\u56de\\u306f\\u7d46\\u30ec\\u30d9\\u30eb\\u4e0a\\u3052\\u306b\\u6642\\u9593\\u5236\\u9650\\u304c\\u3042\\u308b\\u306e\\u3067\\u3001\\u305d\\u306e\\u8fba\\u308a\\u6c17\\u3092\\u3064\\u3051\\u3066\\u30fc\\u3002 https:\\\/\\\/t.co\\\/Q8f71XG\\u2026\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"qootaro7\",\"name\":\"Fake6\\u5dfb\\u3092\\u8aad\\u3093\\u3060Qoo\\u305f\\u308d\\u30fc\",\"id\":726817725419397120,\"id_str\":\"726817725419397120\",\"indices\":[3,12]}],\"urls\":[]},\"metadata\":{\"iso_language_code\":\"ja\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/android\\\" rel=\\\"nofollow\\\"\\u003eTwitter for Android\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":195312634,\"id_str\":\"195312634\",\"name\":\"\\u306a\\u3080\\u306a\\u3080\",\"screen_name\":\"namunohi\",\"location\":\"\\u5343\\u8449\\u770c\",\"description\":\"\\u6210\\u4eba\\u6e08\\u8150\\u5973\\u5b50 \\u7dcf\\u4e00 \\u7dd1\\u9ad8 \\u5d50\\u8fc5 \\u30b6\\u30d7\\u30ec\\u30aa \\u30de\\u30fc\\u30ed\\u30de \\u5973\\u4f53\\u5316\\u611b\\u3057\\u3066\\u308b \\u767e\\u5408\\u3082\\u30d8\\u30c6\\u30ed\\u3082\\u5927\\u597d\\u7269 \\u81ea\\u5df1\\u5b8c\\u7d50\\u3059\\u308b\\u6027\\u8cea\\u306e\\u305f\\u3081\\u4f1a\\u8a71\\u304c\\u82e6\\u624b RT\\u9b54 \\u8003\\u5bdf\\u5927\\u597d\\u304d\\u3060\\u304c\\u81ea\\u5206\\u3067\\u3067\\u304d\\u308b\\u3068\\u306f\\u8a00\\u3063\\u3066\\u3044\\u306a\\u3044 \\u5357\\u7121\\u306e\\u65e5\\u751f\\u307e\\u308c\",\"url\":\"https:\\\/\\\/t.co\\\/zyXOarl5eN\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/zyXOarl5eN\",\"expanded_url\":\"https:\\\/\\\/fusetter.com\\\/u\\\/namunohi\",\"display_url\":\"fusetter.com\\\/u\\\/namunohi\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":294,\"friends_count\":565,\"listed_count\":50,\"created_at\":\"Sun Sep 26 11:10:51 +0000 2010\",\"favourites_count\":156962,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":538977,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"9AE4E8\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme16\\\/bg.gif\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme16\\\/bg.gif\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/495384537585573889\\\/RjXK-joV_normal.jpeg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/495384537585573889\\\/RjXK-joV_normal.jpeg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/195312634\\\/1470121689\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"BDDCAD\",\"profile_sidebar_fill_color\":\"DDFFCC\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Sat Apr 25 13:03:54 +0000 2020\",\"id\":1254033393991335937,\"id_str\":\"1254033393991335937\",\"text\":\"\\u5b54\\u660e\\u306f\\u7d46\\u30ec\\u30d9\\u30eb\\u4e0a\\u304c\\u308b\\u306e\\u3081\\u3063\\u3061\\u3083\\u9045\\u3044\\u3067\\u3059\\u304c\\u3001\\u5f7c\\u3092\\u77e5\\u308c\\u3070\\u77e5\\u308b\\u307b\\u3069\\u300e\\u3082\\u3063\\u3068\\u2026\\u9045\\u304f\\u3066\\u3044\\u3044\\u306e\\u3088\\u2026\\uff01\\uff01\\uff01\\u305d\\u308c\\u3067\\u3053\\u305d\\u2026\\u541b\\u3060\\u2026\\uff01\\u30a2\\u30e9\\u30e9\\u30a4\\u2026\\uff01\\u300f\\u3063\\u3066\\u306a\\u308a\\u307e\\u3059\\u3002\\n\\u3067\\u3082\\u4eca\\u56de\\u306f\\u7d46\\u30ec\\u30d9\\u30eb\\u4e0a\\u3052\\u306b\\u6642\\u9593\\u5236\\u9650\\u304c\\u3042\\u308b\\u306e\\u3067\\u3001\\u305d\\u306e\\u8fba\\u308a\\u6c17\\u3092\\u3064\\u3051\\u3066\\u30fc\\u3002 https:\\\/\\\/t.co\\\/Q8f71XGiNe\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[],\"media\":[{\"id\":1254033375712571395,\"id_str\":\"1254033375712571395\",\"indices\":[105,128],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWc4tgfU8AMtVte.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWc4tgfU8AMtVte.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/Q8f71XGiNe\",\"display_url\":\"pic.twitter.com\\\/Q8f71XGiNe\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/qootaro7\\\/status\\\/1254033393991335937\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":680,\"h\":382,\"resize\":\"fit\"},\"large\":{\"w\":1334,\"h\":750,\"resize\":\"fit\"},\"medium\":{\"w\":1200,\"h\":675,\"resize\":\"fit\"}}}]},\"extended_entities\":{\"media\":[{\"id\":1254033375712571395,\"id_str\":\"1254033375712571395\",\"indices\":[105,128],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWc4tgfU8AMtVte.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWc4tgfU8AMtVte.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/Q8f71XGiNe\",\"display_url\":\"pic.twitter.com\\\/Q8f71XGiNe\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/qootaro7\\\/status\\\/1254033393991335937\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":680,\"h\":382,\"resize\":\"fit\"},\"large\":{\"w\":1334,\"h\":750,\"resize\":\"fit\"},\"medium\":{\"w\":1200,\"h\":675,\"resize\":\"fit\"}}}]},\"metadata\":{\"iso_language_code\":\"ja\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":1254029743504031744,\"in_reply_to_status_id_str\":\"1254029743504031744\",\"in_reply_to_user_id\":726817725419397120,\"in_reply_to_user_id_str\":\"726817725419397120\",\"in_reply_to_screen_name\":\"qootaro7\",\"user\":{\"id\":726817725419397120,\"id_str\":\"726817725419397120\",\"name\":\"Fake6\\u5dfb\\u3092\\u8aad\\u3093\\u3060Qoo\\u305f\\u308d\\u30fc\",\"screen_name\":\"qootaro7\",\"location\":\"\",\"description\":\"\\u304f\\u30fc\\u305f\\u308d\\u30fc\\u3067\\u3059\\u3002\\u30a4\\u30b9\\u30ab\\u30f3\\u30c0\\u30eb\\uff08\\u5927\\u5c0f\\uff09\\u00d7\\u30a6\\u30a7\\u30a4\\u30d0\\u30fc\\uff08\\u5927\\u5c0f\\uff09 \\u30d5\\u30e9\\u2161\\u3068\\u30e1\\u30eb\\u2161\\u3082\\u3082\\u3050\\u3082\\u3050\\u3002\\u30b5\\u30ea\\u30a8\\u30ea\\u5148\\u751f\\u30fc\\uff01\\u30a8\\u30ed\\u3044\\u30fc\\uff01\\u30ea\\u30d0\\u306f\\u97f3\\u697d\\u6027\\u306e\\u9055\\u3044\\u3067\\u305d\\u3063\\u3068\\u96e2\\u308c\\u308b\\u3002\\u7121\\u8a00\\u30d5\\u30a9\\u30ed\\u30fc\\u5931\\u793c\\u81f4\\u3057\\u307e\\u3059 \\u6210\\u4eba\\u6e08\\u3067\\u3059\\u308f\\u3088\\u3002\\u3074\\u304f\\u3057\\u3076\\uff1ahttps:\\\/\\\/t.co\\\/lCgu9WQyrN\",\"url\":null,\"entities\":{\"description\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/lCgu9WQyrN\",\"expanded_url\":\"https:\\\/\\\/pixiv.me\\\/ku2222\",\"display_url\":\"pixiv.me\\\/ku2222\",\"indices\":[98,121]}]}},\"protected\":false,\"followers_count\":787,\"friends_count\":135,\"listed_count\":18,\"created_at\":\"Sun May 01 16:57:04 +0000 2016\",\"favourites_count\":17309,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":19510,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/891533014697562112\\\/j6zQ2wH8_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/891533014697562112\\\/j6zQ2wH8_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/726817725419397120\\\/1501392666\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":7,\"favorite_count\":11,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"ja\"},\"is_quote_status\":false,\"retweet_count\":7,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"ja\"},{\"created_at\":\"Sun Apr 26 00:31:48 +0000 2020\",\"id\":1254206511204700160,\"id_str\":\"1254206511204700160\",\"text\":\"RT @SharqiyaOyun: \\u2733\\ufe0f \\u0627\\u0644\\u0633\\u0624\\u0627\\u0644 \\u0627\\u0644\\u062b\\u0627\\u0646\\u064a :\\n\\u0622\\u064a\\u0629 \\u0641\\u064a #\\u0627\\u0644\\u0642\\u0631\\u0622\\u0646 \\u062c\\u0645\\u0639\\u062a \\u0623\\u0631\\u0628\\u0639\\u0629 \\u0623\\u0633\\u0628\\u0627\\u0628 \\u062a\\u062f\\u0631\\u0643 \\u0628\\u0647\\u0627 #\\u0645\\u063a\\u0641\\u0631\\u0629 \\u0627\\u0644\\u0644\\u0647 \\u0644\\u0644\\u0639\\u0628\\u062f \\u0623\\u0630\\u0643\\u0631\\u0647\\u0627 \\u061f \\n\\u0646\\u0633\\u062a\\u0642\\u0628\\u0644 \\u0627\\u0644\\u0625\\u062c\\u0627\\u0628\\u0627\\u062a \\u062d\\u062a\\u0649 \\u063a\\u062f\\u0627\\u064b \\u0627\\u0644\\u0640 10\\u0645\\u2026\",\"truncated\":false,\"entities\":{\"hashtags\":[{\"text\":\"\\u0627\\u0644\\u0642\\u0631\\u0622\\u0646\",\"indices\":[44,51]},{\"text\":\"\\u0645\\u063a\\u0641\\u0631\\u0629\",\"indices\":[78,84]}],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"SharqiyaOyun\",\"name\":\"\\u0639\\u064a\\u0648\\u0646 \\u0627\\u0644\\u0634\\u0631\\u0642\\u064a\\u0629 \\ud83c\\uddf8\\ud83c\\udde6\",\"id\":3327219576,\"id_str\":\"3327219576\",\"indices\":[3,16]}],\"urls\":[]},\"metadata\":{\"iso_language_code\":\"ar\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/android\\\" rel=\\\"nofollow\\\"\\u003eTwitter for Android\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":1237722641483681792,\"id_str\":\"1237722641483681792\",\"name\":\"\\u0627\\u0645 \\u0633\\u0644\\u0637\\u0627\\u0646 #\",\"screen_name\":\"HVrw0HcoBkavAo5\",\"location\":\"\",\"description\":\"\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":72,\"friends_count\":728,\"listed_count\":0,\"created_at\":\"Wed Mar 11 12:51:07 +0000 2020\",\"favourites_count\":2591,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":3335,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1246136541015146496\\\/JZifYs9r_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1246136541015146496\\\/JZifYs9r_normal.jpg\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Sat Apr 25 19:35:17 +0000 2020\",\"id\":1254131886697431045,\"id_str\":\"1254131886697431045\",\"text\":\"\\u2733\\ufe0f \\u0627\\u0644\\u0633\\u0624\\u0627\\u0644 \\u0627\\u0644\\u062b\\u0627\\u0646\\u064a :\\n\\u0622\\u064a\\u0629 \\u0641\\u064a #\\u0627\\u0644\\u0642\\u0631\\u0622\\u0646 \\u062c\\u0645\\u0639\\u062a \\u0623\\u0631\\u0628\\u0639\\u0629 \\u0623\\u0633\\u0628\\u0627\\u0628 \\u062a\\u062f\\u0631\\u0643 \\u0628\\u0647\\u0627 #\\u0645\\u063a\\u0641\\u0631\\u0629 \\u0627\\u0644\\u0644\\u0647 \\u0644\\u0644\\u0639\\u0628\\u062f \\u0623\\u0630\\u0643\\u0631\\u0647\\u0627 \\u061f \\n\\u0646\\u0633\\u062a\\u0642\\u0628\\u0644 \\u0627\\u0644\\u0625\\u062c\\u0627\\u0628\\u0627\\u062a \\u062d\\u062a\\u0649 \\u063a\\u062f\\u0627\\u064b \\u0627\\u0644\\u2026 https:\\\/\\\/t.co\\\/KYsIapnzTI\",\"truncated\":true,\"entities\":{\"hashtags\":[{\"text\":\"\\u0627\\u0644\\u0642\\u0631\\u0622\\u0646\",\"indices\":[26,33]},{\"text\":\"\\u0645\\u063a\\u0641\\u0631\\u0629\",\"indices\":[60,66]}],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/KYsIapnzTI\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/i\\\/web\\\/status\\\/1254131886697431045\",\"display_url\":\"twitter.com\\\/i\\\/web\\\/status\\\/1\\u2026\",\"indices\":[117,140]}]},\"metadata\":{\"iso_language_code\":\"ar\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":3327219576,\"id_str\":\"3327219576\",\"name\":\"\\u0639\\u064a\\u0648\\u0646 \\u0627\\u0644\\u0634\\u0631\\u0642\\u064a\\u0629 \\ud83c\\uddf8\\ud83c\\udde6\",\"screen_name\":\"SharqiyaOyun\",\"location\":\"\",\"description\":\"| \\u0645\\u0646\\u0635\\u0629 #\\u0625\\u0639\\u0644\\u0627\\u0645\\u064a\\u0629 \\u0644\\u0646\\u0634\\u0631 #\\u0623\\u062d\\u062f\\u0627\\u062b \\u0648 #\\u0641\\u0639\\u0627\\u0644\\u064a\\u0627\\u062a \\u0648 #\\u0625\\u0639\\u0644\\u0627\\u0646\\u0627\\u062a #\\u0627\\u0644\\u0645\\u0646\\u0637\\u0642\\u0629_\\u0627\\u0644\\u0634\\u0631\\u0642\\u064a\\u0629 #\\u062a\\u0647\\u062f\\u0641 \\u0644\\u0625\\u064a\\u062c\\u0627\\u062f \\u0625\\u0639\\u0644\\u0627\\u0645 #\\u0646\\u0627\\u062c\\u062d #\\u0645\\u0633\\u0624\\u0648\\u0644 \\u062a\\u062c\\u0627\\u0647 #\\u0648\\u0637\\u0646\\u0647 \\u0648\\u0645\\u062c\\u062a\\u0645\\u0639\\u0647 \\u0648\\u0641\\u0642\\u0627\\u064b #\\u0644\\u0631\\u0624\\u064a\\u0629 2030 \\u0628\\u0640 #\\u0625\\u0634\\u0631\\u0627\\u0641 \\u0641\\u0631\\u064a\\u0642 #\\u0625\\u0639\\u0644\\u0627\\u0645\\u064a\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":56770,\"friends_count\":202,\"listed_count\":97,\"created_at\":\"Sun Aug 23 21:50:25 +0000 2015\",\"favourites_count\":3920,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":39511,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1179520814296784896\\\/Dj5_aP9F_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1179520814296784896\\\/Dj5_aP9F_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/3327219576\\\/1587401418\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":1660,\"favorite_count\":638,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"ar\"},\"is_quote_status\":false,\"retweet_count\":1660,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"ar\"},{\"created_at\":\"Sun Apr 26 00:31:48 +0000 2020\",\"id\":1254206511171031041,\"id_str\":\"1254206511171031041\",\"text\":\"@PeterSchiff Peter they\\u2019ve got an old pic of you. Get them to update with your Twitter pic. You look older and wise\\u2026 https:\\\/\\\/t.co\\\/IUo7JDo2u9\",\"truncated\":true,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"PeterSchiff\",\"name\":\"Peter Schiff\",\"id\":56562803,\"id_str\":\"56562803\",\"indices\":[0,12]}],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/IUo7JDo2u9\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/i\\\/web\\\/status\\\/1254206511171031041\",\"display_url\":\"twitter.com\\\/i\\\/web\\\/status\\\/1\\u2026\",\"indices\":[117,140]}]},\"metadata\":{\"iso_language_code\":\"en\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":1253764294421987329,\"in_reply_to_status_id_str\":\"1253764294421987329\",\"in_reply_to_user_id\":56562803,\"in_reply_to_user_id_str\":\"56562803\",\"in_reply_to_screen_name\":\"PeterSchiff\",\"user\":{\"id\":39978586,\"id_str\":\"39978586\",\"name\":\"Steve JB\",\"screen_name\":\"rhcp_steve\",\"location\":\"\",\"description\":\"\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":8,\"friends_count\":34,\"listed_count\":0,\"created_at\":\"Thu May 14 11:59:30 +0000 2009\",\"favourites_count\":136,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":151,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/sticky\\\/default_profile_images\\\/default_profile_normal.png\",\"profile_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/sticky\\\/default_profile_images\\\/default_profile_normal.png\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":true,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":0,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"en\"}],\"search_metadata\":{\"completed_in\":0.104,\"max_id\":1254206512068734977,\"max_id_str\":\"1254206512068734977\",\"next_results\":\"?max_id=1254206511171031040&q=twitter&include_entities=1\",\"query\":\"twitter\",\"refresh_url\":\"?since_id=1254206512068734977&q=twitter&include_entities=1\",\"count\":15,\"since_id\":0,\"since_id_str\":\"0\"}}" - } -}] \ No newline at end of file diff --git a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testGetSearchTweetsWithMaxId.json b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testGetSearchTweetsWithMaxId.json deleted file mode 100644 index 0a6471cd4..000000000 --- a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testGetSearchTweetsWithMaxId.json +++ /dev/null @@ -1,46 +0,0 @@ -[{ - "request": { - "method": "GET", - "url": "https:\/\/api.twitter.com\/1.1\/search\/tweets.json?max_id=1254206511171031041&q=twitter", - "headers": { - "Host": "api.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"OPWXmWD4p%2FgCquqMxYnispg%2BJnI%3D\"", - "Expect": null - } - }, - "response": { - "status": { - "http_version": "2", - "code": "200", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-disposition": "attachment; filename=json.json", - "content-encoding": "gzip", - "content-length": "13698", - "content-type": "application\/json;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:31:50 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:31:50 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_xE9B4fzDXgzvJ7jG6MLNsw==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:50 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786111059256410; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:50 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "200 OK", - "strict-transport-security": "max-age=631138519", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "dfeb32ee81ac07fc5a2c05cd515a12eb", - "x-content-type-options": "nosniff", - "x-frame-options": "SAMEORIGIN", - "x-rate-limit-limit": "180", - "x-rate-limit-remaining": "175", - "x-rate-limit-reset": "1587861623", - "x-response-time": "199", - "x-transaction": "000aa9600062bd1e", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "0" - }, - "body": "{\"statuses\":[{\"created_at\":\"Sun Apr 26 00:31:48 +0000 2020\",\"id\":1254206511171031041,\"id_str\":\"1254206511171031041\",\"text\":\"@PeterSchiff Peter they\\u2019ve got an old pic of you. Get them to update with your Twitter pic. You look older and wise\\u2026 https:\\\/\\\/t.co\\\/IUo7JDo2u9\",\"truncated\":true,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"PeterSchiff\",\"name\":\"Peter Schiff\",\"id\":56562803,\"id_str\":\"56562803\",\"indices\":[0,12]}],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/IUo7JDo2u9\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/i\\\/web\\\/status\\\/1254206511171031041\",\"display_url\":\"twitter.com\\\/i\\\/web\\\/status\\\/1\\u2026\",\"indices\":[117,140]}]},\"metadata\":{\"iso_language_code\":\"en\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":1253764294421987329,\"in_reply_to_status_id_str\":\"1253764294421987329\",\"in_reply_to_user_id\":56562803,\"in_reply_to_user_id_str\":\"56562803\",\"in_reply_to_screen_name\":\"PeterSchiff\",\"user\":{\"id\":39978586,\"id_str\":\"39978586\",\"name\":\"Steve JB\",\"screen_name\":\"rhcp_steve\",\"location\":\"\",\"description\":\"\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":8,\"friends_count\":34,\"listed_count\":0,\"created_at\":\"Thu May 14 11:59:30 +0000 2009\",\"favourites_count\":136,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":151,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/sticky\\\/default_profile_images\\\/default_profile_normal.png\",\"profile_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/sticky\\\/default_profile_images\\\/default_profile_normal.png\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":true,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":0,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"en\"},{\"created_at\":\"Sun Apr 26 00:31:48 +0000 2020\",\"id\":1254206511166836736,\"id_str\":\"1254206511166836736\",\"text\":\"RT @raffine_svtww: \\ud30c\\ud2b8 \\uc801\\uc740 4\\uba85 \\uc911\\uc5d0 \\uadf8\\ub798\\ub3c4 \\uadf8\\ub098\\ub9c8 \\uc138\\uba85\\uc740 \\ud37c\\ud3ec\\ud300\\uc774\\ub77c \\ubb34\\ub300 \\uc704\\uc5d0\\uc11c \\uc548\\ubb34\\ud558\\ub294 \\uac74 \\ubcf4\\uc774\\ub294\\ub370 \\uc6d0\\uc6b0\\ub294 \\ud30c\\ud2b8\\ub3c4 \\uc801\\uc740\\ub370 \\ub3d9\\uc120\\ub3c4 \\ub9e8\\ub0a0 \\ub4b7\\ub4b7\\uc904,\\ub4b7\\ub4b7\\ub4b7\\uc904\\uc774\\ub77c \\ubb34\\ub300 \\uc704\\uc5d0\\uc11c \\uba64\\ubc84 \\uc548 \\uac78\\ub9b0 \\uc0c1\\ud0dc\\ub85c \\uc560\\ub97c \\ubcf4\\uae30\\ub294 \\uc815\\ub9d0 \\ud558\\ub298\\uc758 \\ubcc4\\ub530\\uae30.. 2\\ub144\\u2026\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"raffine_svtww\",\"name\":\"\\uc6d0\\uc6b0\\ud83e\\uddda\\ud83c\\udffb\\u200d\\u2642\\ufe0fRaffine\",\"id\":826694346116194304,\"id_str\":\"826694346116194304\",\"indices\":[3,17]}],\"urls\":[]},\"metadata\":{\"result_type\":\"recent\",\"iso_language_code\":\"ko\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/android\\\" rel=\\\"nofollow\\\"\\u003eTwitter for Android\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":735107767,\"id_str\":\"735107767\",\"name\":\"\\ubc31\\ud558\",\"screen_name\":\"dkwye17\",\"location\":\"\",\"description\":\"4\\uae30 \\uce90\\ub7ff!! \\ub2a6\\ub355\\uc785\\ub2c8\\ub2e4\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":26,\"friends_count\":186,\"listed_count\":0,\"created_at\":\"Fri Aug 03 15:57:33 +0000 2012\",\"favourites_count\":2924,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":45344,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"0099B9\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1229159898379767808\\\/ujP9hUZw_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1229159898379767808\\\/ujP9hUZw_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/735107767\\\/1581889530\",\"profile_link_color\":\"0099B9\",\"profile_sidebar_border_color\":\"FFFFFF\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":false,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Sat Apr 25 19:29:57 +0000 2020\",\"id\":1254130547049164800,\"id_str\":\"1254130547049164800\",\"text\":\"\\ud30c\\ud2b8 \\uc801\\uc740 4\\uba85 \\uc911\\uc5d0 \\uadf8\\ub798\\ub3c4 \\uadf8\\ub098\\ub9c8 \\uc138\\uba85\\uc740 \\ud37c\\ud3ec\\ud300\\uc774\\ub77c \\ubb34\\ub300 \\uc704\\uc5d0\\uc11c \\uc548\\ubb34\\ud558\\ub294 \\uac74 \\ubcf4\\uc774\\ub294\\ub370 \\uc6d0\\uc6b0\\ub294 \\ud30c\\ud2b8\\ub3c4 \\uc801\\uc740\\ub370 \\ub3d9\\uc120\\ub3c4 \\ub9e8\\ub0a0 \\ub4b7\\ub4b7\\uc904,\\ub4b7\\ub4b7\\ub4b7\\uc904\\uc774\\ub77c \\ubb34\\ub300 \\uc704\\uc5d0\\uc11c \\uba64\\ubc84 \\uc548 \\uac78\\ub9b0 \\uc0c1\\ud0dc\\ub85c \\uc560\\ub97c \\ubcf4\\uae30\\ub294 \\uc815\\ub9d0 \\ud558\\ub298\\uc758 \\ubcc4\\ub530\\uae30\\u2026 https:\\\/\\\/t.co\\\/o45JXOl0oS\",\"truncated\":true,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/o45JXOl0oS\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/i\\\/web\\\/status\\\/1254130547049164800\",\"display_url\":\"twitter.com\\\/i\\\/web\\\/status\\\/1\\u2026\",\"indices\":[117,140]}]},\"metadata\":{\"result_type\":\"recent\",\"iso_language_code\":\"ko\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":826694346116194304,\"id_str\":\"826694346116194304\",\"name\":\"\\uc6d0\\uc6b0\\ud83e\\uddda\\ud83c\\udffb\\u200d\\u2642\\ufe0fRaffine\",\"screen_name\":\"raffine_svtww\",\"location\":\"raffineww@gmail.com\",\"description\":\"Seventeen Wonwoo\\u2764\\ufe0finstagram\\u27a1\\ufe0fraffineww HQ\\u27a1\\ufe0f\\ud83d\\udc9c #\\uc6d0\\uc6b0 #WONWOO #\\u30a6\\u30a9\\u30cc #\\uc138\\ube10\\ud2f4 #SEVENTEEN\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":90302,\"friends_count\":9,\"listed_count\":3142,\"created_at\":\"Wed Feb 01 07:31:06 +0000 2017\",\"favourites_count\":3527,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":6624,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1247560030708105222\\\/jVe19ms0_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1247560030708105222\\\/jVe19ms0_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/826694346116194304\\\/1543312038\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":45,\"favorite_count\":80,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"ko\"},\"is_quote_status\":false,\"retweet_count\":45,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"ko\"},{\"created_at\":\"Sun Apr 26 00:31:48 +0000 2020\",\"id\":1254206511162802178,\"id_str\":\"1254206511162802178\",\"text\":\"RT @vivianagrondona: Acabo de terminar mi obra de arte en cuarentena, no puedo creer que hayan quedado tan hermosos!\\ud83d\\udc96\\ud83d\\ude4c\\ud83c\\udffc\\ud83c\\udf08\\u2728 retweet si te los\\u2026\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"vivianagrondona\",\"name\":\"Viviana Grondona.\",\"id\":1009407560,\"id_str\":\"1009407560\",\"indices\":[3,19]}],\"urls\":[]},\"metadata\":{\"iso_language_code\":\"es\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":135680613,\"id_str\":\"135680613\",\"name\":\"Rexy Jane\",\"screen_name\":\"miss_minicherry\",\"location\":\"\\ud83c\\uddf2\\ud83c\\uddfd\",\"description\":\"We can live like Jack and Sally if you want...\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":393,\"friends_count\":3223,\"listed_count\":1,\"created_at\":\"Thu Apr 22 00:29:25 +0000 2010\",\"favourites_count\":21415,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":4431,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"642D8B\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1250301277260529669\\\/2o5ggA34_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1250301277260529669\\\/2o5ggA34_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/135680613\\\/1578468508\",\"profile_link_color\":\"AA18C7\",\"profile_sidebar_border_color\":\"6300D4\",\"profile_sidebar_fill_color\":\"7AC3EE\",\"profile_text_color\":\"3D1957\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Sat Apr 25 22:46:55 +0000 2020\",\"id\":1254180113819852801,\"id_str\":\"1254180113819852801\",\"text\":\"Acabo de terminar mi obra de arte en cuarentena, no puedo creer que hayan quedado tan hermosos!\\ud83d\\udc96\\ud83d\\ude4c\\ud83c\\udffc\\ud83c\\udf08\\u2728 retweet si te\\u2026 https:\\\/\\\/t.co\\\/pg3PNy92hH\",\"truncated\":true,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/pg3PNy92hH\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/i\\\/web\\\/status\\\/1254180113819852801\",\"display_url\":\"twitter.com\\\/i\\\/web\\\/status\\\/1\\u2026\",\"indices\":[116,139]}]},\"metadata\":{\"iso_language_code\":\"es\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":1009407560,\"id_str\":\"1009407560\",\"name\":\"Viviana Grondona.\",\"screen_name\":\"vivianagrondona\",\"location\":\"Bogot\\u00e1, D.C., Colombia\",\"description\":\"Dibujo. dibujo en todas partes\",\"url\":\"https:\\\/\\\/t.co\\\/JpZMAnWlLi\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/JpZMAnWlLi\",\"expanded_url\":\"https:\\\/\\\/www.instagram.com\\\/vivianagrondona\\\/?hl=es\",\"display_url\":\"instagram.com\\\/vivianagrondon\\u2026\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":24119,\"friends_count\":215,\"listed_count\":23,\"created_at\":\"Thu Dec 13 18:13:09 +0000 2012\",\"favourites_count\":3439,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":464,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"FFB499\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/916134587532791809\\\/HgWSoc5Z_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/916134587532791809\\\/HgWSoc5Z_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/1009407560\\\/1508186831\",\"profile_link_color\":\"FA9696\",\"profile_sidebar_border_color\":\"FFFFFF\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":150,\"favorite_count\":973,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"es\"},\"is_quote_status\":false,\"retweet_count\":150,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"es\"},{\"created_at\":\"Sun Apr 26 00:31:48 +0000 2020\",\"id\":1254206511162613761,\"id_str\":\"1254206511162613761\",\"text\":\"RT @HKR20_official: \\u672c\\u65e5\\u3082\\u3054\\u8996\\u8074\\u3042\\u308a\\u304c\\u3068\\u3046\\u3054\\u3056\\u3044\\u307e\\u3057\\u305f\\u3002\\u653e\\u9001\\u5f8c\\u306f\\u4eee\\u9762\\u30e9\\u30a4\\u30c0\\u30fc\\u30b7\\u30ea\\u30fc\\u30ba\\u306e\\u6700\\u65b0\\u60c5\\u5831\\u3092\\u516c\\u5f0f\\u30b5\\u30a4\\u30c8\\u3067\\u662f\\u975e\\u2728\\n\\nhttps:\\\/\\\/t.co\\\/3IQWuav2Zn\\n\\n#\\u4eee\\u9762\\u30e9\\u30a4\\u30c0\\u30fc\\u30bc\\u30ed\\u30ef\\u30f3 #nitiasa https:\\\/\\\/t.co\\\/2m9j5p55DU\",\"truncated\":false,\"entities\":{\"hashtags\":[{\"text\":\"\\u4eee\\u9762\\u30e9\\u30a4\\u30c0\\u30fc\\u30bc\\u30ed\\u30ef\\u30f3\",\"indices\":[94,105]},{\"text\":\"nitiasa\",\"indices\":[106,114]}],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"HKR20_official\",\"name\":\"\\u4eee\\u9762\\u30e9\\u30a4\\u30c0\\u30fc\\u516c\\u5f0f\",\"id\":1023878417899372545,\"id_str\":\"1023878417899372545\",\"indices\":[3,18]}],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/3IQWuav2Zn\",\"expanded_url\":\"https:\\\/\\\/kamen-rider-official.com\\\/weekly_topics\\\/40\",\"display_url\":\"kamen-rider-official.com\\\/weekly_topics\\\/\\u2026\",\"indices\":[69,92]}],\"media\":[{\"id\":1254205319468552192,\"id_str\":\"1254205319468552192\",\"indices\":[115,138],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfVF85UEAA8I3D.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfVF85UEAA8I3D.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/2m9j5p55DU\",\"display_url\":\"pic.twitter.com\\\/2m9j5p55DU\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/HKR20_official\\\/status\\\/1254205326095642625\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"medium\":{\"w\":1000,\"h\":750,\"resize\":\"fit\"},\"small\":{\"w\":680,\"h\":510,\"resize\":\"fit\"},\"large\":{\"w\":1000,\"h\":750,\"resize\":\"fit\"}},\"source_status_id\":1254205326095642625,\"source_status_id_str\":\"1254205326095642625\",\"source_user_id\":1023878417899372545,\"source_user_id_str\":\"1023878417899372545\"}]},\"extended_entities\":{\"media\":[{\"id\":1254205319468552192,\"id_str\":\"1254205319468552192\",\"indices\":[115,138],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfVF85UEAA8I3D.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfVF85UEAA8I3D.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/2m9j5p55DU\",\"display_url\":\"pic.twitter.com\\\/2m9j5p55DU\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/HKR20_official\\\/status\\\/1254205326095642625\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"medium\":{\"w\":1000,\"h\":750,\"resize\":\"fit\"},\"small\":{\"w\":680,\"h\":510,\"resize\":\"fit\"},\"large\":{\"w\":1000,\"h\":750,\"resize\":\"fit\"}},\"source_status_id\":1254205326095642625,\"source_status_id_str\":\"1254205326095642625\",\"source_user_id\":1023878417899372545,\"source_user_id_str\":\"1023878417899372545\"},{\"id\":1254205323314749440,\"id_str\":\"1254205323314749440\",\"indices\":[115,138],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfVGLOUYAALANf.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfVGLOUYAALANf.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/2m9j5p55DU\",\"display_url\":\"pic.twitter.com\\\/2m9j5p55DU\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/HKR20_official\\\/status\\\/1254205326095642625\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"small\":{\"w\":680,\"h\":356,\"resize\":\"fit\"},\"large\":{\"w\":1280,\"h\":670,\"resize\":\"fit\"},\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"medium\":{\"w\":1200,\"h\":628,\"resize\":\"fit\"}},\"source_status_id\":1254205326095642625,\"source_status_id_str\":\"1254205326095642625\",\"source_user_id\":1023878417899372545,\"source_user_id_str\":\"1023878417899372545\"}]},\"metadata\":{\"iso_language_code\":\"ja\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":843724376180576257,\"id_str\":\"843724376180576257\",\"name\":\"\\ud83c\\uddfa\\ud83c\\uddf8YOSHIHISA\\ud83c\\uddfa\\ud83c\\uddf8\",\"screen_name\":\"yosshii1002\",\"location\":\"\\u798f\\u5ca1 \\u798f\\u5ca1\\u5e02 \\u4e2d\\u592e\\u533a\",\"description\":\"WE ARE X\\uff01\\uff01\\uff01\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":231,\"friends_count\":753,\"listed_count\":0,\"created_at\":\"Mon Mar 20 07:22:21 +0000 2017\",\"favourites_count\":299491,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":7654,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1171661771616268290\\\/JHyfbwxV_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1171661771616268290\\\/JHyfbwxV_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/843724376180576257\\\/1536253021\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Sun Apr 26 00:27:06 +0000 2020\",\"id\":1254205326095642625,\"id_str\":\"1254205326095642625\",\"text\":\"\\u672c\\u65e5\\u3082\\u3054\\u8996\\u8074\\u3042\\u308a\\u304c\\u3068\\u3046\\u3054\\u3056\\u3044\\u307e\\u3057\\u305f\\u3002\\u653e\\u9001\\u5f8c\\u306f\\u4eee\\u9762\\u30e9\\u30a4\\u30c0\\u30fc\\u30b7\\u30ea\\u30fc\\u30ba\\u306e\\u6700\\u65b0\\u60c5\\u5831\\u3092\\u516c\\u5f0f\\u30b5\\u30a4\\u30c8\\u3067\\u662f\\u975e\\u2728\\n\\nhttps:\\\/\\\/t.co\\\/3IQWuav2Zn\\n\\n#\\u4eee\\u9762\\u30e9\\u30a4\\u30c0\\u30fc\\u30bc\\u30ed\\u30ef\\u30f3 #nitiasa https:\\\/\\\/t.co\\\/2m9j5p55DU\",\"truncated\":false,\"entities\":{\"hashtags\":[{\"text\":\"\\u4eee\\u9762\\u30e9\\u30a4\\u30c0\\u30fc\\u30bc\\u30ed\\u30ef\\u30f3\",\"indices\":[74,85]},{\"text\":\"nitiasa\",\"indices\":[86,94]}],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/3IQWuav2Zn\",\"expanded_url\":\"https:\\\/\\\/kamen-rider-official.com\\\/weekly_topics\\\/40\",\"display_url\":\"kamen-rider-official.com\\\/weekly_topics\\\/\\u2026\",\"indices\":[49,72]}],\"media\":[{\"id\":1254205319468552192,\"id_str\":\"1254205319468552192\",\"indices\":[95,118],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfVF85UEAA8I3D.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfVF85UEAA8I3D.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/2m9j5p55DU\",\"display_url\":\"pic.twitter.com\\\/2m9j5p55DU\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/HKR20_official\\\/status\\\/1254205326095642625\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"medium\":{\"w\":1000,\"h\":750,\"resize\":\"fit\"},\"small\":{\"w\":680,\"h\":510,\"resize\":\"fit\"},\"large\":{\"w\":1000,\"h\":750,\"resize\":\"fit\"}}}]},\"extended_entities\":{\"media\":[{\"id\":1254205319468552192,\"id_str\":\"1254205319468552192\",\"indices\":[95,118],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfVF85UEAA8I3D.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfVF85UEAA8I3D.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/2m9j5p55DU\",\"display_url\":\"pic.twitter.com\\\/2m9j5p55DU\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/HKR20_official\\\/status\\\/1254205326095642625\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"medium\":{\"w\":1000,\"h\":750,\"resize\":\"fit\"},\"small\":{\"w\":680,\"h\":510,\"resize\":\"fit\"},\"large\":{\"w\":1000,\"h\":750,\"resize\":\"fit\"}}},{\"id\":1254205323314749440,\"id_str\":\"1254205323314749440\",\"indices\":[95,118],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfVGLOUYAALANf.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfVGLOUYAALANf.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/2m9j5p55DU\",\"display_url\":\"pic.twitter.com\\\/2m9j5p55DU\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/HKR20_official\\\/status\\\/1254205326095642625\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"small\":{\"w\":680,\"h\":356,\"resize\":\"fit\"},\"large\":{\"w\":1280,\"h\":670,\"resize\":\"fit\"},\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"medium\":{\"w\":1200,\"h\":628,\"resize\":\"fit\"}}}]},\"metadata\":{\"iso_language_code\":\"ja\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/social.userlocal.jp\\\/\\\" rel=\\\"nofollow\\\"\\u003eSocial Insight Post\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":1023878417899372545,\"id_str\":\"1023878417899372545\",\"name\":\"\\u4eee\\u9762\\u30e9\\u30a4\\u30c0\\u30fc\\u516c\\u5f0f\",\"screen_name\":\"HKR20_official\",\"location\":\"\",\"description\":\"\\u4eee\\u9762\\u30e9\\u30a4\\u30c0\\u30fc\\u30b7\\u30ea\\u30fc\\u30ba\\u306e\\u516c\\u5f0fTwitter\\u3067\\u3059\\u3002\\u5e73\\u6210\\u4eee\\u9762\\u30e9\\u30a4\\u30c0\\u30fc20\\u4f5c\\u54c1\\u8a18\\u5ff5\\u516c\\u5f0fTwitter\\u304c\\u30ea\\u30cb\\u30e5\\u30fc\\u30a2\\u30eb\\u3057\\u307e\\u3057\\u305f\\u3002\\u3042\\u308f\\u305b\\u306620\\u4f5c\\u54c1\\u8a18\\u5ff5\\u516c\\u5f0f\\u30b5\\u30a4\\u30c8\\u3082\\u4eee\\u9762\\u30e9\\u30a4\\u30c0\\u30fc\\u516c\\u5f0f\\u30dd\\u30fc\\u30bf\\u30eb\\u30b5\\u30a4\\u30c8\\u300c\\u4eee\\u9762\\u30e9\\u30a4\\u30c0\\u30fcWEB\\u300d\\u306b\\u306a\\u3063\\u3066\\u304a\\u308a\\u307e\\u3059\\u3002\\u3053\\u308c\\u307e\\u3067\\u3088\\u308a\\u4e00\\u5c64\\u3001\\u30d5\\u30a1\\u30f3\\u306e\\u7686\\u69d8\\u306b\\u697d\\u3057\\u3093\\u3067\\u9802\\u3051\\u308b\\u3088\\u3046\\u306b\\u52aa\\u3081\\u3066\\u307e\\u3044\\u308a\\u307e\\u3059\\u306e\\u3067\\u3001\\u5b9c\\u3057\\u304f\\u304a\\u9858\\u3044\\u81f4\\u3057\\u307e\\u3059\\u3002\",\"url\":\"https:\\\/\\\/t.co\\\/lWszSeoFqn\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/lWszSeoFqn\",\"expanded_url\":\"https:\\\/\\\/www.kamen-rider-official.com\\\/\",\"display_url\":\"kamen-rider-official.com\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":183400,\"friends_count\":45,\"listed_count\":1160,\"created_at\":\"Mon Jul 30 10:30:12 +0000 2018\",\"favourites_count\":3507,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":3191,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1170508535613906945\\\/OwSy1M2q_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1170508535613906945\\\/OwSy1M2q_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/1023878417899372545\\\/1567041258\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":723,\"favorite_count\":947,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"ja\"},\"is_quote_status\":false,\"retweet_count\":723,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":true,\"lang\":\"ja\"},{\"created_at\":\"Sun Apr 26 00:31:48 +0000 2020\",\"id\":1254206511158566912,\"id_str\":\"1254206511158566912\",\"text\":\"RT @b_alone0: https:\\\/\\\/t.co\\\/2IPUASJd99\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"b_alone0\",\"name\":\"\\u0628\\u0627\\u0644\\u0648\\u0646\",\"id\":1059742467053047809,\"id_str\":\"1059742467053047809\",\"indices\":[3,12]}],\"urls\":[],\"media\":[{\"id\":1253778566283657222,\"id_str\":\"1253778566283657222\",\"indices\":[14,37],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWZQ9pZWAAYLkUu.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWZQ9pZWAAYLkUu.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/2IPUASJd99\",\"display_url\":\"pic.twitter.com\\\/2IPUASJd99\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/b_alone0\\\/status\\\/1253778573636382721\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"medium\":{\"w\":700,\"h\":834,\"resize\":\"fit\"},\"small\":{\"w\":571,\"h\":680,\"resize\":\"fit\"},\"large\":{\"w\":700,\"h\":834,\"resize\":\"fit\"}},\"source_status_id\":1253778573636382721,\"source_status_id_str\":\"1253778573636382721\",\"source_user_id\":1059742467053047809,\"source_user_id_str\":\"1059742467053047809\"}]},\"extended_entities\":{\"media\":[{\"id\":1253778566283657222,\"id_str\":\"1253778566283657222\",\"indices\":[14,37],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWZQ9pZWAAYLkUu.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWZQ9pZWAAYLkUu.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/2IPUASJd99\",\"display_url\":\"pic.twitter.com\\\/2IPUASJd99\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/b_alone0\\\/status\\\/1253778573636382721\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"medium\":{\"w\":700,\"h\":834,\"resize\":\"fit\"},\"small\":{\"w\":571,\"h\":680,\"resize\":\"fit\"},\"large\":{\"w\":700,\"h\":834,\"resize\":\"fit\"}},\"source_status_id\":1253778573636382721,\"source_status_id_str\":\"1253778573636382721\",\"source_user_id\":1059742467053047809,\"source_user_id_str\":\"1059742467053047809\"}]},\"metadata\":{\"iso_language_code\":\"und\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/android\\\" rel=\\\"nofollow\\\"\\u003eTwitter for Android\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":843538687,\"id_str\":\"843538687\",\"name\":\"hussam\",\"screen_name\":\"legendhussam\",\"location\":\"\",\"description\":\"yeah my shit is crooked, look how far I done got without it...\\numst\",\"url\":\"https:\\\/\\\/t.co\\\/L1sw6f1r4P\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/L1sw6f1r4P\",\"expanded_url\":\"https:\\\/\\\/curiouscat.me\\\/legendhussam?t=1551488678\",\"display_url\":\"curiouscat.me\\\/legendhussam?t\\u2026\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":217,\"friends_count\":203,\"listed_count\":1,\"created_at\":\"Mon Sep 24 12:50:16 +0000 2012\",\"favourites_count\":2592,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":2998,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"000000\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1216076037114691584\\\/CGxbC2tm_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1216076037114691584\\\/CGxbC2tm_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/843538687\\\/1538738245\",\"profile_link_color\":\"ABB8C2\",\"profile_sidebar_border_color\":\"000000\",\"profile_sidebar_fill_color\":\"000000\",\"profile_text_color\":\"000000\",\"profile_use_background_image\":false,\"has_extended_profile\":false,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Fri Apr 24 20:11:20 +0000 2020\",\"id\":1253778573636382721,\"id_str\":\"1253778573636382721\",\"text\":\"https:\\\/\\\/t.co\\\/2IPUASJd99\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[],\"media\":[{\"id\":1253778566283657222,\"id_str\":\"1253778566283657222\",\"indices\":[0,23],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWZQ9pZWAAYLkUu.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWZQ9pZWAAYLkUu.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/2IPUASJd99\",\"display_url\":\"pic.twitter.com\\\/2IPUASJd99\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/b_alone0\\\/status\\\/1253778573636382721\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"medium\":{\"w\":700,\"h\":834,\"resize\":\"fit\"},\"small\":{\"w\":571,\"h\":680,\"resize\":\"fit\"},\"large\":{\"w\":700,\"h\":834,\"resize\":\"fit\"}}}]},\"extended_entities\":{\"media\":[{\"id\":1253778566283657222,\"id_str\":\"1253778566283657222\",\"indices\":[0,23],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWZQ9pZWAAYLkUu.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWZQ9pZWAAYLkUu.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/2IPUASJd99\",\"display_url\":\"pic.twitter.com\\\/2IPUASJd99\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/b_alone0\\\/status\\\/1253778573636382721\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"medium\":{\"w\":700,\"h\":834,\"resize\":\"fit\"},\"small\":{\"w\":571,\"h\":680,\"resize\":\"fit\"},\"large\":{\"w\":700,\"h\":834,\"resize\":\"fit\"}}}]},\"metadata\":{\"iso_language_code\":\"und\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":1059742467053047809,\"id_str\":\"1059742467053047809\",\"name\":\"\\u0628\\u0627\\u0644\\u0648\\u0646\",\"screen_name\":\"b_alone0\",\"location\":\"\",\"description\":\"\\u0627\\u0630\\u0627 \\u0643\\u0628\\u0631\\u062a\\u0647\\u0627 \\u062a\\u0643\\u0628\\u0631, \\u0648\\u0627\\u0630\\u0627 \\u0635\\u063a\\u0631\\u062a\\u0647\\u0627 \\u062a\\u0635\\u063a\\u0631\",\"url\":\"https:\\\/\\\/t.co\\\/qE4KJRbCQp\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/qE4KJRbCQp\",\"expanded_url\":\"https:\\\/\\\/curiouscat.me\\\/balloon\",\"display_url\":\"curiouscat.me\\\/balloon\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":20337,\"friends_count\":417,\"listed_count\":54,\"created_at\":\"Tue Nov 06 09:41:08 +0000 2018\",\"favourites_count\":14,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":21154,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1232421419633565697\\\/71ascTCD_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1232421419633565697\\\/71ascTCD_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/1059742467053047809\\\/1545703535\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":1615,\"favorite_count\":4306,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"und\"},\"is_quote_status\":false,\"retweet_count\":1615,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"und\"},{\"created_at\":\"Sun Apr 26 00:31:48 +0000 2020\",\"id\":1254206511154368519,\"id_str\":\"1254206511154368519\",\"text\":\"RT @thechef71: @mitchellvii https:\\\/\\\/t.co\\\/8Q55DFd6BY\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"thechef71\",\"name\":\"The Chef\",\"id\":10574352,\"id_str\":\"10574352\",\"indices\":[3,13]},{\"screen_name\":\"mitchellvii\",\"name\":\"Bill Mitchell\",\"id\":17980523,\"id_str\":\"17980523\",\"indices\":[15,27]}],\"urls\":[],\"media\":[{\"id\":1254076867830853633,\"id_str\":\"1254076867830853633\",\"indices\":[28,51],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWdgRFQXsAEikEc.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWdgRFQXsAEikEc.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/8Q55DFd6BY\",\"display_url\":\"pic.twitter.com\\\/8Q55DFd6BY\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/thechef71\\\/status\\\/1254076871911800833\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"large\":{\"w\":865,\"h\":960,\"resize\":\"fit\"},\"medium\":{\"w\":865,\"h\":960,\"resize\":\"fit\"},\"small\":{\"w\":613,\"h\":680,\"resize\":\"fit\"}},\"source_status_id\":1254076871911800833,\"source_status_id_str\":\"1254076871911800833\",\"source_user_id\":10574352,\"source_user_id_str\":\"10574352\"}]},\"extended_entities\":{\"media\":[{\"id\":1254076867830853633,\"id_str\":\"1254076867830853633\",\"indices\":[28,51],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWdgRFQXsAEikEc.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWdgRFQXsAEikEc.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/8Q55DFd6BY\",\"display_url\":\"pic.twitter.com\\\/8Q55DFd6BY\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/thechef71\\\/status\\\/1254076871911800833\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"large\":{\"w\":865,\"h\":960,\"resize\":\"fit\"},\"medium\":{\"w\":865,\"h\":960,\"resize\":\"fit\"},\"small\":{\"w\":613,\"h\":680,\"resize\":\"fit\"}},\"source_status_id\":1254076871911800833,\"source_status_id_str\":\"1254076871911800833\",\"source_user_id\":10574352,\"source_user_id_str\":\"10574352\"}]},\"metadata\":{\"iso_language_code\":\"und\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":2660095619,\"id_str\":\"2660095619\",\"name\":\"Michelle Steines Make America Great Again\\ud83c\\uddfa\\ud83c\\uddf8\",\"screen_name\":\"Scapmichelle\",\"location\":\"New Jersey, USA\",\"description\":\"\\u274c TRUMP America First\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":5914,\"friends_count\":5074,\"listed_count\":163,\"created_at\":\"Tue Jul 01 13:23:23 +0000 2014\",\"favourites_count\":112126,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":122548,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1252339771453722625\\\/TP6yXi5j_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1252339771453722625\\\/TP6yXi5j_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/2660095619\\\/1585362478\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Sat Apr 25 15:56:40 +0000 2020\",\"id\":1254076871911800833,\"id_str\":\"1254076871911800833\",\"text\":\"@mitchellvii https:\\\/\\\/t.co\\\/8Q55DFd6BY\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"mitchellvii\",\"name\":\"Bill Mitchell\",\"id\":17980523,\"id_str\":\"17980523\",\"indices\":[0,12]}],\"urls\":[],\"media\":[{\"id\":1254076867830853633,\"id_str\":\"1254076867830853633\",\"indices\":[13,36],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWdgRFQXsAEikEc.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWdgRFQXsAEikEc.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/8Q55DFd6BY\",\"display_url\":\"pic.twitter.com\\\/8Q55DFd6BY\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/thechef71\\\/status\\\/1254076871911800833\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"large\":{\"w\":865,\"h\":960,\"resize\":\"fit\"},\"medium\":{\"w\":865,\"h\":960,\"resize\":\"fit\"},\"small\":{\"w\":613,\"h\":680,\"resize\":\"fit\"}}}]},\"extended_entities\":{\"media\":[{\"id\":1254076867830853633,\"id_str\":\"1254076867830853633\",\"indices\":[13,36],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWdgRFQXsAEikEc.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWdgRFQXsAEikEc.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/8Q55DFd6BY\",\"display_url\":\"pic.twitter.com\\\/8Q55DFd6BY\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/thechef71\\\/status\\\/1254076871911800833\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"large\":{\"w\":865,\"h\":960,\"resize\":\"fit\"},\"medium\":{\"w\":865,\"h\":960,\"resize\":\"fit\"},\"small\":{\"w\":613,\"h\":680,\"resize\":\"fit\"}}}]},\"metadata\":{\"iso_language_code\":\"und\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":1254072710919000065,\"in_reply_to_status_id_str\":\"1254072710919000065\",\"in_reply_to_user_id\":17980523,\"in_reply_to_user_id_str\":\"17980523\",\"in_reply_to_screen_name\":\"mitchellvii\",\"user\":{\"id\":10574352,\"id_str\":\"10574352\",\"name\":\"The Chef\",\"screen_name\":\"thechef71\",\"location\":\"\",\"description\":\"\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":159,\"friends_count\":594,\"listed_count\":1,\"created_at\":\"Sun Nov 25 23:33:59 +0000 2007\",\"favourites_count\":5541,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":2767,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1241817920151355402\\\/nJhrKSzj_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1241817920151355402\\\/nJhrKSzj_normal.jpg\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":208,\"favorite_count\":432,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"und\"},\"is_quote_status\":false,\"retweet_count\":208,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"und\"},{\"created_at\":\"Sun Apr 26 00:31:48 +0000 2020\",\"id\":1254206511154204673,\"id_str\":\"1254206511154204673\",\"text\":\"RT @Feb_sounds: \\u3010\\ud83d\\udca5\\u3050\\u3089\\u3059\\u307d\\u30e9\\u30b8\\u30aa#\\uff19\\u516c\\u958b\\ud83d\\udca5\\u3011\\n\\n\\u6628\\u65e5\\u306b\\u5f15\\u304d\\u7d9a\\u304d\\u300c\\u30ea\\u30cb\\u30e5\\u30fc\\u30a2\\u30eb\\u4e00\\u767a\\u76ee\\u7de8\\u2461\\u300d\\u3092\\u516c\\u958b\\u3057\\u307e\\u3057\\u305f\\ud83d\\udcfb\\ud83e\\udd73\\n\\n\\uff12\\u6708\\u306e\\u300c\\u307f\\u305a\\u3057\\u3043\\u611b\\u300d\\u304c\\u66f4\\u306b\\u70b8\\u88c2\\u2665\\ufe0f\\n\\u65b0\\u66f2\\u300eKURA KURA HAIR\\u300f\\u306e\\u6b4c\\u8a5e\\u3092\\u5206\\u6790\\u3057\\u305f\\u7d50\\u679c\\u3001\\u3068\\u3093\\u3067\\u3082\\u306a\\u3044\\u4f5c\\u54c1\\u3067\\u3042\\u3063\\u305f\\u3053\\u3068\\u3092\\u8a3c\\u660e\\u3057\\u307e\\u3059\\u203c\\ufe0f\\ud83e\\uddda\\n\\n\\u6b4c\\u8a5e\\u3063\\u2026\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"Feb_sounds\",\"name\":\"\\uff12\\u6708\\u3002(DTMer)\",\"id\":954549079953965057,\"id_str\":\"954549079953965057\",\"indices\":[3,14]}],\"urls\":[]},\"metadata\":{\"iso_language_code\":\"ja\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/android\\\" rel=\\\"nofollow\\\"\\u003eTwitter for Android\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":954549079953965057,\"id_str\":\"954549079953965057\",\"name\":\"\\uff12\\u6708\\u3002(DTMer)\",\"screen_name\":\"Feb_sounds\",\"location\":\"\\ud83d\\udc47\\u30db\\u30fc\\u30e0\\u30da\\u30fc\\u30b8\\u306b\\u5404\\u7a2e\\u30ea\\u30f3\\u30af\\u3042\\u308a\\ud83d\\udc47\",\"description\":\"\\uff62\\u306b\\u304c\\u3064\\uff63\\u3068\\u7533\\u3057\\u307e\\u3059\\u3002YouTube\\u306b\\u3066\\u97f3\\u697d\\u6d3b\\u52d5\\u3092\\u3057\\u3066\\u3044\\u307e\\u3059\\ud83c\\udf90\\u4f5c\\u8a5e\\u4f5c\\u66f2\\u7de8\\u66f2\\uff0f\\u30d0\\u30f3\\u30c9\\u30b5\\u30a6\\u30f3\\u30c9\\u304c\\u5f97\\u610f\\uff0f\\u5272\\u7530\\u30c1\\u30eb\\u30c9\\u30ec\\u30f3\\ud83d\\ude80\\u4e43\\u6728\\u5742\\u25e2\\u2074\\u2076\\u9ad8\\u5c71\\u4e00\\u5b9f\\u3055\\u3093\\u63a8\\u3057\\ud83c\\udf3a\\u3010TheGrasspopper's\\u3011\\u5275\\u8a2d\\u8005\\uff0fhttps:\\\/\\\/t.co\\\/i2Bn4XFS6v\",\"url\":\"https:\\\/\\\/t.co\\\/LkGFPuhBI0\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/LkGFPuhBI0\",\"expanded_url\":\"http:\\\/\\\/site-1631148-4039-1706february2.strikingly.com\\\/\",\"display_url\":\"\\u2026148-4039-1706february2.strikingly.com\",\"indices\":[0,23]}]},\"description\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/i2Bn4XFS6v\",\"expanded_url\":\"https:\\\/\\\/www.youtube.com\\\/channel\\\/UCrGnlGdJZ8pn2Fl5G19Hj4A\",\"display_url\":\"youtube.com\\\/channel\\\/UCrGnl\\u2026\",\"indices\":[94,117]}]}},\"protected\":false,\"followers_count\":1955,\"friends_count\":1933,\"listed_count\":18,\"created_at\":\"Sat Jan 20 03:00:10 +0000 2018\",\"favourites_count\":16589,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":10375,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1212310636744462337\\\/FGx8YAuU_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1212310636744462337\\\/FGx8YAuU_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/954549079953965057\\\/1578799295\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Sat Apr 25 10:37:54 +0000 2020\",\"id\":1253996651410124800,\"id_str\":\"1253996651410124800\",\"text\":\"\\u3010\\ud83d\\udca5\\u3050\\u3089\\u3059\\u307d\\u30e9\\u30b8\\u30aa#\\uff19\\u516c\\u958b\\ud83d\\udca5\\u3011\\n\\n\\u6628\\u65e5\\u306b\\u5f15\\u304d\\u7d9a\\u304d\\u300c\\u30ea\\u30cb\\u30e5\\u30fc\\u30a2\\u30eb\\u4e00\\u767a\\u76ee\\u7de8\\u2461\\u300d\\u3092\\u516c\\u958b\\u3057\\u307e\\u3057\\u305f\\ud83d\\udcfb\\ud83e\\udd73\\n\\n\\uff12\\u6708\\u306e\\u300c\\u307f\\u305a\\u3057\\u3043\\u611b\\u300d\\u304c\\u66f4\\u306b\\u70b8\\u88c2\\u2665\\ufe0f\\n\\u65b0\\u66f2\\u300eKURA KURA HAIR\\u300f\\u306e\\u6b4c\\u8a5e\\u3092\\u5206\\u6790\\u3057\\u305f\\u7d50\\u679c\\u3001\\u3068\\u3093\\u3067\\u3082\\u306a\\u3044\\u4f5c\\u54c1\\u3067\\u3042\\u3063\\u305f\\u3053\\u3068\\u3092\\u8a3c\\u660e\\u3057\\u307e\\u3059\\u2026 https:\\\/\\\/t.co\\\/CSCMuyX2Os\",\"truncated\":true,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/CSCMuyX2Os\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/i\\\/web\\\/status\\\/1253996651410124800\",\"display_url\":\"twitter.com\\\/i\\\/web\\\/status\\\/1\\u2026\",\"indices\":[117,140]}]},\"metadata\":{\"iso_language_code\":\"ja\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/android\\\" rel=\\\"nofollow\\\"\\u003eTwitter for Android\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":954549079953965057,\"id_str\":\"954549079953965057\",\"name\":\"\\uff12\\u6708\\u3002(DTMer)\",\"screen_name\":\"Feb_sounds\",\"location\":\"\\ud83d\\udc47\\u30db\\u30fc\\u30e0\\u30da\\u30fc\\u30b8\\u306b\\u5404\\u7a2e\\u30ea\\u30f3\\u30af\\u3042\\u308a\\ud83d\\udc47\",\"description\":\"\\uff62\\u306b\\u304c\\u3064\\uff63\\u3068\\u7533\\u3057\\u307e\\u3059\\u3002YouTube\\u306b\\u3066\\u97f3\\u697d\\u6d3b\\u52d5\\u3092\\u3057\\u3066\\u3044\\u307e\\u3059\\ud83c\\udf90\\u4f5c\\u8a5e\\u4f5c\\u66f2\\u7de8\\u66f2\\uff0f\\u30d0\\u30f3\\u30c9\\u30b5\\u30a6\\u30f3\\u30c9\\u304c\\u5f97\\u610f\\uff0f\\u5272\\u7530\\u30c1\\u30eb\\u30c9\\u30ec\\u30f3\\ud83d\\ude80\\u4e43\\u6728\\u5742\\u25e2\\u2074\\u2076\\u9ad8\\u5c71\\u4e00\\u5b9f\\u3055\\u3093\\u63a8\\u3057\\ud83c\\udf3a\\u3010TheGrasspopper's\\u3011\\u5275\\u8a2d\\u8005\\uff0fhttps:\\\/\\\/t.co\\\/i2Bn4XFS6v\",\"url\":\"https:\\\/\\\/t.co\\\/LkGFPuhBI0\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/LkGFPuhBI0\",\"expanded_url\":\"http:\\\/\\\/site-1631148-4039-1706february2.strikingly.com\\\/\",\"display_url\":\"\\u2026148-4039-1706february2.strikingly.com\",\"indices\":[0,23]}]},\"description\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/i2Bn4XFS6v\",\"expanded_url\":\"https:\\\/\\\/www.youtube.com\\\/channel\\\/UCrGnlGdJZ8pn2Fl5G19Hj4A\",\"display_url\":\"youtube.com\\\/channel\\\/UCrGnl\\u2026\",\"indices\":[94,117]}]}},\"protected\":false,\"followers_count\":1955,\"friends_count\":1933,\"listed_count\":18,\"created_at\":\"Sat Jan 20 03:00:10 +0000 2018\",\"favourites_count\":16589,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":10375,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1212310636744462337\\\/FGx8YAuU_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1212310636744462337\\\/FGx8YAuU_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/954549079953965057\\\/1578799295\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":1,\"favorite_count\":6,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"ja\"},\"is_quote_status\":false,\"retweet_count\":1,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"ja\"},{\"created_at\":\"Sun Apr 26 00:31:48 +0000 2020\",\"id\":1254206511146061824,\"id_str\":\"1254206511146061824\",\"text\":\"RT @Tik_Tokers_: Error de calculo https:\\\/\\\/t.co\\\/ew3lt96L2Y\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"Tik_Tokers_\",\"name\":\"Tik Tokers\",\"id\":976340242881015814,\"id_str\":\"976340242881015814\",\"indices\":[3,15]}],\"urls\":[],\"media\":[{\"id\":1254198030456229889,\"id_str\":\"1254198030456229889\",\"indices\":[34,57],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254198030456229889\\\/pu\\\/img\\\/5GCvS6_dUfUtRbcy.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254198030456229889\\\/pu\\\/img\\\/5GCvS6_dUfUtRbcy.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/ew3lt96L2Y\",\"display_url\":\"pic.twitter.com\\\/ew3lt96L2Y\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/Tik_Tokers_\\\/status\\\/1254198133313191936\\\/video\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":383,\"h\":680,\"resize\":\"fit\"},\"large\":{\"w\":576,\"h\":1024,\"resize\":\"fit\"},\"medium\":{\"w\":576,\"h\":1024,\"resize\":\"fit\"}},\"source_status_id\":1254198133313191936,\"source_status_id_str\":\"1254198133313191936\",\"source_user_id\":976340242881015814,\"source_user_id_str\":\"976340242881015814\"}]},\"extended_entities\":{\"media\":[{\"id\":1254198030456229889,\"id_str\":\"1254198030456229889\",\"indices\":[34,57],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254198030456229889\\\/pu\\\/img\\\/5GCvS6_dUfUtRbcy.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254198030456229889\\\/pu\\\/img\\\/5GCvS6_dUfUtRbcy.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/ew3lt96L2Y\",\"display_url\":\"pic.twitter.com\\\/ew3lt96L2Y\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/Tik_Tokers_\\\/status\\\/1254198133313191936\\\/video\\\/1\",\"type\":\"video\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":383,\"h\":680,\"resize\":\"fit\"},\"large\":{\"w\":576,\"h\":1024,\"resize\":\"fit\"},\"medium\":{\"w\":576,\"h\":1024,\"resize\":\"fit\"}},\"source_status_id\":1254198133313191936,\"source_status_id_str\":\"1254198133313191936\",\"source_user_id\":976340242881015814,\"source_user_id_str\":\"976340242881015814\",\"video_info\":{\"aspect_ratio\":[9,16],\"duration_millis\":35351,\"variants\":[{\"bitrate\":832000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254198030456229889\\\/pu\\\/vid\\\/360x640\\\/30eP9ptknO3qLid-.mp4?tag=10\"},{\"content_type\":\"application\\\/x-mpegURL\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254198030456229889\\\/pu\\\/pl\\\/NXuY-zobKc-6axzl.m3u8?tag=10\"},{\"bitrate\":2176000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254198030456229889\\\/pu\\\/vid\\\/576x1024\\\/Ck76pIe6yXKpNyVZ.mp4?tag=10\"},{\"bitrate\":632000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254198030456229889\\\/pu\\\/vid\\\/320x568\\\/RCXAMh3Ovls7yeiM.mp4?tag=10\"}]},\"additional_media_info\":{\"monetizable\":false,\"source_user\":{\"id\":976340242881015814,\"id_str\":\"976340242881015814\",\"name\":\"Tik Tokers\",\"screen_name\":\"Tik_Tokers_\",\"location\":\"Latam\",\"description\":\"Recopilaci\\u00f3n de los mejores videos de Tik Tok\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":33814,\"friends_count\":1,\"listed_count\":53,\"created_at\":\"Wed Mar 21 06:10:28 +0000 2018\",\"favourites_count\":1567,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":126,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"000000\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1253161914299023360\\\/V7mPCvbI_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1253161914299023360\\\/V7mPCvbI_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/976340242881015814\\\/1587612082\",\"profile_link_color\":\"981CEB\",\"profile_sidebar_border_color\":\"000000\",\"profile_sidebar_fill_color\":\"000000\",\"profile_text_color\":\"000000\",\"profile_use_background_image\":false,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"}}}]},\"metadata\":{\"iso_language_code\":\"es\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/android\\\" rel=\\\"nofollow\\\"\\u003eTwitter for Android\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":163290335,\"id_str\":\"163290335\",\"name\":\"Maynor Cruz\",\"screen_name\":\"Maynor317\",\"location\":\"Tegucigalpa, Honduras\",\"description\":\"Es muy dif\\u00edcil describirse a si mismo cuando ni uno mismo se conoce lo suficientemente bien.\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":176,\"friends_count\":955,\"listed_count\":2,\"created_at\":\"Tue Jul 06 01:34:16 +0000 2010\",\"favourites_count\":920,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":2627,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"ACDED6\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1216440733860802560\\\/tGqc_vLm_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1216440733860802560\\\/tGqc_vLm_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/163290335\\\/1517883559\",\"profile_link_color\":\"1B95E0\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Sat Apr 25 23:58:31 +0000 2020\",\"id\":1254198133313191936,\"id_str\":\"1254198133313191936\",\"text\":\"Error de calculo https:\\\/\\\/t.co\\\/ew3lt96L2Y\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[],\"media\":[{\"id\":1254198030456229889,\"id_str\":\"1254198030456229889\",\"indices\":[17,40],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254198030456229889\\\/pu\\\/img\\\/5GCvS6_dUfUtRbcy.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254198030456229889\\\/pu\\\/img\\\/5GCvS6_dUfUtRbcy.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/ew3lt96L2Y\",\"display_url\":\"pic.twitter.com\\\/ew3lt96L2Y\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/Tik_Tokers_\\\/status\\\/1254198133313191936\\\/video\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":383,\"h\":680,\"resize\":\"fit\"},\"large\":{\"w\":576,\"h\":1024,\"resize\":\"fit\"},\"medium\":{\"w\":576,\"h\":1024,\"resize\":\"fit\"}}}]},\"extended_entities\":{\"media\":[{\"id\":1254198030456229889,\"id_str\":\"1254198030456229889\",\"indices\":[17,40],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254198030456229889\\\/pu\\\/img\\\/5GCvS6_dUfUtRbcy.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254198030456229889\\\/pu\\\/img\\\/5GCvS6_dUfUtRbcy.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/ew3lt96L2Y\",\"display_url\":\"pic.twitter.com\\\/ew3lt96L2Y\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/Tik_Tokers_\\\/status\\\/1254198133313191936\\\/video\\\/1\",\"type\":\"video\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":383,\"h\":680,\"resize\":\"fit\"},\"large\":{\"w\":576,\"h\":1024,\"resize\":\"fit\"},\"medium\":{\"w\":576,\"h\":1024,\"resize\":\"fit\"}},\"video_info\":{\"aspect_ratio\":[9,16],\"duration_millis\":35351,\"variants\":[{\"bitrate\":832000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254198030456229889\\\/pu\\\/vid\\\/360x640\\\/30eP9ptknO3qLid-.mp4?tag=10\"},{\"content_type\":\"application\\\/x-mpegURL\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254198030456229889\\\/pu\\\/pl\\\/NXuY-zobKc-6axzl.m3u8?tag=10\"},{\"bitrate\":2176000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254198030456229889\\\/pu\\\/vid\\\/576x1024\\\/Ck76pIe6yXKpNyVZ.mp4?tag=10\"},{\"bitrate\":632000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254198030456229889\\\/pu\\\/vid\\\/320x568\\\/RCXAMh3Ovls7yeiM.mp4?tag=10\"}]},\"additional_media_info\":{\"monetizable\":false}}]},\"metadata\":{\"iso_language_code\":\"es\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":976340242881015814,\"id_str\":\"976340242881015814\",\"name\":\"Tik Tokers\",\"screen_name\":\"Tik_Tokers_\",\"location\":\"Latam\",\"description\":\"Recopilaci\\u00f3n de los mejores videos de Tik Tok\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":33814,\"friends_count\":1,\"listed_count\":53,\"created_at\":\"Wed Mar 21 06:10:28 +0000 2018\",\"favourites_count\":1567,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":126,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"000000\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1253161914299023360\\\/V7mPCvbI_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1253161914299023360\\\/V7mPCvbI_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/976340242881015814\\\/1587612082\",\"profile_link_color\":\"981CEB\",\"profile_sidebar_border_color\":\"000000\",\"profile_sidebar_fill_color\":\"000000\",\"profile_text_color\":\"000000\",\"profile_use_background_image\":false,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":86,\"favorite_count\":211,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"es\"},\"is_quote_status\":false,\"retweet_count\":86,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"es\"},{\"created_at\":\"Sun Apr 26 00:31:48 +0000 2020\",\"id\":1254206511145943040,\"id_str\":\"1254206511145943040\",\"text\":\"RT @d_rab1a: Les anglais qui apprennent le fran\\u00e7ais\\ud83d\\ude2d\\ud83d\\ude2d\\ud83d\\ude2d\\ud83d\\ude2d https:\\\/\\\/t.co\\\/R4VW9TQDr1\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"d_rab1a\",\"name\":\"DOH REMI\",\"id\":1005126366545801216,\"id_str\":\"1005126366545801216\",\"indices\":[3,11]}],\"urls\":[],\"media\":[{\"id\":1254111657976004610,\"id_str\":\"1254111657976004610\",\"indices\":[56,79],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254111657976004610\\\/pu\\\/img\\\/ZQIGAKuujcABTL4A.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254111657976004610\\\/pu\\\/img\\\/ZQIGAKuujcABTL4A.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/R4VW9TQDr1\",\"display_url\":\"pic.twitter.com\\\/R4VW9TQDr1\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/d_rab1a\\\/status\\\/1254111706856468481\\\/video\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"medium\":{\"w\":540,\"h\":960,\"resize\":\"fit\"},\"small\":{\"w\":383,\"h\":680,\"resize\":\"fit\"},\"large\":{\"w\":540,\"h\":960,\"resize\":\"fit\"}},\"source_status_id\":1254111706856468481,\"source_status_id_str\":\"1254111706856468481\",\"source_user_id\":1005126366545801216,\"source_user_id_str\":\"1005126366545801216\"}]},\"extended_entities\":{\"media\":[{\"id\":1254111657976004610,\"id_str\":\"1254111657976004610\",\"indices\":[56,79],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254111657976004610\\\/pu\\\/img\\\/ZQIGAKuujcABTL4A.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254111657976004610\\\/pu\\\/img\\\/ZQIGAKuujcABTL4A.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/R4VW9TQDr1\",\"display_url\":\"pic.twitter.com\\\/R4VW9TQDr1\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/d_rab1a\\\/status\\\/1254111706856468481\\\/video\\\/1\",\"type\":\"video\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"medium\":{\"w\":540,\"h\":960,\"resize\":\"fit\"},\"small\":{\"w\":383,\"h\":680,\"resize\":\"fit\"},\"large\":{\"w\":540,\"h\":960,\"resize\":\"fit\"}},\"source_status_id\":1254111706856468481,\"source_status_id_str\":\"1254111706856468481\",\"source_user_id\":1005126366545801216,\"source_user_id_str\":\"1005126366545801216\",\"video_info\":{\"aspect_ratio\":[9,16],\"duration_millis\":21193,\"variants\":[{\"bitrate\":2176000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254111657976004610\\\/pu\\\/vid\\\/540x960\\\/shzeE1tFoliZQnH-.mp4?tag=10\"},{\"bitrate\":632000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254111657976004610\\\/pu\\\/vid\\\/320x568\\\/nM57kk80PS3gnzFf.mp4?tag=10\"},{\"content_type\":\"application\\\/x-mpegURL\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254111657976004610\\\/pu\\\/pl\\\/xVxIakbjQjoYHkYo.m3u8?tag=10\"},{\"bitrate\":832000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254111657976004610\\\/pu\\\/vid\\\/360x640\\\/rvozbdj9dBEBGr4k.mp4?tag=10\"}]},\"additional_media_info\":{\"monetizable\":false,\"source_user\":{\"id\":1005126366545801216,\"id_str\":\"1005126366545801216\",\"name\":\"DOH REMI\",\"screen_name\":\"d_rab1a\",\"location\":\"Bruxelles, Belgique\",\"description\":\"\\u0636\\u062d\\u0649\\ud83c\\uddf5\\ud83c\\uddf8\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":1580,\"friends_count\":1447,\"listed_count\":0,\"created_at\":\"Fri Jun 08 16:36:14 +0000 2018\",\"favourites_count\":4522,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":3226,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1243947972867604480\\\/yoc3pSRx_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1243947972867604480\\\/yoc3pSRx_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/1005126366545801216\\\/1587318525\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"}}}]},\"metadata\":{\"iso_language_code\":\"fr\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":746068949436141568,\"id_str\":\"746068949436141568\",\"name\":\"dan\",\"screen_name\":\"dan_uds\",\"location\":\"\",\"description\":\"\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":66,\"friends_count\":239,\"listed_count\":1,\"created_at\":\"Thu Jun 23 19:54:33 +0000 2016\",\"favourites_count\":22552,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":3985,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1215954895657979904\\\/5vAunFWw_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1215954895657979904\\\/5vAunFWw_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/746068949436141568\\\/1586795961\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Sat Apr 25 18:15:05 +0000 2020\",\"id\":1254111706856468481,\"id_str\":\"1254111706856468481\",\"text\":\"Les anglais qui apprennent le fran\\u00e7ais\\ud83d\\ude2d\\ud83d\\ude2d\\ud83d\\ude2d\\ud83d\\ude2d https:\\\/\\\/t.co\\\/R4VW9TQDr1\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[],\"media\":[{\"id\":1254111657976004610,\"id_str\":\"1254111657976004610\",\"indices\":[43,66],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254111657976004610\\\/pu\\\/img\\\/ZQIGAKuujcABTL4A.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254111657976004610\\\/pu\\\/img\\\/ZQIGAKuujcABTL4A.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/R4VW9TQDr1\",\"display_url\":\"pic.twitter.com\\\/R4VW9TQDr1\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/d_rab1a\\\/status\\\/1254111706856468481\\\/video\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"medium\":{\"w\":540,\"h\":960,\"resize\":\"fit\"},\"small\":{\"w\":383,\"h\":680,\"resize\":\"fit\"},\"large\":{\"w\":540,\"h\":960,\"resize\":\"fit\"}}}]},\"extended_entities\":{\"media\":[{\"id\":1254111657976004610,\"id_str\":\"1254111657976004610\",\"indices\":[43,66],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254111657976004610\\\/pu\\\/img\\\/ZQIGAKuujcABTL4A.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254111657976004610\\\/pu\\\/img\\\/ZQIGAKuujcABTL4A.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/R4VW9TQDr1\",\"display_url\":\"pic.twitter.com\\\/R4VW9TQDr1\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/d_rab1a\\\/status\\\/1254111706856468481\\\/video\\\/1\",\"type\":\"video\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"medium\":{\"w\":540,\"h\":960,\"resize\":\"fit\"},\"small\":{\"w\":383,\"h\":680,\"resize\":\"fit\"},\"large\":{\"w\":540,\"h\":960,\"resize\":\"fit\"}},\"video_info\":{\"aspect_ratio\":[9,16],\"duration_millis\":21193,\"variants\":[{\"bitrate\":2176000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254111657976004610\\\/pu\\\/vid\\\/540x960\\\/shzeE1tFoliZQnH-.mp4?tag=10\"},{\"bitrate\":632000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254111657976004610\\\/pu\\\/vid\\\/320x568\\\/nM57kk80PS3gnzFf.mp4?tag=10\"},{\"content_type\":\"application\\\/x-mpegURL\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254111657976004610\\\/pu\\\/pl\\\/xVxIakbjQjoYHkYo.m3u8?tag=10\"},{\"bitrate\":832000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254111657976004610\\\/pu\\\/vid\\\/360x640\\\/rvozbdj9dBEBGr4k.mp4?tag=10\"}]},\"additional_media_info\":{\"monetizable\":false}}]},\"metadata\":{\"iso_language_code\":\"fr\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":1005126366545801216,\"id_str\":\"1005126366545801216\",\"name\":\"DOH REMI\",\"screen_name\":\"d_rab1a\",\"location\":\"Bruxelles, Belgique\",\"description\":\"\\u0636\\u062d\\u0649\\ud83c\\uddf5\\ud83c\\uddf8\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":1580,\"friends_count\":1447,\"listed_count\":0,\"created_at\":\"Fri Jun 08 16:36:14 +0000 2018\",\"favourites_count\":4522,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":3226,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1243947972867604480\\\/yoc3pSRx_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1243947972867604480\\\/yoc3pSRx_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/1005126366545801216\\\/1587318525\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":14439,\"favorite_count\":27410,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"fr\"},\"is_quote_status\":false,\"retweet_count\":14439,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"fr\"},{\"created_at\":\"Sun Apr 26 00:31:48 +0000 2020\",\"id\":1254206511145865216,\"id_str\":\"1254206511145865216\",\"text\":\"RT @clmazin: Vichnaya pamyat. https:\\\/\\\/t.co\\\/PJhpWbTdtD\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"clmazin\",\"name\":\"Craig Mazin\",\"id\":22720093,\"id_str\":\"22720093\",\"indices\":[3,11]}],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/PJhpWbTdtD\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/atomicanalyst\\\/status\\\/1254174281656926208\",\"display_url\":\"twitter.com\\\/atomicanalyst\\\/\\u2026\",\"indices\":[30,53]}]},\"metadata\":{\"iso_language_code\":\"tl\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/mobile.twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web App\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":3265558424,\"id_str\":\"3265558424\",\"name\":\"Kevin Fox\",\"screen_name\":\"Michigrimk\",\"location\":\"Los Angeles\\\/Santa Barbara\",\"description\":\"Writer, director, actor, now podcaster also have a variety of odd side hustles including secret corporate contract work. Screencraft Semi-Finalist.\",\"url\":\"https:\\\/\\\/t.co\\\/ORCNvzV9Vo\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/ORCNvzV9Vo\",\"expanded_url\":\"http:\\\/\\\/theywontletmeleavethisblank.ca\",\"display_url\":\"theywontletmeleavethisblank.ca\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":1262,\"friends_count\":2177,\"listed_count\":14,\"created_at\":\"Thu Jul 02 01:03:17 +0000 2015\",\"favourites_count\":51124,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":15618,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1244701555674079234\\\/BQ7SHxPl_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1244701555674079234\\\/BQ7SHxPl_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/3265558424\\\/1576372151\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Sun Apr 26 00:30:53 +0000 2020\",\"id\":1254206276520693762,\"id_str\":\"1254206276520693762\",\"text\":\"Vichnaya pamyat. https:\\\/\\\/t.co\\\/PJhpWbTdtD\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/PJhpWbTdtD\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/atomicanalyst\\\/status\\\/1254174281656926208\",\"display_url\":\"twitter.com\\\/atomicanalyst\\\/\\u2026\",\"indices\":[17,40]}]},\"metadata\":{\"iso_language_code\":\"tl\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/#!\\\/download\\\/ipad\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPad\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":22720093,\"id_str\":\"22720093\",\"name\":\"Craig Mazin\",\"screen_name\":\"clmazin\",\"location\":\"La Ca\\u00f1ada Flintridge\",\"description\":\"Writer-Producer of the upcoming @HBO series The Last of Us with @neil_druckmann\\n\\nWriter-Producer of #CHERNOBYL on @HBO and @SkyAtlantic.\",\"url\":\"https:\\\/\\\/t.co\\\/VcpdGm3NDF\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/VcpdGm3NDF\",\"expanded_url\":\"https:\\\/\\\/www.hbo.com\\\/chernobyl\",\"display_url\":\"hbo.com\\\/chernobyl\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":208886,\"friends_count\":825,\"listed_count\":1362,\"created_at\":\"Wed Mar 04 02:24:54 +0000 2009\",\"favourites_count\":35834,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":true,\"statuses_count\":13790,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1235619341795655680\\\/4bY4EBJO_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1235619341795655680\\\/4bY4EBJO_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/22720093\\\/1583429585\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":true,\"quoted_status_id\":1254174281656926208,\"quoted_status_id_str\":\"1254174281656926208\",\"quoted_status\":{\"created_at\":\"Sat Apr 25 22:23:44 +0000 2020\",\"id\":1254174281656926208,\"id_str\":\"1254174281656926208\",\"text\":\"Right now in 1986 (1:23:45am local time, Sat. April 26), the badly-designed Chernobyl Unit 4 nuclear reactor in Pri\\u2026 https:\\\/\\\/t.co\\\/zhoO4T7n9m\",\"truncated\":true,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/zhoO4T7n9m\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/i\\\/web\\\/status\\\/1254174281656926208\",\"display_url\":\"twitter.com\\\/i\\\/web\\\/status\\\/1\\u2026\",\"indices\":[117,140]}]},\"metadata\":{\"iso_language_code\":\"tl\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/mobile.twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web App\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":1413698887,\"id_str\":\"1413698887\",\"name\":\"Stephen Schwartz\",\"screen_name\":\"AtomicAnalyst\",\"location\":\"Chicago, IL\",\"description\":\"Nonresident Senior Fellow @BulletinAtomic \\u2022 Fellow @NSquareCollab \\u2022 Editor\\\/Co-author, Atomic Audit: The Costs and Consequences of US Nuclear Weapons Since 1940\",\"url\":\"https:\\\/\\\/t.co\\\/MPTzW7OgrR\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/MPTzW7OgrR\",\"expanded_url\":\"https:\\\/\\\/www.brookings.edu\\\/book\\\/atomic-audit\\\/\",\"display_url\":\"brookings.edu\\\/book\\\/atomic-au\\u2026\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":31974,\"friends_count\":1296,\"listed_count\":551,\"created_at\":\"Wed May 08 19:46:38 +0000 2013\",\"favourites_count\":2014,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":true,\"statuses_count\":26480,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"DBE9ED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme17\\\/bg.gif\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme17\\\/bg.gif\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/940479981636988928\\\/uWWAxh4y_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/940479981636988928\\\/uWWAxh4y_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/1413698887\\\/1436508483\",\"profile_link_color\":\"7A17A4\",\"profile_sidebar_border_color\":\"000000\",\"profile_sidebar_fill_color\":\"000000\",\"profile_text_color\":\"000000\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":48,\"favorite_count\":46,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"en\"},\"retweet_count\":2,\"favorite_count\":15,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"tl\"},\"is_quote_status\":true,\"quoted_status_id\":1254174281656926208,\"quoted_status_id_str\":\"1254174281656926208\",\"retweet_count\":2,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"tl\"},{\"created_at\":\"Sun Apr 26 00:31:48 +0000 2020\",\"id\":1254206511141830659,\"id_str\":\"1254206511141830659\",\"text\":\"I came https:\\\/\\\/t.co\\\/EHWIyO9BZc\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/EHWIyO9BZc\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/mauriliobarbosa\\\/status\\\/1254204175950524427\",\"display_url\":\"twitter.com\\\/mauriliobarbos\\u2026\",\"indices\":[7,30]}]},\"metadata\":{\"iso_language_code\":\"en\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":161871073,\"id_str\":\"161871073\",\"name\":\"dordoris \\ud83e\\udd91 \\ud83d\\udea9\",\"screen_name\":\"Dordoris\",\"location\":\"Brazil\",\"description\":\"There yet are two things in my destiny: a world to roam through, and a home with thee.\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":623,\"friends_count\":668,\"listed_count\":15,\"created_at\":\"Fri Jul 02 00:45:32 +0000 2010\",\"favourites_count\":51198,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":67019,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"DADFE8\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme14\\\/bg.gif\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme14\\\/bg.gif\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1183182356393447425\\\/FMddfmxw_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1183182356393447425\\\/FMddfmxw_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/161871073\\\/1554476656\",\"profile_link_color\":\"1F2DA6\",\"profile_sidebar_border_color\":\"FFFFFF\",\"profile_sidebar_fill_color\":\"DEDEDE\",\"profile_text_color\":\"000000\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":true,\"quoted_status_id\":1254204175950524427,\"quoted_status_id_str\":\"1254204175950524427\",\"quoted_status\":{\"created_at\":\"Sun Apr 26 00:22:32 +0000 2020\",\"id\":1254204175950524427,\"id_str\":\"1254204175950524427\",\"text\":\"A legenda \\u00e9 de voc\\u00eas https:\\\/\\\/t.co\\\/3HTwUY9OZc\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[],\"media\":[{\"id\":1254204170313359362,\"id_str\":\"1254204170313359362\",\"indices\":[21,44],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfUDD9XYAILHtR.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfUDD9XYAILHtR.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/3HTwUY9OZc\",\"display_url\":\"pic.twitter.com\\\/3HTwUY9OZc\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/MaurilioBarbosa\\\/status\\\/1254204175950524427\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"medium\":{\"w\":1086,\"h\":652,\"resize\":\"fit\"},\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"large\":{\"w\":1086,\"h\":652,\"resize\":\"fit\"},\"small\":{\"w\":680,\"h\":408,\"resize\":\"fit\"}}}]},\"extended_entities\":{\"media\":[{\"id\":1254204170313359362,\"id_str\":\"1254204170313359362\",\"indices\":[21,44],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfUDD9XYAILHtR.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfUDD9XYAILHtR.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/3HTwUY9OZc\",\"display_url\":\"pic.twitter.com\\\/3HTwUY9OZc\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/MaurilioBarbosa\\\/status\\\/1254204175950524427\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"medium\":{\"w\":1086,\"h\":652,\"resize\":\"fit\"},\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"large\":{\"w\":1086,\"h\":652,\"resize\":\"fit\"},\"small\":{\"w\":680,\"h\":408,\"resize\":\"fit\"}}}]},\"metadata\":{\"iso_language_code\":\"en\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":63296611,\"id_str\":\"63296611\",\"name\":\"maumau\",\"screen_name\":\"MaurilioBarbosa\",\"location\":\"Campo Grande, Brasil\",\"description\":\"Neste perfil n\\u00e3o damos palco para malucos. Mestre pela UFMS e doutorando pela UNICAMP\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":49584,\"friends_count\":35365,\"listed_count\":218,\"created_at\":\"Wed Aug 05 23:35:34 +0000 2009\",\"favourites_count\":35847,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":71454,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"1A1B1F\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme9\\\/bg.gif\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme9\\\/bg.gif\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1249046386231914498\\\/1PBZdGA4_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1249046386231914498\\\/1PBZdGA4_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/63296611\\\/1575659825\",\"profile_link_color\":\"ABB8C2\",\"profile_sidebar_border_color\":\"FFFFFF\",\"profile_sidebar_fill_color\":\"252429\",\"profile_text_color\":\"666666\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":3,\"favorite_count\":53,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"pt\"},\"retweet_count\":0,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"en\"},{\"created_at\":\"Sun Apr 26 00:31:48 +0000 2020\",\"id\":1254206511141683200,\"id_str\":\"1254206511141683200\",\"text\":\"RT @JDak_7: man onna a mission #TRUZZ that\",\"truncated\":false,\"entities\":{\"hashtags\":[{\"text\":\"TRUZZ\",\"indices\":[31,37]}],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"JDak_7\",\"name\":\"John Daka\",\"id\":117885335,\"id_str\":\"117885335\",\"indices\":[3,10]}],\"urls\":[]},\"metadata\":{\"iso_language_code\":\"en\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":3302055140,\"id_str\":\"3302055140\",\"name\":\"Silky Johnson 51\\\/50\",\"screen_name\":\"FluFlamSam\",\"location\":\"North Orange County California\",\"description\":\"Email: bandokizzlemusic@gmail.com #RAVENFLOCK OR DONT TALK \\ud83e\\udd2b\",\"url\":\"https:\\\/\\\/t.co\\\/cusngmsWfC\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/cusngmsWfC\",\"expanded_url\":\"https:\\\/\\\/soundcloud.com\\\/bandokizzle\\\/digits-bando-kizzle-ft-dom-the-kidprod-big-head\",\"display_url\":\"soundcloud.com\\\/bandokizzle\\\/di\\u2026\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":411,\"friends_count\":567,\"listed_count\":7,\"created_at\":\"Fri Jul 31 03:45:40 +0000 2015\",\"favourites_count\":68955,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":42116,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1205338096717271040\\\/xYN8R9jF_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1205338096717271040\\\/xYN8R9jF_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/3302055140\\\/1507655714\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Sat Apr 25 23:10:20 +0000 2020\",\"id\":1254186008909930496,\"id_str\":\"1254186008909930496\",\"text\":\"man onna a mission #TRUZZ that https:\\\/\\\/t.co\\\/IVGew8CgF3\",\"truncated\":false,\"entities\":{\"hashtags\":[{\"text\":\"TRUZZ\",\"indices\":[19,25]}],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/IVGew8CgF3\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/madia_dnrsports\\\/status\\\/1254184166503190535\",\"display_url\":\"twitter.com\\\/madia_dnrsport\\u2026\",\"indices\":[31,54]}]},\"metadata\":{\"iso_language_code\":\"en\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":117885335,\"id_str\":\"117885335\",\"name\":\"John Daka\",\"screen_name\":\"JDak_7\",\"location\":\"301\\u27a1\\ufe0f540\",\"description\":\"\\ud83c\\uddff\\ud83c\\uddf2 #CEO\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":1225,\"friends_count\":501,\"listed_count\":8,\"created_at\":\"Fri Feb 26 23:09:30 +0000 2010\",\"favourites_count\":4364,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":24098,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"131516\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme14\\\/bg.gif\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme14\\\/bg.gif\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1219794881574580224\\\/BuvqE1J0_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1219794881574580224\\\/BuvqE1J0_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/117885335\\\/1574298518\",\"profile_link_color\":\"009999\",\"profile_sidebar_border_color\":\"EEEEEE\",\"profile_sidebar_fill_color\":\"EFEFEF\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":true,\"quoted_status_id\":1254184166503190535,\"quoted_status_id_str\":\"1254184166503190535\",\"quoted_status\":{\"created_at\":\"Sat Apr 25 23:03:01 +0000 2020\",\"id\":1254184166503190535,\"id_str\":\"1254184166503190535\",\"text\":\"That was quick. JMU defensive end John Daka, the 2019 FCS leader in sacks and tackles for loss, tells me he's signe\\u2026 https:\\\/\\\/t.co\\\/hQSoxHFl58\",\"truncated\":true,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/hQSoxHFl58\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/i\\\/web\\\/status\\\/1254184166503190535\",\"display_url\":\"twitter.com\\\/i\\\/web\\\/status\\\/1\\u2026\",\"indices\":[117,140]}]},\"metadata\":{\"iso_language_code\":\"en\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/about.twitter.com\\\/products\\\/tweetdeck\\\" rel=\\\"nofollow\\\"\\u003eTweetDeck\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":156844983,\"id_str\":\"156844983\",\"name\":\"Greg Madia\",\"screen_name\":\"Madia_DNRSports\",\"location\":\"Harrisonburg, VA\",\"description\":\"JMU football beat writer at the Daily News-Record. Some local college baseball, too. FWAA member. Jersey native. Loyal Mets fan.\",\"url\":\"https:\\\/\\\/t.co\\\/1wGAAi4HQg\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/1wGAAi4HQg\",\"expanded_url\":\"https:\\\/\\\/www.dnronline.com\\\/users\\\/profile\\\/football\\\/\",\"display_url\":\"dnronline.com\\\/users\\\/profile\\\/\\u2026\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":3827,\"friends_count\":886,\"listed_count\":70,\"created_at\":\"Fri Jun 18 02:58:08 +0000 2010\",\"favourites_count\":1815,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":25097,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1028971098547908610\\\/trORIIsG_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1028971098547908610\\\/trORIIsG_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/156844983\\\/1492867256\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":246,\"favorite_count\":647,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"en\"},\"retweet_count\":87,\"favorite_count\":345,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"en\"},\"is_quote_status\":true,\"quoted_status_id\":1254184166503190535,\"quoted_status_id_str\":\"1254184166503190535\",\"retweet_count\":87,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"en\"},{\"created_at\":\"Sun Apr 26 00:31:48 +0000 2020\",\"id\":1254206511137488902,\"id_str\":\"1254206511137488902\",\"text\":\"RT @vonetop: \\ub208\\ubb3c\\ucb50\\ucb50 https:\\\/\\\/t.co\\\/Dej8eb7r93\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"vonetop\",\"name\":\"\\ud83d\\ude2e\\ud83d\\ude2f\\ud83d\\ude32\",\"id\":1213824878865862656,\"id_str\":\"1213824878865862656\",\"indices\":[3,11]}],\"urls\":[],\"media\":[{\"id\":1254129066136887296,\"id_str\":\"1254129066136887296\",\"indices\":[18,41],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254129066136887296\\\/pu\\\/img\\\/SpR_1MxnofjjrzOF.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254129066136887296\\\/pu\\\/img\\\/SpR_1MxnofjjrzOF.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/Dej8eb7r93\",\"display_url\":\"pic.twitter.com\\\/Dej8eb7r93\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/vonetop\\\/status\\\/1254129086844112896\\\/video\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":680,\"h\":680,\"resize\":\"fit\"},\"large\":{\"w\":1080,\"h\":1080,\"resize\":\"fit\"},\"medium\":{\"w\":1080,\"h\":1080,\"resize\":\"fit\"}},\"source_status_id\":1254129086844112896,\"source_status_id_str\":\"1254129086844112896\",\"source_user_id\":1213824878865862656,\"source_user_id_str\":\"1213824878865862656\"}]},\"extended_entities\":{\"media\":[{\"id\":1254129066136887296,\"id_str\":\"1254129066136887296\",\"indices\":[18,41],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254129066136887296\\\/pu\\\/img\\\/SpR_1MxnofjjrzOF.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254129066136887296\\\/pu\\\/img\\\/SpR_1MxnofjjrzOF.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/Dej8eb7r93\",\"display_url\":\"pic.twitter.com\\\/Dej8eb7r93\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/vonetop\\\/status\\\/1254129086844112896\\\/video\\\/1\",\"type\":\"video\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":680,\"h\":680,\"resize\":\"fit\"},\"large\":{\"w\":1080,\"h\":1080,\"resize\":\"fit\"},\"medium\":{\"w\":1080,\"h\":1080,\"resize\":\"fit\"}},\"source_status_id\":1254129086844112896,\"source_status_id_str\":\"1254129086844112896\",\"source_user_id\":1213824878865862656,\"source_user_id_str\":\"1213824878865862656\",\"video_info\":{\"aspect_ratio\":[1,1],\"duration_millis\":1900,\"variants\":[{\"content_type\":\"application\\\/x-mpegURL\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254129066136887296\\\/pu\\\/pl\\\/ZbfkGtSG2pyrOmb2.m3u8?tag=10\"},{\"bitrate\":432000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254129066136887296\\\/pu\\\/vid\\\/320x320\\\/dHHcq68LQmtbXzKr.mp4?tag=10\"},{\"bitrate\":1280000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254129066136887296\\\/pu\\\/vid\\\/720x720\\\/Ee2Cs_hIlk6vXppu.mp4?tag=10\"},{\"bitrate\":832000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254129066136887296\\\/pu\\\/vid\\\/480x480\\\/FkbEy_pfyBpCg_og.mp4?tag=10\"}]},\"additional_media_info\":{\"monetizable\":false,\"source_user\":{\"id\":1213824878865862656,\"id_str\":\"1213824878865862656\",\"name\":\"\\ud83d\\ude2e\\ud83d\\ude2f\\ud83d\\ude32\",\"screen_name\":\"vonetop\",\"location\":\"\",\"description\":\"(\\uc77d\\uc74c)\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":2243,\"friends_count\":35,\"listed_count\":32,\"created_at\":\"Sun Jan 05 14:09:46 +0000 2020\",\"favourites_count\":899,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":3746,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1253738871088537606\\\/5-qrPmca_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1253738871088537606\\\/5-qrPmca_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/1213824878865862656\\\/1584029278\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"}}}]},\"metadata\":{\"result_type\":\"recent\",\"iso_language_code\":\"ko\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":946774125384679424,\"id_str\":\"946774125384679424\",\"name\":\"\\u25e1\\u0308 forever_V_BTS\",\"screen_name\":\"michellejiji7\",\"location\":\"\",\"description\":\"\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":74,\"friends_count\":123,\"listed_count\":1,\"created_at\":\"Fri Dec 29 16:05:16 +0000 2017\",\"favourites_count\":133937,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":92065,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1223987207733514242\\\/x16VrS6u_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1223987207733514242\\\/x16VrS6u_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/946774125384679424\\\/1580656267\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Sat Apr 25 19:24:09 +0000 2020\",\"id\":1254129086844112896,\"id_str\":\"1254129086844112896\",\"text\":\"\\ub208\\ubb3c\\ucb50\\ucb50 https:\\\/\\\/t.co\\\/Dej8eb7r93\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[],\"media\":[{\"id\":1254129066136887296,\"id_str\":\"1254129066136887296\",\"indices\":[5,28],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254129066136887296\\\/pu\\\/img\\\/SpR_1MxnofjjrzOF.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254129066136887296\\\/pu\\\/img\\\/SpR_1MxnofjjrzOF.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/Dej8eb7r93\",\"display_url\":\"pic.twitter.com\\\/Dej8eb7r93\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/vonetop\\\/status\\\/1254129086844112896\\\/video\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":680,\"h\":680,\"resize\":\"fit\"},\"large\":{\"w\":1080,\"h\":1080,\"resize\":\"fit\"},\"medium\":{\"w\":1080,\"h\":1080,\"resize\":\"fit\"}}}]},\"extended_entities\":{\"media\":[{\"id\":1254129066136887296,\"id_str\":\"1254129066136887296\",\"indices\":[5,28],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254129066136887296\\\/pu\\\/img\\\/SpR_1MxnofjjrzOF.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254129066136887296\\\/pu\\\/img\\\/SpR_1MxnofjjrzOF.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/Dej8eb7r93\",\"display_url\":\"pic.twitter.com\\\/Dej8eb7r93\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/vonetop\\\/status\\\/1254129086844112896\\\/video\\\/1\",\"type\":\"video\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":680,\"h\":680,\"resize\":\"fit\"},\"large\":{\"w\":1080,\"h\":1080,\"resize\":\"fit\"},\"medium\":{\"w\":1080,\"h\":1080,\"resize\":\"fit\"}},\"video_info\":{\"aspect_ratio\":[1,1],\"duration_millis\":1900,\"variants\":[{\"content_type\":\"application\\\/x-mpegURL\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254129066136887296\\\/pu\\\/pl\\\/ZbfkGtSG2pyrOmb2.m3u8?tag=10\"},{\"bitrate\":432000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254129066136887296\\\/pu\\\/vid\\\/320x320\\\/dHHcq68LQmtbXzKr.mp4?tag=10\"},{\"bitrate\":1280000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254129066136887296\\\/pu\\\/vid\\\/720x720\\\/Ee2Cs_hIlk6vXppu.mp4?tag=10\"},{\"bitrate\":832000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254129066136887296\\\/pu\\\/vid\\\/480x480\\\/FkbEy_pfyBpCg_og.mp4?tag=10\"}]},\"additional_media_info\":{\"monetizable\":false}}]},\"metadata\":{\"result_type\":\"recent\",\"iso_language_code\":\"ko\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":1213824878865862656,\"id_str\":\"1213824878865862656\",\"name\":\"\\ud83d\\ude2e\\ud83d\\ude2f\\ud83d\\ude32\",\"screen_name\":\"vonetop\",\"location\":\"\",\"description\":\"(\\uc77d\\uc74c)\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":2243,\"friends_count\":35,\"listed_count\":32,\"created_at\":\"Sun Jan 05 14:09:46 +0000 2020\",\"favourites_count\":899,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":3746,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1253738871088537606\\\/5-qrPmca_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1253738871088537606\\\/5-qrPmca_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/1213824878865862656\\\/1584029278\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":24,\"favorite_count\":42,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"ko\"},\"is_quote_status\":false,\"retweet_count\":24,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":true,\"lang\":\"ko\"},{\"created_at\":\"Sun Apr 26 00:31:48 +0000 2020\",\"id\":1254206511129284608,\"id_str\":\"1254206511129284608\",\"text\":\"RT @PARlSHITME: https:\\\/\\\/t.co\\\/3f5ATJ01qY\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"PARlSHITME\",\"name\":\"SUPERFICIAL\",\"id\":1069728005893836805,\"id_str\":\"1069728005893836805\",\"indices\":[3,14]}],\"urls\":[],\"media\":[{\"id\":1254047769230262275,\"id_str\":\"1254047769230262275\",\"indices\":[16,39],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWdFzUhXQAMTNb1.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWdFzUhXQAMTNb1.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/3f5ATJ01qY\",\"display_url\":\"pic.twitter.com\\\/3f5ATJ01qY\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/PARlSHITME\\\/status\\\/1254047772585721862\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"medium\":{\"w\":416,\"h\":305,\"resize\":\"fit\"},\"large\":{\"w\":416,\"h\":305,\"resize\":\"fit\"},\"small\":{\"w\":416,\"h\":305,\"resize\":\"fit\"}},\"source_status_id\":1254047772585721862,\"source_status_id_str\":\"1254047772585721862\",\"source_user_id\":1069728005893836805,\"source_user_id_str\":\"1069728005893836805\"}]},\"extended_entities\":{\"media\":[{\"id\":1254047769230262275,\"id_str\":\"1254047769230262275\",\"indices\":[16,39],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWdFzUhXQAMTNb1.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWdFzUhXQAMTNb1.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/3f5ATJ01qY\",\"display_url\":\"pic.twitter.com\\\/3f5ATJ01qY\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/PARlSHITME\\\/status\\\/1254047772585721862\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"medium\":{\"w\":416,\"h\":305,\"resize\":\"fit\"},\"large\":{\"w\":416,\"h\":305,\"resize\":\"fit\"},\"small\":{\"w\":416,\"h\":305,\"resize\":\"fit\"}},\"source_status_id\":1254047772585721862,\"source_status_id_str\":\"1254047772585721862\",\"source_user_id\":1069728005893836805,\"source_user_id_str\":\"1069728005893836805\"},{\"id\":1254047769234477056,\"id_str\":\"1254047769234477056\",\"indices\":[16,39],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWdFzUiXkAARNzL.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWdFzUiXkAARNzL.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/3f5ATJ01qY\",\"display_url\":\"pic.twitter.com\\\/3f5ATJ01qY\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/PARlSHITME\\\/status\\\/1254047772585721862\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"large\":{\"w\":416,\"h\":314,\"resize\":\"fit\"},\"medium\":{\"w\":416,\"h\":314,\"resize\":\"fit\"},\"small\":{\"w\":416,\"h\":314,\"resize\":\"fit\"}},\"source_status_id\":1254047772585721862,\"source_status_id_str\":\"1254047772585721862\",\"source_user_id\":1069728005893836805,\"source_user_id_str\":\"1069728005893836805\"}]},\"metadata\":{\"iso_language_code\":\"und\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":3313634721,\"id_str\":\"3313634721\",\"name\":\"\\ud83d\\udc96\",\"screen_name\":\"Rosykeenex\",\"location\":\"Islington, London\",\"description\":\"\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":484,\"friends_count\":232,\"listed_count\":4,\"created_at\":\"Mon Jun 08 18:34:35 +0000 2015\",\"favourites_count\":40405,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":44137,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1252638826658516992\\\/Lz9wdrUf_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1252638826658516992\\\/Lz9wdrUf_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/3313634721\\\/1564454636\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Sat Apr 25 14:01:02 +0000 2020\",\"id\":1254047772585721862,\"id_str\":\"1254047772585721862\",\"text\":\"https:\\\/\\\/t.co\\\/3f5ATJ01qY\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[],\"media\":[{\"id\":1254047769230262275,\"id_str\":\"1254047769230262275\",\"indices\":[0,23],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWdFzUhXQAMTNb1.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWdFzUhXQAMTNb1.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/3f5ATJ01qY\",\"display_url\":\"pic.twitter.com\\\/3f5ATJ01qY\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/PARlSHITME\\\/status\\\/1254047772585721862\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"medium\":{\"w\":416,\"h\":305,\"resize\":\"fit\"},\"large\":{\"w\":416,\"h\":305,\"resize\":\"fit\"},\"small\":{\"w\":416,\"h\":305,\"resize\":\"fit\"}}}]},\"extended_entities\":{\"media\":[{\"id\":1254047769230262275,\"id_str\":\"1254047769230262275\",\"indices\":[0,23],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWdFzUhXQAMTNb1.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWdFzUhXQAMTNb1.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/3f5ATJ01qY\",\"display_url\":\"pic.twitter.com\\\/3f5ATJ01qY\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/PARlSHITME\\\/status\\\/1254047772585721862\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"medium\":{\"w\":416,\"h\":305,\"resize\":\"fit\"},\"large\":{\"w\":416,\"h\":305,\"resize\":\"fit\"},\"small\":{\"w\":416,\"h\":305,\"resize\":\"fit\"}}},{\"id\":1254047769234477056,\"id_str\":\"1254047769234477056\",\"indices\":[0,23],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWdFzUiXkAARNzL.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWdFzUiXkAARNzL.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/3f5ATJ01qY\",\"display_url\":\"pic.twitter.com\\\/3f5ATJ01qY\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/PARlSHITME\\\/status\\\/1254047772585721862\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"large\":{\"w\":416,\"h\":314,\"resize\":\"fit\"},\"medium\":{\"w\":416,\"h\":314,\"resize\":\"fit\"},\"small\":{\"w\":416,\"h\":314,\"resize\":\"fit\"}}}]},\"metadata\":{\"iso_language_code\":\"und\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":1069728005893836805,\"id_str\":\"1069728005893836805\",\"name\":\"SUPERFICIAL\",\"screen_name\":\"PARlSHITME\",\"location\":\"The Mirror\",\"description\":\"Sex. Clothes. Popularity. Whatever.\",\"url\":\"https:\\\/\\\/t.co\\\/4L7mYwzcYM\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/4L7mYwzcYM\",\"expanded_url\":\"http:\\\/\\\/instagram.com\\\/tonyistrouble\",\"display_url\":\"instagram.com\\\/tonyistrouble\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":947,\"friends_count\":3,\"listed_count\":4,\"created_at\":\"Mon Dec 03 23:00:05 +0000 2018\",\"favourites_count\":3219,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":8249,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1078546663017463809\\\/Ef1LCu3m_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1078546663017463809\\\/Ef1LCu3m_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/1069728005893836805\\\/1547437240\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":17,\"favorite_count\":27,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"und\"},\"is_quote_status\":false,\"retweet_count\":17,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"und\"},{\"created_at\":\"Sun Apr 26 00:31:48 +0000 2020\",\"id\":1254206511129059329,\"id_str\":\"1254206511129059329\",\"text\":\"RT @jnxnvr: First Reese\\u2019s Pieces now this. I cannot believe I have to cancel Elle.\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"jnxnvr\",\"name\":\"\\ud83c\\udf28\",\"id\":828789651641098240,\"id_str\":\"828789651641098240\",\"indices\":[3,10]}],\"urls\":[]},\"metadata\":{\"iso_language_code\":\"en\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":1600218031,\"id_str\":\"1600218031\",\"name\":\"\\ud835\\udc86 \\ud835\\udd29 \\ud835\\udd29 \\ud835\\udc1e\",\"screen_name\":\"ElleGenerico\",\"location\":\"the boneyard \",\"description\":\"NOT Karl's actual wife\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":3766,\"friends_count\":593,\"listed_count\":99,\"created_at\":\"Wed Jul 17 05:58:52 +0000 2013\",\"favourites_count\":74770,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":56577,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"91D2FA\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1252278118854754307\\\/Ajy8xaYr_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1252278118854754307\\\/Ajy8xaYr_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/1600218031\\\/1573116819\",\"profile_link_color\":\"E81C4F\",\"profile_sidebar_border_color\":\"FFFFFF\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Sun Apr 26 00:29:43 +0000 2020\",\"id\":1254205984538537985,\"id_str\":\"1254205984538537985\",\"text\":\"First Reese\\u2019s Pieces now this. I cannot believe I have to cancel Elle. https:\\\/\\\/t.co\\\/79ssXrvgTD\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/79ssXrvgTD\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/ellegenerico\\\/status\\\/1254205718858629120\",\"display_url\":\"twitter.com\\\/ellegenerico\\\/s\\u2026\",\"indices\":[71,94]}]},\"metadata\":{\"iso_language_code\":\"en\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":828789651641098240,\"id_str\":\"828789651641098240\",\"name\":\"\\ud83c\\udf28\",\"screen_name\":\"jnxnvr\",\"location\":\"NYPD Special Victims Unit\",\"description\":\"meteorologist - writer - she\\\/her\",\"url\":\"https:\\\/\\\/t.co\\\/2ttaVeIxa8\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/2ttaVeIxa8\",\"expanded_url\":\"https:\\\/\\\/jsnaillon.journoportfolio.com\\\/\",\"display_url\":\"jsnaillon.journoportfolio.com\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":246,\"friends_count\":237,\"listed_count\":2,\"created_at\":\"Tue Feb 07 02:17:05 +0000 2017\",\"favourites_count\":4039,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":19326,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"000000\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1228571629166436352\\\/M5guYTkx_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1228571629166436352\\\/M5guYTkx_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/828789651641098240\\\/1565039785\",\"profile_link_color\":\"1122BB\",\"profile_sidebar_border_color\":\"000000\",\"profile_sidebar_fill_color\":\"000000\",\"profile_text_color\":\"000000\",\"profile_use_background_image\":false,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":true,\"quoted_status_id\":1254205718858629120,\"quoted_status_id_str\":\"1254205718858629120\",\"quoted_status\":{\"created_at\":\"Sun Apr 26 00:28:40 +0000 2020\",\"id\":1254205718858629120,\"id_str\":\"1254205718858629120\",\"text\":\"YES https:\\\/\\\/t.co\\\/dqzHMOIp1s\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/dqzHMOIp1s\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/jnxnvr\\\/status\\\/1254205620934381569\",\"display_url\":\"twitter.com\\\/jnxnvr\\\/status\\\/\\u2026\",\"indices\":[4,27]}]},\"metadata\":{\"iso_language_code\":\"en\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":1600218031,\"id_str\":\"1600218031\",\"name\":\"\\ud835\\udc86 \\ud835\\udd29 \\ud835\\udd29 \\ud835\\udc1e\",\"screen_name\":\"ElleGenerico\",\"location\":\"the boneyard \",\"description\":\"NOT Karl's actual wife\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":3766,\"friends_count\":593,\"listed_count\":99,\"created_at\":\"Wed Jul 17 05:58:52 +0000 2013\",\"favourites_count\":74770,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":56577,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"91D2FA\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1252278118854754307\\\/Ajy8xaYr_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1252278118854754307\\\/Ajy8xaYr_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/1600218031\\\/1573116819\",\"profile_link_color\":\"E81C4F\",\"profile_sidebar_border_color\":\"FFFFFF\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":true,\"quoted_status_id\":1254205620934381569,\"quoted_status_id_str\":\"1254205620934381569\",\"retweet_count\":0,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"und\"},\"retweet_count\":1,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"en\"},\"is_quote_status\":true,\"quoted_status_id\":1254205718858629120,\"quoted_status_id_str\":\"1254205718858629120\",\"retweet_count\":1,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"en\"}],\"search_metadata\":{\"completed_in\":0.122,\"max_id\":1254206511171031041,\"max_id_str\":\"1254206511171031041\",\"next_results\":\"?max_id=1254206511129059328&q=twitter&include_entities=1\",\"query\":\"twitter\",\"refresh_url\":\"?since_id=1254206511171031041&q=twitter&include_entities=1\",\"count\":15,\"since_id\":0,\"since_id_str\":\"0\"}}" - } -}] \ No newline at end of file diff --git a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testGetStatusesMentionsTimeline.json b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testGetStatusesMentionsTimeline.json deleted file mode 100644 index 3e9c96808..000000000 --- a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testGetStatusesMentionsTimeline.json +++ /dev/null @@ -1,49 +0,0 @@ -[{ - "request": { - "method": "GET", - "url": "https:\/\/api.twitter.com\/1.1\/statuses\/mentions_timeline.json", - "headers": { - "Host": "api.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"XBG94YLieQDRW%2FSohCUWyw7cCjs%3D\"", - "Expect": null - } - }, - "response": { - "status": { - "http_version": "2", - "code": "200", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-disposition": "attachment; filename=json.json", - "content-encoding": "gzip", - "content-length": "6295", - "content-type": "application\/json;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:31:49 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:31:49 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_R2D1tzBO5vr\/p0hAkM5zpQ==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:49 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786110971872163; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:49 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "200 OK", - "strict-transport-security": "max-age=631138519", - "x-access-level": "read-write-directmessages", - "x-app-rate-limit-limit": "100000", - "x-app-rate-limit-remaining": "99989", - "x-app-rate-limit-reset": "1587934976", - "x-connection-hash": "fe1724a702fbcac93da2de2b62ba3fe9", - "x-content-type-options": "nosniff", - "x-frame-options": "SAMEORIGIN", - "x-rate-limit-limit": "75", - "x-rate-limit-remaining": "73", - "x-rate-limit-reset": "1587861623", - "x-response-time": "72", - "x-transaction": "0050abfc0028f502", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "0" - }, - "body": "[{\"created_at\":\"Tue Oct 09 09:16:34 +0000 2018\",\"id\":1049589427318743040,\"id_str\":\"1049589427318743040\",\"text\":\"@oauthlibtest wawa\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"oauthlibtest\",\"name\":\"OAuth Library Test\",\"id\":93915746,\"id_str\":\"93915746\",\"indices\":[0,13]}],\"urls\":[]},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web Client\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":93915746,\"in_reply_to_user_id_str\":\"93915746\",\"in_reply_to_screen_name\":\"oauthlibtest\",\"user\":{\"id\":385051447,\"id_str\":\"385051447\",\"name\":\"\\u041d\\u0438\\u043a\\u043e\\u043b\\u0430 \\u041d\\u0438\\u043a\\u043e\\u043b\\u043e\\u0432\\u0441\\u043a\\u0438\",\"screen_name\":\"AmigoNiko\",\"location\":\"Teh internets\",\"description\":\"\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":2,\"friends_count\":3,\"listed_count\":0,\"created_at\":\"Tue Oct 04 19:50:08 +0000 2011\",\"favourites_count\":0,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":10,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/sticky\\\/default_profile_images\\\/default_profile_normal.png\",\"profile_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/sticky\\\/default_profile_images\\\/default_profile_normal.png\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":true,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":0,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"tl\"},{\"created_at\":\"Mon Oct 10 21:11:07 +0000 2016\",\"id\":785588495129739264,\"id_str\":\"785588495129739264\",\"text\":\"@oauthlibtest lol\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"oauthlibtest\",\"name\":\"OAuth Library Test\",\"id\":93915746,\"id_str\":\"93915746\",\"indices\":[0,13]}],\"urls\":[]},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":6242973112,\"in_reply_to_status_id_str\":\"6242973112\",\"in_reply_to_user_id\":93915746,\"in_reply_to_user_id_str\":\"93915746\",\"in_reply_to_screen_name\":\"oauthlibtest\",\"user\":{\"id\":107232049,\"id_str\":\"107232049\",\"name\":\"\\ud83c\\udf10 Mao \\u2192 \\ud83c\\udf0d\",\"screen_name\":\"De_Li_Yang\",\"location\":\"My Twitter account's profile location is the longest ever because it's very cool, ok? I don't really know how I wrote all of this... but I like it :)!\",\"description\":\"\\u00b0+\\u00b0 https:\\\/\\\/t.co\\\/rZwgF3TQar\",\"url\":\"https:\\\/\\\/t.co\\\/d65WAlDNlH\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/d65WAlDNlH\",\"expanded_url\":\"http:\\\/\\\/this.is.probably.the.longest.loopy.fake.website.url.on.a.twitter.profile.of.all.time.because.you.can.possibly.never.never.never.ever.ever.ever.ever.ever.ever.ever.ever.ever.ever.write.something.longer.than.this.link.i.assume.so.i.am.just.gonna.finish.this.is.probably.the.longest.loopy.fake.website.url.on.a.twitter.profile.of.all.time.because.you.can.possibly.never.ever.ever.ever.ever.ever.ever.ever.ever.ever.ever.write.something.longer.than.this.link.i.assume.so.i.am.just.gonna.finish.this.is.probably.the.longest.loopy.fake.website.url.on.a.twitter.profile.of.all.time.because.you.can.possibly.never.ever.ever.ever.ever.ever.ever.ever.ever.ever.ever.write.something.longer.than.this.link.i.assume.so.i.am.just.gonna.finish.this.is.probably.the.longest.loopy.fake.website.url.on.a.twitter.profile.of.all.time.because.you.can.possibly.never.ever.ever.ever.ever.ever.ever.ever.ever.ever.ever.write.something.longer.than.this.link.i.assume.so.i.am.just.gonna.finish.this.is.probably.the.longest.loopy.fake.website.url.on.a.twitter.profile.of.all.time.because.you.can.possibly.never.ever.ever.ever.ever.ever.ever.ever.ever.ever.ever.write.something.longer.than.this.link.i.assume.so.i.am.just.gonna.finish.this.is.probably.the.longest.loopy.fake.website.url.on.a.twitter.profile.of.all.time.because.you.can.possibly.never.ever.ever.ever.ever.ever.ever.ever.ever.ever.ever.write.something.longer.than.this.link.i.assume.so.i.am.just.gonna.finish.this.is.probably.the.longest.loopy.fake.website.url.on.a.twitter.profile.of.all.time.because.you.can.possibly.never.ever.ever.ever.ever.ever.ever.ever.ever.ever.ever.write.something.longer.than.this.link.i.assume.so.i.am.just.gonna.finish.this.is.probably.the.longest.loopy.fake.website.url.on.a.twitter.profile.of.all.time.because.you.can.possibly.never.ever.ever.ever.ever.ever.ever.ever.ever.ever.ever.write.something.longer.than.this.link.i.assume.so.i.am.just.gonna.finish.this.is.probably.the.longest.loopy.fake.website.url.on.a.twitter.profile.of.all.time.because.you.can.possibly.never.ever.ever.ever.ever.ever.ever.ever.ever.ever.ever.write.something.longer.than.this.link.i.assume.so.i.am.just.gonna.finish.this.is.probably.the.longest.loopy.fake.website.url.on.a.twitter.profile.of.all.time.because.you.can.possibly.never.ever.ever.ever.ever.ever.ever.ever.ever.ever.ever.write.something.longer.than.this.link.i.assume.so.i.am.just.gonna.finish.this.is.probably.the.longest.loopy.fake.website.url.on.a.twitter.profile.of.all.time.because.you.can.possibly.never.ever.ever.ever.ever.ever.ever.ever.ever.ever.ever.write.something.longer.than.this.link.i.assume.so.i.am.just.gonna.finish.this.is.probably.the.longest.loopy.fake.website.url.on.a.twitter.profile.of.all.time.because.you.can.possibly.never.ever.ever.ever.ever.ever.ever.ever.ever.ever.ever.write.something.longer.than.this.link.i.assume.so.i.am.just.gonna.finish.this.is.probably.the.longest.loopy.fake.website.url.on.a.twitter.profile.of.all.time.because.you.can.possibly.never.ever.ever.ever.ever.ever.ever.ever.ever.ever.ever.write.something.longer.than.this.link.i.assume.so.i.am.just.gonna.finish.this.is.probably.the.longest.loopy.fake.website.url.on.a.twitter.profile.of.all.time.because.you.can.possibly.never.ever.ever.ever.ever.ever.ever.ever.ever.ever.ever.write.something.longer.than.this.link.i.assume.so.i.am.just.gonna.finish.this.is.probably.the.longest.loopy.fake.website.url.on.a.twitter.profile.of.all.time.because.you.can.possibly.never.ever.ever.ever.ever.ever.ever.ever.ever.ever.ever.write.something.longer.than.this.link.i.assume.so.i.am.just.gonna.finish.this.is.probably.the.longest.loopy.fake.website.url.on.a.twitter.profile.of.all.time.because.you.can.possibly.never.ever.ever.ever.ever.ever.ever.ever.ever.ever.ever.write.something.longer.than.this.link.i.assume.so.i.am.just.gonna.finish.this.is.probably.the.longest.loopy.fake.website.url.on.a.twitter.profile.of.all.time.because.you.can.possibly.never.ever.ever.ever.ever.ever.ever.ever.ever.ever.ever.write.something.longer.than.this.link.i.assume.so.i.am.just.gonna.finish.this.okbye.com\",\"display_url\":\"\\u2026i.am.just.gonna.finish.this.okbye.com\",\"indices\":[0,23]}]},\"description\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/rZwgF3TQar\",\"expanded_url\":\"http:\\\/\\\/paypal.me\\\/DeLi\",\"display_url\":\"paypal.me\\\/DeLi\",\"indices\":[4,27]}]}},\"protected\":false,\"followers_count\":2212,\"friends_count\":21,\"listed_count\":4,\"created_at\":\"Thu Jan 21 22:49:03 +0000 2010\",\"favourites_count\":0,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":385791,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":true,\"is_translation_enabled\":false,\"profile_background_color\":\"000000\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme14\\\/bg.gif\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme14\\\/bg.gif\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/2456970211\\\/xngkt99c24et9k7pco13_normal.gif\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/2456970211\\\/xngkt99c24et9k7pco13_normal.gif\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/107232049\\\/1375640549\",\"profile_link_color\":\"05BFF2\",\"profile_sidebar_border_color\":\"000000\",\"profile_sidebar_fill_color\":\"EFEFEF\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"moderator\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":0,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"und\"},{\"created_at\":\"Mon Jul 29 10:33:20 +0000 2013\",\"id\":361796578241028097,\"id_str\":\"361796578241028097\",\"text\":\"@lakotadlustig @oauthlibtest @twittyapp DM\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"lakotadlustig\",\"name\":\"Lakota Lustig \\ud83c\\udf31\",\"id\":868067922,\"id_str\":\"868067922\",\"indices\":[0,14]},{\"screen_name\":\"oauthlibtest\",\"name\":\"OAuth Library Test\",\"id\":93915746,\"id_str\":\"93915746\",\"indices\":[15,28]},{\"screen_name\":\"twittyapp\",\"name\":\"Twitty\",\"id\":1465708922,\"id_str\":\"1465708922\",\"indices\":[29,39]}],\"urls\":[]},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web Client\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":361795965159608321,\"in_reply_to_status_id_str\":\"361795965159608321\",\"in_reply_to_user_id\":868067922,\"in_reply_to_user_id_str\":\"868067922\",\"in_reply_to_screen_name\":\"lakotadlustig\",\"user\":{\"id\":421392342,\"id_str\":\"421392342\",\"name\":\"Evert De Spiegeleer\",\"screen_name\":\"eds1999\",\"location\":\"Belgium\",\"description\":\"20. European. Engineer. Developer. Here for everything space-related.\",\"url\":\"https:\\\/\\\/t.co\\\/m19HQXRy3P\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/m19HQXRy3P\",\"expanded_url\":\"http:\\\/\\\/github.com\\\/evertdespiegeleer\",\"display_url\":\"github.com\\\/evertdespiegel\\u2026\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":433,\"friends_count\":1175,\"listed_count\":14,\"created_at\":\"Fri Nov 25 21:58:06 +0000 2011\",\"favourites_count\":1765,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":5209,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"FFFFFF\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme14\\\/bg.gif\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme14\\\/bg.gif\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1226456092378529793\\\/eoJ-xOeW_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1226456092378529793\\\/eoJ-xOeW_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/421392342\\\/1424992018\",\"profile_link_color\":\"009999\",\"profile_sidebar_border_color\":\"000000\",\"profile_sidebar_fill_color\":\"EFEFEF\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":0,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"und\"},{\"created_at\":\"Mon Apr 29 07:12:03 +0000 2013\",\"id\":328768625957814272,\"id_str\":\"328768625957814272\",\"text\":\"@oauthlibtest 1\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"oauthlibtest\",\"name\":\"OAuth Library Test\",\"id\":93915746,\"id_str\":\"93915746\",\"indices\":[0,13]}],\"urls\":[]},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web Client\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":93915746,\"in_reply_to_user_id_str\":\"93915746\",\"in_reply_to_screen_name\":\"oauthlibtest\",\"user\":{\"id\":1331868230,\"id_str\":\"1331868230\",\"name\":\"Den TSVETOK\",\"screen_name\":\"denTsvetok\",\"location\":\"Teh internets\",\"description\":\"\",\"url\":\"http:\\\/\\\/t.co\\\/jvqJ6VIgn7\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"http:\\\/\\\/t.co\\\/jvqJ6VIgn7\",\"expanded_url\":\"http:\\\/\\\/123.ru\",\"display_url\":\"123.ru\",\"indices\":[0,22]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":4,\"friends_count\":419,\"listed_count\":0,\"created_at\":\"Sat Apr 06 15:34:15 +0000 2013\",\"favourites_count\":1,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":27,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"FFFFFF\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/3576594159\\\/63b3f9afe2d0643356ee3951c66f11a8_normal.jpeg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/3576594159\\\/63b3f9afe2d0643356ee3951c66f11a8_normal.jpeg\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":0,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"und\"},{\"created_at\":\"Mon Apr 01 11:10:53 +0000 2013\",\"id\":318681871691157504,\"id_str\":\"318681871691157504\",\"text\":\"@oauthlibtest test\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"oauthlibtest\",\"name\":\"OAuth Library Test\",\"id\":93915746,\"id_str\":\"93915746\",\"indices\":[0,13]}],\"urls\":[]},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web Client\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":6242973112,\"in_reply_to_status_id_str\":\"6242973112\",\"in_reply_to_user_id\":93915746,\"in_reply_to_user_id_str\":\"93915746\",\"in_reply_to_screen_name\":\"oauthlibtest\",\"user\":{\"id\":532290601,\"id_str\":\"532290601\",\"name\":\"TestVakoms\",\"screen_name\":\"TestVakoms\",\"location\":\"\",\"description\":\"\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":1,\"friends_count\":5,\"listed_count\":0,\"created_at\":\"Wed Mar 21 14:56:15 +0000 2012\",\"favourites_count\":20,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":560,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/3662702134\\\/f87a2bcff8ec621239ef03662cae9a0a_normal.jpeg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/3662702134\\\/f87a2bcff8ec621239ef03662cae9a0a_normal.jpeg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/532290601\\\/1365162944\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":0,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"en\"},{\"created_at\":\"Sun Sep 09 06:11:54 +0000 2012\",\"id\":244679505170550785,\"id_str\":\"244679505170550785\",\"text\":\"@oauthlibtest - -\\\"\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"oauthlibtest\",\"name\":\"OAuth Library Test\",\"id\":93915746,\"id_str\":\"93915746\",\"indices\":[0,13]}],\"urls\":[]},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":6242973112,\"in_reply_to_status_id_str\":\"6242973112\",\"in_reply_to_user_id\":93915746,\"in_reply_to_user_id_str\":\"93915746\",\"in_reply_to_screen_name\":\"oauthlibtest\",\"user\":{\"id\":14567940,\"id_str\":\"14567940\",\"name\":\"Ming Sangkeettrakarn\",\"screen_name\":\"javakung\",\"location\":\"\",\"description\":\"chatbot,question answering,\\nsocial web technology, researcher,human-computer interaction,data\\\/opinion mining,semantic,ontology, animation,investor\",\"url\":\"http:\\\/\\\/t.co\\\/EfcUdKPzIb\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"http:\\\/\\\/t.co\\\/EfcUdKPzIb\",\"expanded_url\":\"http:\\\/\\\/facebook.com\\\/imconan\",\"display_url\":\"facebook.com\\\/imconan\",\"indices\":[0,22]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":367,\"friends_count\":338,\"listed_count\":23,\"created_at\":\"Mon Apr 28 11:15:13 +0000 2008\",\"favourites_count\":93,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":22657,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C6E2EE\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme2\\\/bg.gif\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme2\\\/bg.gif\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/378800000067935959\\\/8097c4b4c3ba876bf839ee4ee11ba9ea_normal.jpeg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/378800000067935959\\\/8097c4b4c3ba876bf839ee4ee11ba9ea_normal.jpeg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/14567940\\\/1372598045\",\"profile_link_color\":\"1F98C7\",\"profile_sidebar_border_color\":\"000000\",\"profile_sidebar_fill_color\":\"DAECF4\",\"profile_text_color\":\"663B12\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":0,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"und\"},{\"created_at\":\"Sun Jul 15 08:35:03 +0000 2012\",\"id\":224421809980833794,\"id_str\":\"224421809980833794\",\"text\":\"@oauthlibtest lol\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"oauthlibtest\",\"name\":\"OAuth Library Test\",\"id\":93915746,\"id_str\":\"93915746\",\"indices\":[0,13]}],\"urls\":[]},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/android\\\" rel=\\\"nofollow\\\"\\u003eTwitter for Android\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":6242973112,\"in_reply_to_status_id_str\":\"6242973112\",\"in_reply_to_user_id\":93915746,\"in_reply_to_user_id_str\":\"93915746\",\"in_reply_to_screen_name\":\"oauthlibtest\",\"user\":{\"id\":127961215,\"id_str\":\"127961215\",\"name\":\"DEZCO\",\"screen_name\":\"iDezco\",\"location\":\"En una Lemniscata de Bernoulli\",\"description\":\"#Caster en @ULeagueMX | @Skill3Sports | Contacto: dezco23@gmail.com | Los h\\u00e9roes se desvanecen con el tiempo pero las leyendas nunca mueren.\",\"url\":\"https:\\\/\\\/t.co\\\/U6DDuMTtgy\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/U6DDuMTtgy\",\"expanded_url\":\"https:\\\/\\\/www.youtube.com\\\/user\\\/iDezco\",\"display_url\":\"youtube.com\\\/user\\\/iDezco\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":5492,\"friends_count\":565,\"listed_count\":22,\"created_at\":\"Tue Mar 30 18:37:12 +0000 2010\",\"favourites_count\":892,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":11765,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"131516\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme14\\\/bg.gif\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme14\\\/bg.gif\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/843228055237607426\\\/cBs7UmZX_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/843228055237607426\\\/cBs7UmZX_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/127961215\\\/1489875781\",\"profile_link_color\":\"009999\",\"profile_sidebar_border_color\":\"FFFFFF\",\"profile_sidebar_fill_color\":\"EFEFEF\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":0,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"und\"},{\"created_at\":\"Tue Apr 03 21:15:40 +0000 2012\",\"id\":187287275426689024,\"id_str\":\"187287275426689024\",\"text\":\"@oauthlibtest YES!\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"oauthlibtest\",\"name\":\"OAuth Library Test\",\"id\":93915746,\"id_str\":\"93915746\",\"indices\":[0,13]}],\"urls\":[]},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web Client\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":6242973112,\"in_reply_to_status_id_str\":\"6242973112\",\"in_reply_to_user_id\":93915746,\"in_reply_to_user_id_str\":\"93915746\",\"in_reply_to_screen_name\":\"oauthlibtest\",\"user\":{\"id\":140710184,\"id_str\":\"140710184\",\"name\":\"Roberto Soler\",\"screen_name\":\"robertolsoler\",\"location\":\"Barceloneta, PR\",\"description\":\"Cantautor, Singer-Songwriter, Music Producer\",\"url\":\"http:\\\/\\\/t.co\\\/CNhfpdtLFK\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"http:\\\/\\\/t.co\\\/CNhfpdtLFK\",\"expanded_url\":\"http:\\\/\\\/www.facebook.com\\\/roberto.luis.soler\",\"display_url\":\"facebook.com\\\/roberto.luis.s\\u2026\",\"indices\":[0,22]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":106,\"friends_count\":265,\"listed_count\":3,\"created_at\":\"Thu May 06 06:09:49 +0000 2010\",\"favourites_count\":67,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":1105,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"131516\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme14\\\/bg.gif\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme14\\\/bg.gif\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/630823843922219008\\\/8JxXrkMm_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/630823843922219008\\\/8JxXrkMm_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/140710184\\\/1439235059\",\"profile_link_color\":\"009999\",\"profile_sidebar_border_color\":\"EEEEEE\",\"profile_sidebar_fill_color\":\"EFEFEF\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":0,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"und\"},{\"created_at\":\"Tue Apr 03 20:57:44 +0000 2012\",\"id\":187282759394410498,\"id_str\":\"187282759394410498\",\"text\":\"@_IODreams @oauthlibtest hehe\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"oauthlibtest\",\"name\":\"OAuth Library Test\",\"id\":93915746,\"id_str\":\"93915746\",\"indices\":[11,24]}],\"urls\":[]},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web Client\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":187278576037535744,\"in_reply_to_status_id_str\":\"187278576037535744\",\"in_reply_to_user_id\":140528703,\"in_reply_to_user_id_str\":\"140528703\",\"in_reply_to_screen_name\":\"lightsonjoy\",\"user\":{\"id\":140710184,\"id_str\":\"140710184\",\"name\":\"Roberto Soler\",\"screen_name\":\"robertolsoler\",\"location\":\"Barceloneta, PR\",\"description\":\"Cantautor, Singer-Songwriter, Music Producer\",\"url\":\"http:\\\/\\\/t.co\\\/CNhfpdtLFK\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"http:\\\/\\\/t.co\\\/CNhfpdtLFK\",\"expanded_url\":\"http:\\\/\\\/www.facebook.com\\\/roberto.luis.soler\",\"display_url\":\"facebook.com\\\/roberto.luis.s\\u2026\",\"indices\":[0,22]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":106,\"friends_count\":265,\"listed_count\":3,\"created_at\":\"Thu May 06 06:09:49 +0000 2010\",\"favourites_count\":67,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":1105,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"131516\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme14\\\/bg.gif\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme14\\\/bg.gif\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/630823843922219008\\\/8JxXrkMm_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/630823843922219008\\\/8JxXrkMm_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/140710184\\\/1439235059\",\"profile_link_color\":\"009999\",\"profile_sidebar_border_color\":\"EEEEEE\",\"profile_sidebar_fill_color\":\"EFEFEF\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":0,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"tl\"},{\"created_at\":\"Tue Apr 03 20:41:06 +0000 2012\",\"id\":187278576037535744,\"id_str\":\"187278576037535744\",\"text\":\"@oauthlibtest @robertolsoler ya estoy postiando y retweeting por el api :)\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"oauthlibtest\",\"name\":\"OAuth Library Test\",\"id\":93915746,\"id_str\":\"93915746\",\"indices\":[0,13]},{\"screen_name\":\"robertolsoler\",\"name\":\"Roberto Soler\",\"id\":140710184,\"id_str\":\"140710184\",\"indices\":[14,28]}],\"urls\":[]},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web Client\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":6242973112,\"in_reply_to_status_id_str\":\"6242973112\",\"in_reply_to_user_id\":93915746,\"in_reply_to_user_id_str\":\"93915746\",\"in_reply_to_screen_name\":\"oauthlibtest\",\"user\":{\"id\":140528703,\"id_str\":\"140528703\",\"name\":\"Eduardo Joy\",\"screen_name\":\"lightsonjoy\",\"location\":\"Puerto Rico\",\"description\":\"Family adds Fuel.\\u26fd\\ufe0f \\ud83d\\udd25 Convirtiendo a @1justonce en el lider \\ud83c\\udf0e\\ud83e\\udde2. Documentando mi camino. \\ud83d\\udc47\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":618,\"friends_count\":77,\"listed_count\":6,\"created_at\":\"Wed May 05 18:41:52 +0000 2010\",\"favourites_count\":6,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":3242,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"050505\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme9\\\/bg.gif\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme9\\\/bg.gif\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/989203086487924736\\\/5oRBhZrF_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/989203086487924736\\\/5oRBhZrF_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/140528703\\\/1524688600\",\"profile_link_color\":\"2FC2EF\",\"profile_sidebar_border_color\":\"FFFFFF\",\"profile_sidebar_fill_color\":\"252429\",\"profile_text_color\":\"666666\",\"profile_use_background_image\":false,\"has_extended_profile\":false,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":0,\"favorite_count\":1,\"favorited\":false,\"retweeted\":false,\"lang\":\"es\"},{\"created_at\":\"Mon Jan 30 17:41:20 +0000 2012\",\"id\":164040511240404993,\"id_str\":\"164040511240404993\",\"text\":\"@oauthlibtest hey\\u2755\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"oauthlibtest\",\"name\":\"OAuth Library Test\",\"id\":93915746,\"id_str\":\"93915746\",\"indices\":[0,13]}],\"urls\":[]},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":93915746,\"in_reply_to_user_id_str\":\"93915746\",\"in_reply_to_screen_name\":\"oauthlibtest\",\"user\":{\"id\":17953020,\"id_str\":\"17953020\",\"name\":\"Chris\\ud83c\\udf10\",\"screen_name\":\"ChrisTiv7_\",\"location\":\"Canada\",\"description\":\"You got to sacrifice the small useless things to get the best things\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":666,\"friends_count\":970,\"listed_count\":7,\"created_at\":\"Mon Dec 08 01:56:29 +0000 2008\",\"favourites_count\":1604,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":38608,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"1A1B1F\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme9\\\/bg.gif\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme9\\\/bg.gif\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1183222943951790080\\\/aiMiOqUs_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1183222943951790080\\\/aiMiOqUs_normal.jpg\",\"profile_link_color\":\"000000\",\"profile_sidebar_border_color\":\"181A1E\",\"profile_sidebar_fill_color\":\"252429\",\"profile_text_color\":\"666666\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":0,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"und\"},{\"created_at\":\"Tue Oct 11 07:08:39 +0000 2011\",\"id\":123656239707197440,\"id_str\":\"123656239707197440\",\"text\":\"@oauthlibtest what is this?\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"oauthlibtest\",\"name\":\"OAuth Library Test\",\"id\":93915746,\"id_str\":\"93915746\",\"indices\":[0,13]}],\"urls\":[]},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web Client\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":6242973112,\"in_reply_to_status_id_str\":\"6242973112\",\"in_reply_to_user_id\":93915746,\"in_reply_to_user_id_str\":\"93915746\",\"in_reply_to_screen_name\":\"oauthlibtest\",\"user\":{\"id\":386959632,\"id_str\":\"386959632\",\"name\":\"Abhinav Pathak\",\"screen_name\":\"abhinavoctal\",\"location\":\"Jaipur\",\"description\":\"\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":1,\"friends_count\":5,\"listed_count\":0,\"created_at\":\"Sat Oct 08 06:44:15 +0000 2011\",\"favourites_count\":0,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":43,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"FFFFFF\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1584709272\\\/012_Wharton_1024x768_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1584709272\\\/012_Wharton_1024x768_normal.jpg\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":0,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"en\"},{\"created_at\":\"Fri Aug 12 05:46:40 +0000 2011\",\"id\":101892336094691329,\"id_str\":\"101892336094691329\",\"text\":\"test 02~~RT @oauthlibtest: Test!\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"oauthlibtest\",\"name\":\"OAuth Library Test\",\"id\":93915746,\"id_str\":\"93915746\",\"indices\":[12,25]}],\"urls\":[]},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/seesmic.com\\\/\\\" rel=\\\"nofollow\\\"\\u003eSeesmic\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":168561998,\"id_str\":\"168561998\",\"name\":\"\\ubd09\\ucc3d\\ub6ab\\uae30\",\"screen_name\":\"younla91\",\"location\":\"seoul\",\"description\":\"Job: ITA\\\/EA,IT Governing, web Developing Planner. Bio: lonesome single\\\/ Dreamer\\\/World of Warcraft\\\/\\uc2ec\\uc2ec\\ud558\\ub2e4.\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":225,\"friends_count\":254,\"listed_count\":4,\"created_at\":\"Tue Jul 20 06:56:33 +0000 2010\",\"favourites_count\":19,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":2442,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"B2DFDA\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme13\\\/bg.gif\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme13\\\/bg.gif\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/711560733566218241\\\/M5T2XsoE_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/711560733566218241\\\/M5T2XsoE_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/168561998\\\/1458484272\",\"profile_link_color\":\"93A644\",\"profile_sidebar_border_color\":\"EEEEEE\",\"profile_sidebar_fill_color\":\"FFFFFF\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":0,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"et\"},{\"created_at\":\"Fri Jun 03 02:29:59 +0000 2011\",\"id\":76475688735092736,\"id_str\":\"76475688735092736\",\"text\":\"@oauthlibtest Hello ! I'm Dong\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"oauthlibtest\",\"name\":\"OAuth Library Test\",\"id\":93915746,\"id_str\":\"93915746\",\"indices\":[0,13]}],\"urls\":[]},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web Client\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":6242973112,\"in_reply_to_status_id_str\":\"6242973112\",\"in_reply_to_user_id\":93915746,\"in_reply_to_user_id_str\":\"93915746\",\"in_reply_to_screen_name\":\"oauthlibtest\",\"user\":{\"id\":267474806,\"id_str\":\"267474806\",\"name\":\"Beautiful Life\",\"screen_name\":\"dongta712\",\"location\":\"Ha Noi, Viet Nam\",\"description\":\"think different, think smart , always intelligent solutions , php expert\",\"url\":\"https:\\\/\\\/t.co\\\/PEIWG6SgQY\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/PEIWG6SgQY\",\"expanded_url\":\"https:\\\/\\\/www.facebook.com\\\/BeautifulLifeImage\",\"display_url\":\"facebook.com\\\/BeautifulLifeI\\u2026\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":80,\"friends_count\":56,\"listed_count\":0,\"created_at\":\"Thu Mar 17 00:50:28 +0000 2011\",\"favourites_count\":0,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":15136,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"ACDED6\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme18\\\/bg.gif\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme18\\\/bg.gif\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/750356464275890177\\\/wmVESyfU_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/750356464275890177\\\/wmVESyfU_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/267474806\\\/1467734084\",\"profile_link_color\":\"038543\",\"profile_sidebar_border_color\":\"EEEEEE\",\"profile_sidebar_fill_color\":\"F6F6F6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":0,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"en\"},{\"created_at\":\"Tue May 03 11:45:07 +0000 2011\",\"id\":65381365901828096,\"id_str\":\"65381365901828096\",\"text\":\"@oauthlibtest \\ub098\\ub3c4test..\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"oauthlibtest\",\"name\":\"OAuth Library Test\",\"id\":93915746,\"id_str\":\"93915746\",\"indices\":[0,13]}],\"urls\":[]},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/android\\\" rel=\\\"nofollow\\\"\\u003eTwitter for Android\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":6242973112,\"in_reply_to_status_id_str\":\"6242973112\",\"in_reply_to_user_id\":93915746,\"in_reply_to_user_id_str\":\"93915746\",\"in_reply_to_screen_name\":\"oauthlibtest\",\"user\":{\"id\":249113612,\"id_str\":\"249113612\",\"name\":\"GgongNa\",\"screen_name\":\"ggonna04\",\"location\":\"\\uc9c0\\uad6c.\\ud55c\\uad6d.\\uadf8\\uc5b4\\ub518\\uac00...\",\"description\":\"\\ud56d\\uc0c1..\\ub204\\uad70\\uac00\\uc5d0\\uac8c\\ub530\\ub73b\\ubbf8\\uc18c\\ub97c\\uc9c0\\uc744\\uc218\\uc788\\ub294...\\ub9d8\\ub113\\uc740\\uc774\",\"url\":\"http:\\\/\\\/t.co\\\/sI6dCHB2gr\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"http:\\\/\\\/t.co\\\/sI6dCHB2gr\",\"expanded_url\":\"http:\\\/\\\/koreantweeters.com\\\/ggonna04\",\"display_url\":\"koreantweeters.com\\\/ggonna04\",\"indices\":[0,22]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":16,\"friends_count\":19,\"listed_count\":1,\"created_at\":\"Tue Feb 08 11:48:27 +0000 2011\",\"favourites_count\":2,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":227,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1384141054\\\/VfKWV12o_normal\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1384141054\\\/VfKWV12o_normal\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":0,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"ko\"},{\"created_at\":\"Tue Mar 22 05:24:01 +0000 2011\",\"id\":50065170642370560,\"id_str\":\"50065170642370560\",\"text\":\"@oauthlibtest latest\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"oauthlibtest\",\"name\":\"OAuth Library Test\",\"id\":93915746,\"id_str\":\"93915746\",\"indices\":[0,13]}],\"urls\":[]},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web Client\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":6242973112,\"in_reply_to_status_id_str\":\"6242973112\",\"in_reply_to_user_id\":93915746,\"in_reply_to_user_id_str\":\"93915746\",\"in_reply_to_screen_name\":\"oauthlibtest\",\"user\":{\"id\":267737297,\"id_str\":\"267737297\",\"name\":\"Developer Artworld\",\"screen_name\":\"dev786art\",\"location\":\"Teh internets\",\"description\":\"\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":2,\"friends_count\":1,\"listed_count\":0,\"created_at\":\"Thu Mar 17 13:05:59 +0000 2011\",\"favourites_count\":0,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":48,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"FFFFFF\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/sticky\\\/default_profile_images\\\/default_profile_normal.png\",\"profile_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/sticky\\\/default_profile_images\\\/default_profile_normal.png\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":false,\"default_profile_image\":true,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":0,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"en\"},{\"created_at\":\"Tue Mar 22 05:23:49 +0000 2011\",\"id\":50065118918213632,\"id_str\":\"50065118918213632\",\"text\":\"@oauthlibtest : this is new retweet\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"oauthlibtest\",\"name\":\"OAuth Library Test\",\"id\":93915746,\"id_str\":\"93915746\",\"indices\":[0,13]}],\"urls\":[]},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web Client\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":6242973112,\"in_reply_to_status_id_str\":\"6242973112\",\"in_reply_to_user_id\":93915746,\"in_reply_to_user_id_str\":\"93915746\",\"in_reply_to_screen_name\":\"oauthlibtest\",\"user\":{\"id\":267737297,\"id_str\":\"267737297\",\"name\":\"Developer Artworld\",\"screen_name\":\"dev786art\",\"location\":\"Teh internets\",\"description\":\"\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":2,\"friends_count\":1,\"listed_count\":0,\"created_at\":\"Thu Mar 17 13:05:59 +0000 2011\",\"favourites_count\":0,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":48,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"FFFFFF\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/sticky\\\/default_profile_images\\\/default_profile_normal.png\",\"profile_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/sticky\\\/default_profile_images\\\/default_profile_normal.png\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":false,\"default_profile_image\":true,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":0,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"en\"},{\"created_at\":\"Sun Mar 20 15:24:28 +0000 2011\",\"id\":49491502925225985,\"id_str\":\"49491502925225985\",\"text\":\"Now tracking stats for @oauthlibtest at http:\\\/\\\/twittercounter.com\\\/oauthlibtest?t=t (52 followers)\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"oauthlibtest\",\"name\":\"OAuth Library Test\",\"id\":93915746,\"id_str\":\"93915746\",\"indices\":[23,36]}],\"urls\":[]},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/twittercounter.com\\\" rel=\\\"nofollow\\\"\\u003eThe Counter\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":39328213,\"id_str\":\"39328213\",\"name\":\"OurStatus\",\"screen_name\":\"OurStatus\",\"location\":\"TwitterWorld\",\"description\":\"We welcome EVERY new member here so following us might be annoying for you. :-)\",\"url\":\"http:\\\/\\\/t.co\\\/MJn4MTUuC0\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"http:\\\/\\\/t.co\\\/MJn4MTUuC0\",\"expanded_url\":\"http:\\\/\\\/twittercounter.com\\\/\",\"display_url\":\"twittercounter.com\",\"indices\":[0,22]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":2481,\"friends_count\":8,\"listed_count\":51,\"created_at\":\"Mon May 11 20:03:28 +0000 2009\",\"favourites_count\":0,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":1190192,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"EDECE9\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1087614264\\\/twc_logo_normal.png\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1087614264\\\/twc_logo_normal.png\",\"profile_link_color\":\"088253\",\"profile_sidebar_border_color\":\"D3D2CF\",\"profile_sidebar_fill_color\":\"E3E2DE\",\"profile_text_color\":\"634047\",\"profile_use_background_image\":false,\"has_extended_profile\":false,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":0,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"en\"},{\"created_at\":\"Tue Mar 08 16:54:24 +0000 2011\",\"id\":45165480461352960,\"id_str\":\"45165480461352960\",\"text\":\"@oauthlibtest http:\\\/\\\/www.facebook.com\\\/event.php?eid=147409505321037 invita i tuoi amici\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"oauthlibtest\",\"name\":\"OAuth Library Test\",\"id\":93915746,\"id_str\":\"93915746\",\"indices\":[0,13]}],\"urls\":[]},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web Client\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":6242973112,\"in_reply_to_status_id_str\":\"6242973112\",\"in_reply_to_user_id\":93915746,\"in_reply_to_user_id_str\":\"93915746\",\"in_reply_to_screen_name\":\"oauthlibtest\",\"user\":{\"id\":9885752,\"id_str\":\"9885752\",\"name\":\"tor100\",\"screen_name\":\"tor100\",\"location\":\"italia\",\"description\":\"Cot vade a fe la 'n mes, piciu?\\r\\niononsonodisinistramaCOMUNISTA\",\"url\":\"http:\\\/\\\/t.co\\\/BXBfxnpxqN\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"http:\\\/\\\/t.co\\\/BXBfxnpxqN\",\"expanded_url\":\"http:\\\/\\\/tor100.wordpress.com\\\/\",\"display_url\":\"tor100.wordpress.com\",\"indices\":[0,22]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":241,\"friends_count\":363,\"listed_count\":12,\"created_at\":\"Fri Nov 02 14:16:38 +0000 2007\",\"favourites_count\":20,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":13788,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"9AE4E8\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1224654764\\\/pat_normal.gif\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1224654764\\\/pat_normal.gif\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/9885752\\\/1398770471\",\"profile_link_color\":\"0000FF\",\"profile_sidebar_border_color\":\"FFFFFF\",\"profile_sidebar_fill_color\":\"E0FF92\",\"profile_text_color\":\"000000\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":0,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"it\"},{\"created_at\":\"Tue Mar 08 16:53:35 +0000 2011\",\"id\":45165273631817728,\"id_str\":\"45165273631817728\",\"text\":\"@oauthlibtest works\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"oauthlibtest\",\"name\":\"OAuth Library Test\",\"id\":93915746,\"id_str\":\"93915746\",\"indices\":[0,13]}],\"urls\":[]},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web Client\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":6242973112,\"in_reply_to_status_id_str\":\"6242973112\",\"in_reply_to_user_id\":93915746,\"in_reply_to_user_id_str\":\"93915746\",\"in_reply_to_screen_name\":\"oauthlibtest\",\"user\":{\"id\":52199567,\"id_str\":\"52199567\",\"name\":\"miche fax\",\"screen_name\":\"MicheFax\",\"location\":\"Milano-Verona\",\"description\":\"Trying to improve the good energy inside and outside of me\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":168,\"friends_count\":329,\"listed_count\":4,\"created_at\":\"Mon Jun 29 21:42:18 +0000 2009\",\"favourites_count\":101,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":2619,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1291516151\\\/WeeMee_21507e3d6969f72f670be2f6f4645e9e_for_mi.fac_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1291516151\\\/WeeMee_21507e3d6969f72f670be2f6f4645e9e_for_mi.fac_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/52199567\\\/1453128465\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":0,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"en\"}]" - } -}] \ No newline at end of file diff --git a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testLastResult.json b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testLastResult.json deleted file mode 100644 index 6ca9d38b9..000000000 --- a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testLastResult.json +++ /dev/null @@ -1,46 +0,0 @@ -[{ - "request": { - "method": "GET", - "url": "https:\/\/api.twitter.com\/1.1\/search\/tweets.json?q=twitter", - "headers": { - "Host": "api.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"qWYQHV5qw8biySQjoR59V9%2BDvOQ%3D\"", - "Expect": null - } - }, - "response": { - "status": { - "http_version": "2", - "code": "200", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-disposition": "attachment; filename=json.json", - "content-encoding": "gzip", - "content-length": "12973", - "content-type": "application\/json;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:32:24 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:32:24 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_j\/D8MbYgZO9NrZX0j4Doog==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:24 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786114467858900; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:24 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "200 OK", - "strict-transport-security": "max-age=631138519", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "7dc369267b3c7dbeb719dcad15017787", - "x-content-type-options": "nosniff", - "x-frame-options": "SAMEORIGIN", - "x-rate-limit-limit": "180", - "x-rate-limit-remaining": "174", - "x-rate-limit-reset": "1587861623", - "x-response-time": "190", - "x-transaction": "00f1001400e3fb3b", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "0" - }, - "body": "{\"statuses\":[{\"created_at\":\"Sun Apr 26 00:32:23 +0000 2020\",\"id\":1254206657657257984,\"id_str\":\"1254206657657257984\",\"text\":\"RT @TheUntamedLati2: Ya perd\\u00ed la cuenta de cuantas veces he visto esa escena, ya se que va a pasar despu\\u00e9s..... y a\\u00fan as\\u00ed todav\\u00eda lloro con\\u2026\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"TheUntamedLati2\",\"name\":\"The Untamed Latinoam\\u00e9rica\",\"id\":1234358495631364096,\"id_str\":\"1234358495631364096\",\"indices\":[3,19]}],\"urls\":[]},\"metadata\":{\"iso_language_code\":\"es\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/android\\\" rel=\\\"nofollow\\\"\\u003eTwitter for Android\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":950450150211768320,\"id_str\":\"950450150211768320\",\"name\":\"\\u22b1\\u22b9\\u2133\\u2134\\ud835\\udcb8\\ud835\\udcbd\\ud835\\udcbe \\ud835\\udcc8\\ud835\\udcca\\ud835\\udcb8\\ud835\\udcc7\\ud835\\udcee\\u00b0\\u22b9\\u22b0\",\"screen_name\":\"Mochi_pxxrk\",\"location\":\"\",\"description\":\"\\u2022\\u2022 .\\u00b8\\u00b8.\\u2022\\u00b4\\u00af`\\u2022.\\u2022N\\u1d07\\u1d04\\u1d07s\\u026a\\u1d1b\\u1d0f \\u01eb\\u1d1c\\u1d07 \\u1d0d\\u1d07 \\u0274\\u1d07\\u1d04\\u1d07s\\u026a\\u1d1b\\u1d07s `\\u2022.\\u00b8\\u00b8.\\u2022\\u00b4\\u00b4\\u00af`\\u2022\\u2022\\n\\u06e9\\u25aa\\ufe0e\\ud835\\udc40\\ud835\\udc5c \\ud835\\udc51\\ud835\\udc4e\\ud835\\udc5c \\ud835\\udc67\\ud835\\udc62 \\ud835\\udc60\\u210e\\ud835\\udc56 \\ud835\\udc5a\\ud835\\udc52 \\ud835\\udc51\\ud835\\udc52\\ud835\\udc57\\u00f3 \\ud835\\udc60\\ud835\\udc52\\ud835\\udc5b\\ud835\\udc60\\ud835\\udc56\\ud835\\udc4f\\ud835\\udc59\\ud835\\udc52\\u25aa\\ufe0e\\u06e9\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":68,\"friends_count\":112,\"listed_count\":0,\"created_at\":\"Mon Jan 08 19:32:29 +0000 2018\",\"favourites_count\":32407,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":4806,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1243366985817370626\\\/exDXU85Q_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1243366985817370626\\\/exDXU85Q_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/950450150211768320\\\/1585967564\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Sat Apr 25 20:53:48 +0000 2020\",\"id\":1254151647485472770,\"id_str\":\"1254151647485472770\",\"text\":\"Ya perd\\u00ed la cuenta de cuantas veces he visto esa escena, ya se que va a pasar despu\\u00e9s..... y a\\u00fan as\\u00ed todav\\u00eda lloro\\u2026 https:\\\/\\\/t.co\\\/ypYYG5Gmgw\",\"truncated\":true,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/ypYYG5Gmgw\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/i\\\/web\\\/status\\\/1254151647485472770\",\"display_url\":\"twitter.com\\\/i\\\/web\\\/status\\\/1\\u2026\",\"indices\":[116,139]}]},\"metadata\":{\"iso_language_code\":\"es\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/android\\\" rel=\\\"nofollow\\\"\\u003eTwitter for Android\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":1234358495631364096,\"id_str\":\"1234358495631364096\",\"name\":\"The Untamed Latinoam\\u00e9rica\",\"screen_name\":\"TheUntamedLati2\",\"location\":\"\",\"description\":\"\\ud83d\\udc95Espacio dedicado a las fans de The Untamed\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":1263,\"friends_count\":6,\"listed_count\":0,\"created_at\":\"Mon Mar 02 06:03:15 +0000 2020\",\"favourites_count\":1353,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":690,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1253900779892740106\\\/C-F7iXpT_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1253900779892740106\\\/C-F7iXpT_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/1234358495631364096\\\/1583129151\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":11,\"favorite_count\":54,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"es\"},\"is_quote_status\":false,\"retweet_count\":11,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"es\"},{\"created_at\":\"Sun Apr 26 00:32:23 +0000 2020\",\"id\":1254206657497911297,\"id_str\":\"1254206657497911297\",\"text\":\"RT @muieresnanet: https:\\\/\\\/t.co\\\/Zi7xHqWCDQ\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"muieresnanet\",\"name\":\"mulheres que passaram vergonha\",\"id\":1218213021010616320,\"id_str\":\"1218213021010616320\",\"indices\":[3,16]}],\"urls\":[],\"media\":[{\"id\":1253829607280779264,\"id_str\":\"1253829607280779264\",\"indices\":[18,41],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWZ_Yn7WoAAPtv8.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWZ_Yn7WoAAPtv8.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/Zi7xHqWCDQ\",\"display_url\":\"pic.twitter.com\\\/Zi7xHqWCDQ\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/muieresnanet\\\/status\\\/1253829613031165961\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":653,\"h\":680,\"resize\":\"fit\"},\"large\":{\"w\":1080,\"h\":1125,\"resize\":\"fit\"},\"medium\":{\"w\":1080,\"h\":1125,\"resize\":\"fit\"}},\"source_status_id\":1253829613031165961,\"source_status_id_str\":\"1253829613031165961\",\"source_user_id\":1218213021010616320,\"source_user_id_str\":\"1218213021010616320\"}]},\"extended_entities\":{\"media\":[{\"id\":1253829607280779264,\"id_str\":\"1253829607280779264\",\"indices\":[18,41],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWZ_Yn7WoAAPtv8.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWZ_Yn7WoAAPtv8.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/Zi7xHqWCDQ\",\"display_url\":\"pic.twitter.com\\\/Zi7xHqWCDQ\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/muieresnanet\\\/status\\\/1253829613031165961\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":653,\"h\":680,\"resize\":\"fit\"},\"large\":{\"w\":1080,\"h\":1125,\"resize\":\"fit\"},\"medium\":{\"w\":1080,\"h\":1125,\"resize\":\"fit\"}},\"source_status_id\":1253829613031165961,\"source_status_id_str\":\"1253829613031165961\",\"source_user_id\":1218213021010616320,\"source_user_id_str\":\"1218213021010616320\"},{\"id\":1253829607268155395,\"id_str\":\"1253829607268155395\",\"indices\":[18,41],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWZ_Yn4WAAMDUWM.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWZ_Yn4WAAMDUWM.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/Zi7xHqWCDQ\",\"display_url\":\"pic.twitter.com\\\/Zi7xHqWCDQ\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/muieresnanet\\\/status\\\/1253829613031165961\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"medium\":{\"w\":696,\"h\":1200,\"resize\":\"fit\"},\"large\":{\"w\":742,\"h\":1280,\"resize\":\"fit\"},\"small\":{\"w\":394,\"h\":680,\"resize\":\"fit\"}},\"source_status_id\":1253829613031165961,\"source_status_id_str\":\"1253829613031165961\",\"source_user_id\":1218213021010616320,\"source_user_id_str\":\"1218213021010616320\"}]},\"metadata\":{\"iso_language_code\":\"und\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/android\\\" rel=\\\"nofollow\\\"\\u003eTwitter for Android\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":1241507949392138240,\"id_str\":\"1241507949392138240\",\"name\":\"Gigi7772\",\"screen_name\":\"Gigi77721\",\"location\":\"\",\"description\":\"profissional em procrastinar e ficar desenhando o dia todo, pessoa que gosta de ver o circo pegar o fogo mas que n\\u00e3o colocar\\u00e1 a lenha na fogueira pra isso\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":3,\"friends_count\":25,\"listed_count\":0,\"created_at\":\"Sat Mar 21 23:32:26 +0000 2020\",\"favourites_count\":258,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":123,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1242484034191495178\\\/RvuepMjq_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1242484034191495178\\\/RvuepMjq_normal.jpg\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Fri Apr 24 23:34:09 +0000 2020\",\"id\":1253829613031165961,\"id_str\":\"1253829613031165961\",\"text\":\"https:\\\/\\\/t.co\\\/Zi7xHqWCDQ\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[],\"media\":[{\"id\":1253829607280779264,\"id_str\":\"1253829607280779264\",\"indices\":[0,23],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWZ_Yn7WoAAPtv8.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWZ_Yn7WoAAPtv8.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/Zi7xHqWCDQ\",\"display_url\":\"pic.twitter.com\\\/Zi7xHqWCDQ\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/muieresnanet\\\/status\\\/1253829613031165961\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":653,\"h\":680,\"resize\":\"fit\"},\"large\":{\"w\":1080,\"h\":1125,\"resize\":\"fit\"},\"medium\":{\"w\":1080,\"h\":1125,\"resize\":\"fit\"}}}]},\"extended_entities\":{\"media\":[{\"id\":1253829607280779264,\"id_str\":\"1253829607280779264\",\"indices\":[0,23],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWZ_Yn7WoAAPtv8.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWZ_Yn7WoAAPtv8.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/Zi7xHqWCDQ\",\"display_url\":\"pic.twitter.com\\\/Zi7xHqWCDQ\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/muieresnanet\\\/status\\\/1253829613031165961\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":653,\"h\":680,\"resize\":\"fit\"},\"large\":{\"w\":1080,\"h\":1125,\"resize\":\"fit\"},\"medium\":{\"w\":1080,\"h\":1125,\"resize\":\"fit\"}}},{\"id\":1253829607268155395,\"id_str\":\"1253829607268155395\",\"indices\":[0,23],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWZ_Yn4WAAMDUWM.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWZ_Yn4WAAMDUWM.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/Zi7xHqWCDQ\",\"display_url\":\"pic.twitter.com\\\/Zi7xHqWCDQ\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/muieresnanet\\\/status\\\/1253829613031165961\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"medium\":{\"w\":696,\"h\":1200,\"resize\":\"fit\"},\"large\":{\"w\":742,\"h\":1280,\"resize\":\"fit\"},\"small\":{\"w\":394,\"h\":680,\"resize\":\"fit\"}}}]},\"metadata\":{\"iso_language_code\":\"und\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":1218213021010616320,\"id_str\":\"1218213021010616320\",\"name\":\"mulheres que passaram vergonha\",\"screen_name\":\"muieresnanet\",\"location\":\"\",\"description\":\"este perfil tem como objetivo o entretenimento \\\/ se quer que remova SUA imagem DM \\ud83d\\udce9\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":164214,\"friends_count\":0,\"listed_count\":55,\"created_at\":\"Fri Jan 17 16:46:42 +0000 2020\",\"favourites_count\":1816,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":205,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1218719772629786624\\\/Nza3ahvj_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1218719772629786624\\\/Nza3ahvj_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/1218213021010616320\\\/1580247905\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":436,\"favorite_count\":3472,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"und\"},\"is_quote_status\":false,\"retweet_count\":436,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"und\"},{\"created_at\":\"Sun Apr 26 00:32:23 +0000 2020\",\"id\":1254206657334251523,\"id_str\":\"1254206657334251523\",\"text\":\"@Tmac_thagod https:\\\/\\\/t.co\\\/5FKo9V38wm\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"Tmac_thagod\",\"name\":\"Tmac\",\"id\":439592686,\"id_str\":\"439592686\",\"indices\":[0,12]}],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/5FKo9V38wm\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/gloriaolembo\\\/status\\\/1254136568417259521\",\"display_url\":\"twitter.com\\\/gloriaolembo\\\/s\\u2026\",\"indices\":[13,36]}]},\"metadata\":{\"iso_language_code\":\"und\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":439592686,\"in_reply_to_user_id_str\":\"439592686\",\"in_reply_to_screen_name\":\"Tmac_thagod\",\"user\":{\"id\":2615539497,\"id_str\":\"2615539497\",\"name\":\"BBY.SATURN\",\"screen_name\":\"manny_srz\",\"location\":\"\",\"description\":\"\\u26a0\\ufe0f\\u203c\\ufe0fDon\\u2019t wanna debate w you, stupid\\u203c\\ufe0f\\u26a0\\ufe0f\\ud83d\\ude43\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":260,\"friends_count\":235,\"listed_count\":0,\"created_at\":\"Mon Jun 16 23:13:39 +0000 2014\",\"favourites_count\":24117,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":19284,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1245924964726964224\\\/bHjuSoVJ_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1245924964726964224\\\/bHjuSoVJ_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/2615539497\\\/1587097445\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":true,\"quoted_status_id\":1254136568417259521,\"quoted_status_id_str\":\"1254136568417259521\",\"quoted_status\":{\"created_at\":\"Sat Apr 25 19:53:53 +0000 2020\",\"id\":1254136568417259521,\"id_str\":\"1254136568417259521\",\"text\":\"Il n\\u2019a pas comprit le concept \\ud83d\\ude05\\n#confinement https:\\\/\\\/t.co\\\/j0pvvaXqF2\",\"truncated\":false,\"entities\":{\"hashtags\":[{\"text\":\"confinement\",\"indices\":[32,44]}],\"symbols\":[],\"user_mentions\":[],\"urls\":[],\"media\":[{\"id\":1254136503258808321,\"id_str\":\"1254136503258808321\",\"indices\":[45,68],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254136503258808321\\\/pu\\\/img\\\/F6zOsn8Id0qYrRNO.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254136503258808321\\\/pu\\\/img\\\/F6zOsn8Id0qYrRNO.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/j0pvvaXqF2\",\"display_url\":\"pic.twitter.com\\\/j0pvvaXqF2\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/GloriaOlembo\\\/status\\\/1254136568417259521\\\/video\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"medium\":{\"w\":540,\"h\":960,\"resize\":\"fit\"},\"small\":{\"w\":383,\"h\":680,\"resize\":\"fit\"},\"large\":{\"w\":540,\"h\":960,\"resize\":\"fit\"}}}]},\"extended_entities\":{\"media\":[{\"id\":1254136503258808321,\"id_str\":\"1254136503258808321\",\"indices\":[45,68],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254136503258808321\\\/pu\\\/img\\\/F6zOsn8Id0qYrRNO.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254136503258808321\\\/pu\\\/img\\\/F6zOsn8Id0qYrRNO.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/j0pvvaXqF2\",\"display_url\":\"pic.twitter.com\\\/j0pvvaXqF2\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/GloriaOlembo\\\/status\\\/1254136568417259521\\\/video\\\/1\",\"type\":\"video\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"medium\":{\"w\":540,\"h\":960,\"resize\":\"fit\"},\"small\":{\"w\":383,\"h\":680,\"resize\":\"fit\"},\"large\":{\"w\":540,\"h\":960,\"resize\":\"fit\"}},\"video_info\":{\"aspect_ratio\":[9,16],\"duration_millis\":13078,\"variants\":[{\"bitrate\":632000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254136503258808321\\\/pu\\\/vid\\\/320x568\\\/AVnszQa6W9q7c04O.mp4?tag=10\"},{\"bitrate\":832000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254136503258808321\\\/pu\\\/vid\\\/360x640\\\/Xy2jSsmTHBHeOUUi.mp4?tag=10\"},{\"content_type\":\"application\\\/x-mpegURL\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254136503258808321\\\/pu\\\/pl\\\/OKaz96Nq0Hw-jSDL.m3u8?tag=10\"},{\"bitrate\":2176000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254136503258808321\\\/pu\\\/vid\\\/540x960\\\/2pgtZuZG3AfQD02w.mp4?tag=10\"}]},\"additional_media_info\":{\"monetizable\":false}}]},\"metadata\":{\"iso_language_code\":\"und\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":1164591021008834563,\"id_str\":\"1164591021008834563\",\"name\":\"ITS MY BDAY\\ud83e\\udd73\",\"screen_name\":\"GloriaOlembo\",\"location\":\"Bruxelles, Belgique\",\"description\":\"1m66 de douceur insta: gloriaolembo\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":381,\"friends_count\":87,\"listed_count\":0,\"created_at\":\"Thu Aug 22 17:32:01 +0000 2019\",\"favourites_count\":611,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":588,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1251225268817137670\\\/E5x_QB1R_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1251225268817137670\\\/E5x_QB1R_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/1164591021008834563\\\/1584457034\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":17767,\"favorite_count\":38583,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":true,\"lang\":\"fr\"},\"retweet_count\":0,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"und\"},{\"created_at\":\"Sun Apr 26 00:32:23 +0000 2020\",\"id\":1254206657296506880,\"id_str\":\"1254206657296506880\",\"text\":\"RT @49ers: For the memories.\\nFor the laughs.\\nFor the advice.\\nFor always having our back.\\n\\n@gkittle46 shares a heartfelt message for @jstale\\u2026\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"49ers\",\"name\":\"San Francisco 49ers\",\"id\":43403778,\"id_str\":\"43403778\",\"indices\":[3,9]},{\"screen_name\":\"gkittle46\",\"name\":\"George Kittle\",\"id\":725897344357519360,\"id_str\":\"725897344357519360\",\"indices\":[90,100]}],\"urls\":[]},\"metadata\":{\"iso_language_code\":\"en\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":998424527204945920,\"id_str\":\"998424527204945920\",\"name\":\"\\ud83e\\uddb9\\ud83c\\udffc\\u200d\\u2642\\ufe0f\",\"screen_name\":\"_CursedVillain\",\"location\":\"\",\"description\":\"Sports \\u2022 Music \\u2022 Wrestling \\u2022 Gaming\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":763,\"friends_count\":1204,\"listed_count\":4,\"created_at\":\"Mon May 21 04:45:31 +0000 2018\",\"favourites_count\":65370,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":49379,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1249294890820829184\\\/6paZpZ2h_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1249294890820829184\\\/6paZpZ2h_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/998424527204945920\\\/1586690271\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Sat Apr 25 22:32:34 +0000 2020\",\"id\":1254176502628757504,\"id_str\":\"1254176502628757504\",\"text\":\"For the memories.\\nFor the laughs.\\nFor the advice.\\nFor always having our back.\\n\\n@gkittle46 shares a heartfelt messag\\u2026 https:\\\/\\\/t.co\\\/IKiHkI3yHw\",\"truncated\":true,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"gkittle46\",\"name\":\"George Kittle\",\"id\":725897344357519360,\"id_str\":\"725897344357519360\",\"indices\":[79,89]}],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/IKiHkI3yHw\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/i\\\/web\\\/status\\\/1254176502628757504\",\"display_url\":\"twitter.com\\\/i\\\/web\\\/status\\\/1\\u2026\",\"indices\":[117,140]}]},\"metadata\":{\"iso_language_code\":\"en\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/studio.twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Media Studio\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":43403778,\"id_str\":\"43403778\",\"name\":\"San Francisco 49ers\",\"screen_name\":\"49ers\",\"location\":\"\",\"description\":\"Official Twitter account of the 5-time Super Bowl Champion San Francisco 49ers. \\ud83d\\udccd@LevisStadium \\ud83e\\udd1d@49ersCommunity\",\"url\":\"https:\\\/\\\/t.co\\\/i5n2B6Tchl\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/i5n2B6Tchl\",\"expanded_url\":\"https:\\\/\\\/www.49ers.com\\\/IGYB\",\"display_url\":\"49ers.com\\\/IGYB\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":2195579,\"friends_count\":370,\"listed_count\":10319,\"created_at\":\"Fri May 29 20:34:37 +0000 2009\",\"favourites_count\":11387,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":true,\"statuses_count\":46755,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"000000\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1254124273326686208\\\/xhKFSbQQ_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1254124273326686208\\\/xhKFSbQQ_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/43403778\\\/1587841477\",\"profile_link_color\":\"AA0000\",\"profile_sidebar_border_color\":\"000000\",\"profile_sidebar_fill_color\":\"CCCCCC\",\"profile_text_color\":\"000000\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":1869,\"favorite_count\":8177,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"en\"},\"is_quote_status\":false,\"retweet_count\":1869,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"en\"},{\"created_at\":\"Sun Apr 26 00:32:23 +0000 2020\",\"id\":1254206657112027137,\"id_str\":\"1254206657112027137\",\"text\":\"She owes an apology to everyone for being on twitter. https:\\\/\\\/t.co\\\/CaXY7b1PKl\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/CaXY7b1PKl\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/carolinecstark\\\/status\\\/1254200440729763841\",\"display_url\":\"twitter.com\\\/carolinecstark\\u2026\",\"indices\":[54,77]}]},\"metadata\":{\"iso_language_code\":\"en\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/#!\\\/download\\\/ipad\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPad\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":733283255550509056,\"id_str\":\"733283255550509056\",\"name\":\"comrade 48\",\"screen_name\":\"48kiloss\",\"location\":\"\",\"description\":\"recovering\\\/ 2003\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":2359,\"friends_count\":1725,\"listed_count\":10,\"created_at\":\"Thu May 19 13:08:46 +0000 2016\",\"favourites_count\":43789,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":38037,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1244744839431946240\\\/3XCD7qEK_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1244744839431946240\\\/3XCD7qEK_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/733283255550509056\\\/1585917169\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":true,\"quoted_status_id\":1254200440729763841,\"quoted_status_id_str\":\"1254200440729763841\",\"quoted_status\":{\"created_at\":\"Sun Apr 26 00:07:41 +0000 2020\",\"id\":1254200440729763841,\"id_str\":\"1254200440729763841\",\"text\":\"Amber Tamblyn owes me an apology for being god damned annoying\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[]},\"metadata\":{\"iso_language_code\":\"en\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/mobile.twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web App\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":194071815,\"id_str\":\"194071815\",\"name\":\"\\ud83d\\ude37 Stimulus Chick\\ud83d\\ude37\",\"screen_name\":\"carolinecstark\",\"location\":\"Liberate Virginia\",\"description\":\"Views are my cat's. she\\\/her. avi by @sup_im_sammy\\n\\nVote shamers will be disinfected and put under a UV lamp\\nDon't DM unless we're friendly on here.\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":7447,\"friends_count\":6808,\"listed_count\":18,\"created_at\":\"Thu Sep 23 11:01:35 +0000 2010\",\"favourites_count\":133530,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":38023,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"0099B9\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme4\\\/bg.gif\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme4\\\/bg.gif\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1206722622802800640\\\/Tp_bK1nV_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1206722622802800640\\\/Tp_bK1nV_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/194071815\\\/1406605005\",\"profile_link_color\":\"FF691F\",\"profile_sidebar_border_color\":\"5ED4DC\",\"profile_sidebar_fill_color\":\"95E8EC\",\"profile_text_color\":\"3C3940\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":3,\"favorite_count\":37,\"favorited\":false,\"retweeted\":false,\"lang\":\"en\"},\"retweet_count\":0,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"en\"},{\"created_at\":\"Sun Apr 26 00:32:23 +0000 2020\",\"id\":1254206657111916545,\"id_str\":\"1254206657111916545\",\"text\":\"RT @LJJAY7: Take notes babygirl \\ud83e\\udd17 IG: ljaaaayyyy https:\\\/\\\/t.co\\\/ooeYap03FH\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"LJJAY7\",\"name\":\"L.\",\"id\":1220050781593899010,\"id_str\":\"1220050781593899010\",\"indices\":[3,10]}],\"urls\":[],\"media\":[{\"id\":1252762554796998658,\"id_str\":\"1252762554796998658\",\"indices\":[49,72],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1252762554796998658\\\/pu\\\/img\\\/Fsdpn0mFYGzTjn8H.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1252762554796998658\\\/pu\\\/img\\\/Fsdpn0mFYGzTjn8H.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/ooeYap03FH\",\"display_url\":\"pic.twitter.com\\\/ooeYap03FH\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/LJJAY7\\\/status\\\/1252762680496177152\\\/video\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":383,\"h\":680,\"resize\":\"fit\"},\"large\":{\"w\":720,\"h\":1280,\"resize\":\"fit\"},\"medium\":{\"w\":675,\"h\":1200,\"resize\":\"fit\"}},\"source_status_id\":1252762680496177152,\"source_status_id_str\":\"1252762680496177152\",\"source_user_id\":1220050781593899010,\"source_user_id_str\":\"1220050781593899010\"}]},\"extended_entities\":{\"media\":[{\"id\":1252762554796998658,\"id_str\":\"1252762554796998658\",\"indices\":[49,72],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1252762554796998658\\\/pu\\\/img\\\/Fsdpn0mFYGzTjn8H.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1252762554796998658\\\/pu\\\/img\\\/Fsdpn0mFYGzTjn8H.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/ooeYap03FH\",\"display_url\":\"pic.twitter.com\\\/ooeYap03FH\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/LJJAY7\\\/status\\\/1252762680496177152\\\/video\\\/1\",\"type\":\"video\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":383,\"h\":680,\"resize\":\"fit\"},\"large\":{\"w\":720,\"h\":1280,\"resize\":\"fit\"},\"medium\":{\"w\":675,\"h\":1200,\"resize\":\"fit\"}},\"source_status_id\":1252762680496177152,\"source_status_id_str\":\"1252762680496177152\",\"source_user_id\":1220050781593899010,\"source_user_id_str\":\"1220050781593899010\",\"video_info\":{\"aspect_ratio\":[9,16],\"duration_millis\":7183,\"variants\":[{\"content_type\":\"application\\\/x-mpegURL\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1252762554796998658\\\/pu\\\/pl\\\/PS4qcmG94wzmoBj7.m3u8?tag=10\"},{\"bitrate\":832000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1252762554796998658\\\/pu\\\/vid\\\/360x640\\\/eI-depY-BwgeWs80.mp4?tag=10\"},{\"bitrate\":632000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1252762554796998658\\\/pu\\\/vid\\\/320x568\\\/zYaQDzFbR1zzEuCK.mp4?tag=10\"},{\"bitrate\":2176000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1252762554796998658\\\/pu\\\/vid\\\/720x1280\\\/nw1mTLie45M_C6JU.mp4?tag=10\"}]},\"additional_media_info\":{\"monetizable\":false,\"source_user\":{\"id\":1220050781593899010,\"id_str\":\"1220050781593899010\",\"name\":\"L.\",\"screen_name\":\"LJJAY7\",\"location\":\"\",\"description\":\"Accomplish the unbelievable \\ud83e\\udd2b IG | @ljaaaayyyy Snap | @ljjaayyyy\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":44,\"friends_count\":50,\"listed_count\":0,\"created_at\":\"Wed Jan 22 18:29:17 +0000 2020\",\"favourites_count\":644,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":493,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1250909737622831104\\\/WnwKXHJ5_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1250909737622831104\\\/WnwKXHJ5_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/1220050781593899010\\\/1587857554\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"}}}]},\"metadata\":{\"iso_language_code\":\"en\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":1220050781593899010,\"id_str\":\"1220050781593899010\",\"name\":\"L.\",\"screen_name\":\"LJJAY7\",\"location\":\"\",\"description\":\"Accomplish the unbelievable \\ud83e\\udd2b IG | @ljaaaayyyy Snap | @ljjaayyyy\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":44,\"friends_count\":50,\"listed_count\":0,\"created_at\":\"Wed Jan 22 18:29:17 +0000 2020\",\"favourites_count\":644,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":493,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1250909737622831104\\\/WnwKXHJ5_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1250909737622831104\\\/WnwKXHJ5_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/1220050781593899010\\\/1587857554\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Wed Apr 22 00:54:32 +0000 2020\",\"id\":1252762680496177152,\"id_str\":\"1252762680496177152\",\"text\":\"Take notes babygirl \\ud83e\\udd17 IG: ljaaaayyyy https:\\\/\\\/t.co\\\/ooeYap03FH\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[],\"media\":[{\"id\":1252762554796998658,\"id_str\":\"1252762554796998658\",\"indices\":[37,60],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1252762554796998658\\\/pu\\\/img\\\/Fsdpn0mFYGzTjn8H.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1252762554796998658\\\/pu\\\/img\\\/Fsdpn0mFYGzTjn8H.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/ooeYap03FH\",\"display_url\":\"pic.twitter.com\\\/ooeYap03FH\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/LJJAY7\\\/status\\\/1252762680496177152\\\/video\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":383,\"h\":680,\"resize\":\"fit\"},\"large\":{\"w\":720,\"h\":1280,\"resize\":\"fit\"},\"medium\":{\"w\":675,\"h\":1200,\"resize\":\"fit\"}}}]},\"extended_entities\":{\"media\":[{\"id\":1252762554796998658,\"id_str\":\"1252762554796998658\",\"indices\":[37,60],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1252762554796998658\\\/pu\\\/img\\\/Fsdpn0mFYGzTjn8H.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1252762554796998658\\\/pu\\\/img\\\/Fsdpn0mFYGzTjn8H.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/ooeYap03FH\",\"display_url\":\"pic.twitter.com\\\/ooeYap03FH\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/LJJAY7\\\/status\\\/1252762680496177152\\\/video\\\/1\",\"type\":\"video\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":383,\"h\":680,\"resize\":\"fit\"},\"large\":{\"w\":720,\"h\":1280,\"resize\":\"fit\"},\"medium\":{\"w\":675,\"h\":1200,\"resize\":\"fit\"}},\"video_info\":{\"aspect_ratio\":[9,16],\"duration_millis\":7183,\"variants\":[{\"content_type\":\"application\\\/x-mpegURL\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1252762554796998658\\\/pu\\\/pl\\\/PS4qcmG94wzmoBj7.m3u8?tag=10\"},{\"bitrate\":832000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1252762554796998658\\\/pu\\\/vid\\\/360x640\\\/eI-depY-BwgeWs80.mp4?tag=10\"},{\"bitrate\":632000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1252762554796998658\\\/pu\\\/vid\\\/320x568\\\/zYaQDzFbR1zzEuCK.mp4?tag=10\"},{\"bitrate\":2176000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1252762554796998658\\\/pu\\\/vid\\\/720x1280\\\/nw1mTLie45M_C6JU.mp4?tag=10\"}]},\"additional_media_info\":{\"monetizable\":false}}]},\"metadata\":{\"iso_language_code\":\"en\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":1220050781593899010,\"id_str\":\"1220050781593899010\",\"name\":\"L.\",\"screen_name\":\"LJJAY7\",\"location\":\"\",\"description\":\"Accomplish the unbelievable \\ud83e\\udd2b IG | @ljaaaayyyy Snap | @ljjaayyyy\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":44,\"friends_count\":50,\"listed_count\":0,\"created_at\":\"Wed Jan 22 18:29:17 +0000 2020\",\"favourites_count\":644,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":493,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1250909737622831104\\\/WnwKXHJ5_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1250909737622831104\\\/WnwKXHJ5_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/1220050781593899010\\\/1587857554\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":1,\"favorite_count\":4,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":true,\"lang\":\"en\"},\"is_quote_status\":false,\"retweet_count\":1,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":true,\"lang\":\"en\"},{\"created_at\":\"Sun Apr 26 00:32:23 +0000 2020\",\"id\":1254206657002954753,\"id_str\":\"1254206657002954753\",\"text\":\"RT @LoudLuxury: THIS IS THE CRAZIEST SHOUTOUT WE\\u2019VE EVER HAD https:\\\/\\\/t.co\\\/S2M6rWuIv9\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"LoudLuxury\",\"name\":\"LOUD LUXURY\",\"id\":636798983,\"id_str\":\"636798983\",\"indices\":[3,14]}],\"urls\":[],\"media\":[{\"id\":1254177914548973568,\"id_str\":\"1254177914548973568\",\"indices\":[61,84],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254177914548973568\\\/pu\\\/img\\\/kJERctvXDVMIEf6V.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254177914548973568\\\/pu\\\/img\\\/kJERctvXDVMIEf6V.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/S2M6rWuIv9\",\"display_url\":\"pic.twitter.com\\\/S2M6rWuIv9\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/LoudLuxury\\\/status\\\/1254177942160109568\\\/video\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":315,\"h\":680,\"resize\":\"fit\"},\"medium\":{\"w\":555,\"h\":1200,\"resize\":\"fit\"},\"large\":{\"w\":592,\"h\":1280,\"resize\":\"fit\"}},\"source_status_id\":1254177942160109568,\"source_status_id_str\":\"1254177942160109568\",\"source_user_id\":636798983,\"source_user_id_str\":\"636798983\"}]},\"extended_entities\":{\"media\":[{\"id\":1254177914548973568,\"id_str\":\"1254177914548973568\",\"indices\":[61,84],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254177914548973568\\\/pu\\\/img\\\/kJERctvXDVMIEf6V.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254177914548973568\\\/pu\\\/img\\\/kJERctvXDVMIEf6V.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/S2M6rWuIv9\",\"display_url\":\"pic.twitter.com\\\/S2M6rWuIv9\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/LoudLuxury\\\/status\\\/1254177942160109568\\\/video\\\/1\",\"type\":\"video\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":315,\"h\":680,\"resize\":\"fit\"},\"medium\":{\"w\":555,\"h\":1200,\"resize\":\"fit\"},\"large\":{\"w\":592,\"h\":1280,\"resize\":\"fit\"}},\"source_status_id\":1254177942160109568,\"source_status_id_str\":\"1254177942160109568\",\"source_user_id\":636798983,\"source_user_id_str\":\"636798983\",\"video_info\":{\"aspect_ratio\":[37,80],\"duration_millis\":4468,\"variants\":[{\"content_type\":\"application\\\/x-mpegURL\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254177914548973568\\\/pu\\\/pl\\\/x-8n3sLVOeldDD2B.m3u8?tag=10\"},{\"bitrate\":2176000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254177914548973568\\\/pu\\\/vid\\\/592x1280\\\/BAC3g6bTrFhYAT2A.mp4?tag=10\"},{\"bitrate\":832000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254177914548973568\\\/pu\\\/vid\\\/360x778\\\/CZqGFrt5E9hWIBuF.mp4?tag=10\"},{\"bitrate\":632000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254177914548973568\\\/pu\\\/vid\\\/320x690\\\/Fl4K3_fQtPmrOutK.mp4?tag=10\"}]},\"additional_media_info\":{\"monetizable\":false,\"source_user\":{\"id\":636798983,\"id_str\":\"636798983\",\"name\":\"LOUD LUXURY\",\"screen_name\":\"LoudLuxury\",\"location\":\"\",\"description\":\"nights like this \\ud83c\\udf19\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":16239,\"friends_count\":310,\"listed_count\":79,\"created_at\":\"Mon Jul 16 08:12:40 +0000 2012\",\"favourites_count\":24502,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":true,\"statuses_count\":3860,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"000000\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1243387286156226561\\\/tSBhr6o3_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1243387286156226561\\\/tSBhr6o3_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/636798983\\\/1551346510\",\"profile_link_color\":\"ABB8C2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":false,\"has_extended_profile\":false,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"}}}]},\"metadata\":{\"iso_language_code\":\"en\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/android\\\" rel=\\\"nofollow\\\"\\u003eTwitter for Android\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":3222873008,\"id_str\":\"3222873008\",\"name\":\"Breauxs In The City\",\"screen_name\":\"braudsinthecity\",\"location\":\"New Orleans, LA\",\"description\":\"follow us through all our adventures \\ud83d\\ude0e\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":207,\"friends_count\":690,\"listed_count\":2,\"created_at\":\"Fri May 22 02:38:37 +0000 2015\",\"favourites_count\":10409,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":515,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1167663215091900418\\\/8riZRvQq_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1167663215091900418\\\/8riZRvQq_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/3222873008\\\/1502922748\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Sat Apr 25 22:38:17 +0000 2020\",\"id\":1254177942160109568,\"id_str\":\"1254177942160109568\",\"text\":\"THIS IS THE CRAZIEST SHOUTOUT WE\\u2019VE EVER HAD https:\\\/\\\/t.co\\\/S2M6rWuIv9\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[],\"media\":[{\"id\":1254177914548973568,\"id_str\":\"1254177914548973568\",\"indices\":[45,68],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254177914548973568\\\/pu\\\/img\\\/kJERctvXDVMIEf6V.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254177914548973568\\\/pu\\\/img\\\/kJERctvXDVMIEf6V.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/S2M6rWuIv9\",\"display_url\":\"pic.twitter.com\\\/S2M6rWuIv9\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/LoudLuxury\\\/status\\\/1254177942160109568\\\/video\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":315,\"h\":680,\"resize\":\"fit\"},\"medium\":{\"w\":555,\"h\":1200,\"resize\":\"fit\"},\"large\":{\"w\":592,\"h\":1280,\"resize\":\"fit\"}}}]},\"extended_entities\":{\"media\":[{\"id\":1254177914548973568,\"id_str\":\"1254177914548973568\",\"indices\":[45,68],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254177914548973568\\\/pu\\\/img\\\/kJERctvXDVMIEf6V.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254177914548973568\\\/pu\\\/img\\\/kJERctvXDVMIEf6V.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/S2M6rWuIv9\",\"display_url\":\"pic.twitter.com\\\/S2M6rWuIv9\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/LoudLuxury\\\/status\\\/1254177942160109568\\\/video\\\/1\",\"type\":\"video\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":315,\"h\":680,\"resize\":\"fit\"},\"medium\":{\"w\":555,\"h\":1200,\"resize\":\"fit\"},\"large\":{\"w\":592,\"h\":1280,\"resize\":\"fit\"}},\"video_info\":{\"aspect_ratio\":[37,80],\"duration_millis\":4468,\"variants\":[{\"content_type\":\"application\\\/x-mpegURL\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254177914548973568\\\/pu\\\/pl\\\/x-8n3sLVOeldDD2B.m3u8?tag=10\"},{\"bitrate\":2176000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254177914548973568\\\/pu\\\/vid\\\/592x1280\\\/BAC3g6bTrFhYAT2A.mp4?tag=10\"},{\"bitrate\":832000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254177914548973568\\\/pu\\\/vid\\\/360x778\\\/CZqGFrt5E9hWIBuF.mp4?tag=10\"},{\"bitrate\":632000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254177914548973568\\\/pu\\\/vid\\\/320x690\\\/Fl4K3_fQtPmrOutK.mp4?tag=10\"}]},\"additional_media_info\":{\"monetizable\":false}}]},\"metadata\":{\"iso_language_code\":\"en\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":636798983,\"id_str\":\"636798983\",\"name\":\"LOUD LUXURY\",\"screen_name\":\"LoudLuxury\",\"location\":\"\",\"description\":\"nights like this \\ud83c\\udf19\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":16239,\"friends_count\":310,\"listed_count\":79,\"created_at\":\"Mon Jul 16 08:12:40 +0000 2012\",\"favourites_count\":24502,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":true,\"statuses_count\":3860,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"000000\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1243387286156226561\\\/tSBhr6o3_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1243387286156226561\\\/tSBhr6o3_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/636798983\\\/1551346510\",\"profile_link_color\":\"ABB8C2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":false,\"has_extended_profile\":false,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":26,\"favorite_count\":251,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"en\"},\"is_quote_status\":false,\"retweet_count\":26,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"en\"},{\"created_at\":\"Sun Apr 26 00:32:23 +0000 2020\",\"id\":1254206656977661953,\"id_str\":\"1254206656977661953\",\"text\":\"https:\\\/\\\/t.co\\\/xQVrNV3BXO #\\u30d8\\u30ca\\u30bf\\u30c8\\u30a5\\u30fc\",\"truncated\":false,\"entities\":{\"hashtags\":[{\"text\":\"\\u30d8\\u30ca\\u30bf\\u30c8\\u30a5\\u30fc\",\"indices\":[24,31]}],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/xQVrNV3BXO\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/AntiXxx666\\\/status\\\/678051776164003841\",\"display_url\":\"twitter.com\\\/AntiXxx666\\\/sta\\u2026\",\"indices\":[0,23]}]},\"metadata\":{\"iso_language_code\":\"und\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twittbot.net\\\/\\\" rel=\\\"nofollow\\\"\\u003etwittbot.net\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":4599261734,\"id_str\":\"4599261734\",\"name\":\"\\u30d8\\u30ca\\u30bf\\u30c8\\u30a5\\u30fc\\u753b\\u50cfbot\",\"screen_name\":\"AntiXxx666\",\"location\":\"\",\"description\":\"\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":86,\"friends_count\":30,\"listed_count\":0,\"created_at\":\"Sat Dec 19 02:52:38 +0000 2015\",\"favourites_count\":0,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":28303,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/678047609819295744\\\/-11QfG8W_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/678047609819295744\\\/-11QfG8W_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/4599261734\\\/1450493874\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":true,\"quoted_status_id\":678051776164003841,\"quoted_status_id_str\":\"678051776164003841\",\"quoted_status\":{\"created_at\":\"Sat Dec 19 03:18:35 +0000 2015\",\"id\":678051776164003841,\"id_str\":\"678051776164003841\",\"text\":\"https:\\\/\\\/t.co\\\/BF2Jkyd6qW\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[],\"media\":[{\"id\":678051775409090561,\"id_str\":\"678051775409090561\",\"indices\":[0,23],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/CWjsf0yU8AEDk6b.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/CWjsf0yU8AEDk6b.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/BF2Jkyd6qW\",\"display_url\":\"pic.twitter.com\\\/BF2Jkyd6qW\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/AntiXxx666\\\/status\\\/678051776164003841\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"large\":{\"w\":1024,\"h\":768,\"resize\":\"fit\"},\"medium\":{\"w\":1024,\"h\":768,\"resize\":\"fit\"},\"small\":{\"w\":680,\"h\":510,\"resize\":\"fit\"}}}]},\"extended_entities\":{\"media\":[{\"id\":678051775409090561,\"id_str\":\"678051775409090561\",\"indices\":[0,23],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/CWjsf0yU8AEDk6b.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/CWjsf0yU8AEDk6b.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/BF2Jkyd6qW\",\"display_url\":\"pic.twitter.com\\\/BF2Jkyd6qW\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/AntiXxx666\\\/status\\\/678051776164003841\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"large\":{\"w\":1024,\"h\":768,\"resize\":\"fit\"},\"medium\":{\"w\":1024,\"h\":768,\"resize\":\"fit\"},\"small\":{\"w\":680,\"h\":510,\"resize\":\"fit\"}}}]},\"metadata\":{\"iso_language_code\":\"und\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web Client\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":4599261734,\"id_str\":\"4599261734\",\"name\":\"\\u30d8\\u30ca\\u30bf\\u30c8\\u30a5\\u30fc\\u753b\\u50cfbot\",\"screen_name\":\"AntiXxx666\",\"location\":\"\",\"description\":\"\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":86,\"friends_count\":30,\"listed_count\":0,\"created_at\":\"Sat Dec 19 02:52:38 +0000 2015\",\"favourites_count\":0,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":28303,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/678047609819295744\\\/-11QfG8W_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/678047609819295744\\\/-11QfG8W_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/4599261734\\\/1450493874\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":0,\"favorite_count\":3,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"und\"},\"retweet_count\":0,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"und\"},{\"created_at\":\"Sun Apr 26 00:32:23 +0000 2020\",\"id\":1254206656885514247,\"id_str\":\"1254206656885514247\",\"text\":\"RT @joseurbinasv: Despu\\u00e9s de una larga jornada de trabajo en el hospital, Paty ya va para su casa pero deja este mensaje. https:\\\/\\\/t.co\\\/5FNc\\u2026\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"joseurbinasv\",\"name\":\"Jos\\u00e9 Urbina\",\"id\":1861130508,\"id_str\":\"1861130508\",\"indices\":[3,16]}],\"urls\":[]},\"metadata\":{\"iso_language_code\":\"es\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/#!\\\/download\\\/ipad\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPad\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":1214634599789289476,\"id_str\":\"1214634599789289476\",\"name\":\"JOSE A RAMIREZ\",\"screen_name\":\"JOSEARA67680956\",\"location\":\"\",\"description\":\"APOYO AL 100% AL PRESIDENTE BUKELE Y SOY GRAN ADMIRADOR DE WALTER ARAUJO, SI LO OFENDEN A EL ME OFENDEN A MI Y FIEL DEFENSOR DE LOS INDEFENSOS ANIMALITOS\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":22,\"friends_count\":41,\"listed_count\":0,\"created_at\":\"Tue Jan 07 19:47:33 +0000 2020\",\"favourites_count\":2971,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":1184,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1227436246579978242\\\/XBDTkyeU_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1227436246579978242\\\/XBDTkyeU_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/1214634599789289476\\\/1585688240\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Sun Apr 26 00:01:01 +0000 2020\",\"id\":1254198763679289344,\"id_str\":\"1254198763679289344\",\"text\":\"Despu\\u00e9s de una larga jornada de trabajo en el hospital, Paty ya va para su casa pero deja este mensaje. https:\\\/\\\/t.co\\\/5FNcy2j3O8\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[],\"media\":[{\"id\":1254198673417830403,\"id_str\":\"1254198673417830403\",\"indices\":[104,127],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254198673417830403\\\/pu\\\/img\\\/QiEh9MSgM-XZZrf7.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254198673417830403\\\/pu\\\/img\\\/QiEh9MSgM-XZZrf7.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/5FNcy2j3O8\",\"display_url\":\"pic.twitter.com\\\/5FNcy2j3O8\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/joseurbinasv\\\/status\\\/1254198763679289344\\\/video\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"medium\":{\"w\":1200,\"h\":675,\"resize\":\"fit\"},\"small\":{\"w\":680,\"h\":383,\"resize\":\"fit\"},\"large\":{\"w\":1280,\"h\":720,\"resize\":\"fit\"}}}]},\"extended_entities\":{\"media\":[{\"id\":1254198673417830403,\"id_str\":\"1254198673417830403\",\"indices\":[104,127],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254198673417830403\\\/pu\\\/img\\\/QiEh9MSgM-XZZrf7.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254198673417830403\\\/pu\\\/img\\\/QiEh9MSgM-XZZrf7.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/5FNcy2j3O8\",\"display_url\":\"pic.twitter.com\\\/5FNcy2j3O8\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/joseurbinasv\\\/status\\\/1254198763679289344\\\/video\\\/1\",\"type\":\"video\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"medium\":{\"w\":1200,\"h\":675,\"resize\":\"fit\"},\"small\":{\"w\":680,\"h\":383,\"resize\":\"fit\"},\"large\":{\"w\":1280,\"h\":720,\"resize\":\"fit\"}},\"video_info\":{\"aspect_ratio\":[16,9],\"duration_millis\":27561,\"variants\":[{\"content_type\":\"application\\\/x-mpegURL\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254198673417830403\\\/pu\\\/pl\\\/I11us3PqI_bgan9c.m3u8?tag=10\"},{\"bitrate\":2176000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254198673417830403\\\/pu\\\/vid\\\/1280x720\\\/CbaIxgXze-LxTV3O.mp4?tag=10\"},{\"bitrate\":832000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254198673417830403\\\/pu\\\/vid\\\/640x360\\\/22fmow7vJ4LsuHtZ.mp4?tag=10\"},{\"bitrate\":256000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254198673417830403\\\/pu\\\/vid\\\/480x270\\\/gOkZOrWpiC1O2bra.mp4?tag=10\"}]},\"additional_media_info\":{\"monetizable\":false}}]},\"metadata\":{\"iso_language_code\":\"es\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/android\\\" rel=\\\"nofollow\\\"\\u003eTwitter for Android\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":1861130508,\"id_str\":\"1861130508\",\"name\":\"Jos\\u00e9 Urbina\",\"screen_name\":\"joseurbinasv\",\"location\":\"\",\"description\":\"Maestr\\u00eda en Comunicaci\\u00f3n y Postgrado en Comunicaci\\u00f3n Estrat\\u00e9gica UCA . El mundo cambia cuando los j\\u00f3venes se involucran.\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":4107,\"friends_count\":301,\"listed_count\":35,\"created_at\":\"Fri Sep 13 17:03:21 +0000 2013\",\"favourites_count\":17658,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":46439,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1236740297385705472\\\/IwgSDMrz_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1236740297385705472\\\/IwgSDMrz_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/1861130508\\\/1583696141\",\"profile_link_color\":\"001EB3\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":13,\"favorite_count\":52,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"es\"},\"is_quote_status\":false,\"retweet_count\":13,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"es\"},{\"created_at\":\"Sun Apr 26 00:32:23 +0000 2020\",\"id\":1254206656877133830,\"id_str\":\"1254206656877133830\",\"text\":\"RT @StrikeVixen: https:\\\/\\\/t.co\\\/ZaggN9dKcP\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"StrikeVixen\",\"name\":\"S T A R W I N D\",\"id\":192912527,\"id_str\":\"192912527\",\"indices\":[3,15]}],\"urls\":[],\"media\":[{\"id\":1254045904706965509,\"id_str\":\"1254045904706965509\",\"indices\":[17,40],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWdEGyoXkAU6GZJ.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWdEGyoXkAU6GZJ.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/ZaggN9dKcP\",\"display_url\":\"pic.twitter.com\\\/ZaggN9dKcP\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/StrikeVixen\\\/status\\\/1254045914391552000\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"large\":{\"w\":678,\"h\":1280,\"resize\":\"fit\"},\"small\":{\"w\":360,\"h\":680,\"resize\":\"fit\"},\"medium\":{\"w\":636,\"h\":1200,\"resize\":\"fit\"}},\"source_status_id\":1254045914391552000,\"source_status_id_str\":\"1254045914391552000\",\"source_user_id\":192912527,\"source_user_id_str\":\"192912527\"}]},\"extended_entities\":{\"media\":[{\"id\":1254045904706965509,\"id_str\":\"1254045904706965509\",\"indices\":[17,40],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWdEGyoXkAU6GZJ.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWdEGyoXkAU6GZJ.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/ZaggN9dKcP\",\"display_url\":\"pic.twitter.com\\\/ZaggN9dKcP\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/StrikeVixen\\\/status\\\/1254045914391552000\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"large\":{\"w\":678,\"h\":1280,\"resize\":\"fit\"},\"small\":{\"w\":360,\"h\":680,\"resize\":\"fit\"},\"medium\":{\"w\":636,\"h\":1200,\"resize\":\"fit\"}},\"source_status_id\":1254045914391552000,\"source_status_id_str\":\"1254045914391552000\",\"source_user_id\":192912527,\"source_user_id_str\":\"192912527\"}]},\"metadata\":{\"iso_language_code\":\"und\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/mobile.twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web App\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":3165116835,\"id_str\":\"3165116835\",\"name\":\"Assassin's Creed: New Horizons\",\"screen_name\":\"drivebykissu\",\"location\":\"South Carolina, USA\",\"description\":\"\\ud83d\\udd1e ENFP-A \\ud83c\\udf15 Not so secretly a werecat and many hyenas \\ud83c\\udf16 Video games\\\/Art\\\/Memes \\ud83c\\udf17 i: @Poodlepoofs \\ud83c\\udf18 b: @094px \\ud83c\\udf11 @excaliburnina \\ud83d\\udc9c\",\"url\":\"https:\\\/\\\/t.co\\\/5VmnLtpyin\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/5VmnLtpyin\",\"expanded_url\":\"https:\\\/\\\/www.furaffinity.net\\\/user\\\/kejah\\\/\",\"display_url\":\"furaffinity.net\\\/user\\\/kejah\\\/\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":353,\"friends_count\":2893,\"listed_count\":0,\"created_at\":\"Mon Apr 13 18:55:51 +0000 2015\",\"favourites_count\":31707,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":12111,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"131516\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme14\\\/bg.gif\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme14\\\/bg.gif\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1247058931773562882\\\/G7D5sJmV_normal.png\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1247058931773562882\\\/G7D5sJmV_normal.png\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/3165116835\\\/1573281071\",\"profile_link_color\":\"1B95E0\",\"profile_sidebar_border_color\":\"EEEEEE\",\"profile_sidebar_fill_color\":\"EFEFEF\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":false,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Sat Apr 25 13:53:39 +0000 2020\",\"id\":1254045914391552000,\"id_str\":\"1254045914391552000\",\"text\":\"https:\\\/\\\/t.co\\\/ZaggN9dKcP\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[],\"media\":[{\"id\":1254045904706965509,\"id_str\":\"1254045904706965509\",\"indices\":[0,23],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWdEGyoXkAU6GZJ.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWdEGyoXkAU6GZJ.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/ZaggN9dKcP\",\"display_url\":\"pic.twitter.com\\\/ZaggN9dKcP\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/StrikeVixen\\\/status\\\/1254045914391552000\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"large\":{\"w\":678,\"h\":1280,\"resize\":\"fit\"},\"small\":{\"w\":360,\"h\":680,\"resize\":\"fit\"},\"medium\":{\"w\":636,\"h\":1200,\"resize\":\"fit\"}}}]},\"extended_entities\":{\"media\":[{\"id\":1254045904706965509,\"id_str\":\"1254045904706965509\",\"indices\":[0,23],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWdEGyoXkAU6GZJ.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWdEGyoXkAU6GZJ.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/ZaggN9dKcP\",\"display_url\":\"pic.twitter.com\\\/ZaggN9dKcP\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/StrikeVixen\\\/status\\\/1254045914391552000\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"large\":{\"w\":678,\"h\":1280,\"resize\":\"fit\"},\"small\":{\"w\":360,\"h\":680,\"resize\":\"fit\"},\"medium\":{\"w\":636,\"h\":1200,\"resize\":\"fit\"}}}]},\"metadata\":{\"iso_language_code\":\"und\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/about.twitter.com\\\/products\\\/tweetdeck\\\" rel=\\\"nofollow\\\"\\u003eTweetDeck\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":192912527,\"id_str\":\"192912527\",\"name\":\"S T A R W I N D\",\"screen_name\":\"StrikeVixen\",\"location\":\"\",\"description\":\"Designer, writer, creator and destroyer. She\\\/Her, aspergers, HFA, ADHD, Trans MtF Untransitioned, I block minors and so should you. Occasionally NSFW.\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":3775,\"friends_count\":1116,\"listed_count\":53,\"created_at\":\"Mon Sep 20 14:05:22 +0000 2010\",\"favourites_count\":109305,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":337243,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"304FCC\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme14\\\/bg.gif\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme14\\\/bg.gif\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1181727163562811395\\\/UdfatoLk_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1181727163562811395\\\/UdfatoLk_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/192912527\\\/1570580687\",\"profile_link_color\":\"19CF86\",\"profile_sidebar_border_color\":\"FFFFFF\",\"profile_sidebar_fill_color\":\"EFEFEF\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":false,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":144,\"favorite_count\":421,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"und\"},\"is_quote_status\":false,\"retweet_count\":144,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"und\"},{\"created_at\":\"Sun Apr 26 00:32:23 +0000 2020\",\"id\":1254206656868528128,\"id_str\":\"1254206656868528128\",\"text\":\"RT @GituSharma16: #MustListan_Satsang \\n@SaintRampalJiM \\nMust watch sadna tv 7.30 to 8.30pmIST\",\"truncated\":false,\"entities\":{\"hashtags\":[{\"text\":\"MustListan_Satsang\",\"indices\":[18,37]}],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"GituSharma16\",\"name\":\"\\u2618\\ufe0fGitu sharma \\u2764\\u2618\\ufe0f\\ud83c\\uddee\\ud83c\\uddf3\\ud83d\\udcaf\",\"id\":1198984160951451648,\"id_str\":\"1198984160951451648\",\"indices\":[3,16]},{\"screen_name\":\"SaintRampalJiM\",\"name\":\"Saint Rampal Ji Maharaj\",\"id\":91851084,\"id_str\":\"91851084\",\"indices\":[39,54]}],\"urls\":[]},\"metadata\":{\"iso_language_code\":\"en\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/android\\\" rel=\\\"nofollow\\\"\\u003eTwitter for Android\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":1229250035784699904,\"id_str\":\"1229250035784699904\",\"name\":\"Bhojram Sidar(\\ud83d\\udcafFB)\",\"screen_name\":\"Bhojram88825907\",\"location\":\"\",\"description\":\"\\ud83d\\udea9\\u0930\\u093e\\u092e \\u0930\\u093e\\u092e \\u0938\\u092c \\u091c\\u0917\\u0924 \\u092c\\u0916\\u093e\\u0928\\u0947 \\u0906\\u0926\\u093f \\u0930\\u093e\\u092e \\u0915\\u094b\\u0908 \\u092c\\u093f\\u0930\\u0932\\u093e \\u091c\\u093e\\u0928\\u0947\\u0964 must watch Sadhna tv channel night 7:30pm\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":507,\"friends_count\":470,\"listed_count\":0,\"created_at\":\"Mon Feb 17 03:44:14 +0000 2020\",\"favourites_count\":857,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":590,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1237321566867918848\\\/S3t1WwBW_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1237321566867918848\\\/S3t1WwBW_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/1229250035784699904\\\/1585820547\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Sun Apr 26 00:30:03 +0000 2020\",\"id\":1254206069217337344,\"id_str\":\"1254206069217337344\",\"text\":\"#MustListan_Satsang \\n@SaintRampalJiM \\nMust watch sadna tv 7.30 to 8.30pmIST https:\\\/\\\/t.co\\\/p69xnX78bI\",\"truncated\":false,\"entities\":{\"hashtags\":[{\"text\":\"MustListan_Satsang\",\"indices\":[0,19]}],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"SaintRampalJiM\",\"name\":\"Saint Rampal Ji Maharaj\",\"id\":91851084,\"id_str\":\"91851084\",\"indices\":[21,36]}],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/p69xnX78bI\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/SaintRampalJiM\\\/status\\\/1254204588133019648\",\"display_url\":\"twitter.com\\\/SaintRampalJiM\\u2026\",\"indices\":[77,100]}]},\"metadata\":{\"iso_language_code\":\"en\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/android\\\" rel=\\\"nofollow\\\"\\u003eTwitter for Android\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":1198984160951451648,\"id_str\":\"1198984160951451648\",\"name\":\"\\u2618\\ufe0fGitu sharma \\u2764\\u2618\\ufe0f\\ud83c\\uddee\\ud83c\\uddf3\\ud83d\\udcaf\",\"screen_name\":\"GituSharma16\",\"location\":\"Assam, India\",\"description\":\"\\ud83c\\uddee\\ud83c\\uddf3\\u092e\\u0928\\u0941\\u0937\\u094d\\u092f\\u0964 \\u091c\\u0928\\u094d\\u092e \\u0926\\u0941\\u0930\\u094d\\u0932\\u092d \\u0939\\u0948 \\u092e\\u093f\\u0932\\u0947 \\u0928\\u093e \\u092c\\u0930\\u093e\\u092e \\u092c\\u093e\\u0930\\ud83d\\ude4fonly sewa \\ud83d\\ude4f\\ud83d\\ude4f\",\"url\":\"https:\\\/\\\/t.co\\\/rwdohULLw5\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/rwdohULLw5\",\"expanded_url\":\"http:\\\/\\\/www.jagatgururampalji.org.com\",\"display_url\":\"jagatgururampalji.org.com\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":2747,\"friends_count\":2306,\"listed_count\":0,\"created_at\":\"Mon Nov 25 15:18:49 +0000 2019\",\"favourites_count\":2463,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":3474,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1253690240029638656\\\/3aVMFiPH_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1253690240029638656\\\/3aVMFiPH_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/1198984160951451648\\\/1587714561\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":true,\"quoted_status_id\":1254204588133019648,\"quoted_status_id_str\":\"1254204588133019648\",\"quoted_status\":{\"created_at\":\"Sun Apr 26 00:24:10 +0000 2020\",\"id\":1254204588133019648,\"id_str\":\"1254204588133019648\",\"text\":\"#MustListen_Satsang || Nepal 1 TV 26-04-2020 | Episode - 105 | Sant Rampal Ji Maharaj Satsang https:\\\/\\\/t.co\\\/xYaTSQ4vet\",\"truncated\":false,\"entities\":{\"hashtags\":[{\"text\":\"MustListen_Satsang\",\"indices\":[0,19]}],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/xYaTSQ4vet\",\"expanded_url\":\"https:\\\/\\\/www.pscp.tv\\\/w\\\/cXN6qjFwempNT1ZNcVpnUWR8MXZBeFJCcW1hZ0R4bD0OtZn8wclVZYmhDcmdSZkaTnB5cGWNjXxZ7o4ejlPd\",\"display_url\":\"pscp.tv\\\/w\\\/cXN6qjFwempN\\u2026\",\"indices\":[94,117]}]},\"metadata\":{\"iso_language_code\":\"en\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/periscope.tv\\\" rel=\\\"nofollow\\\"\\u003ePeriscope\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":91851084,\"id_str\":\"91851084\",\"name\":\"Saint Rampal Ji Maharaj\",\"screen_name\":\"SaintRampalJiM\",\"location\":\"Barwala, Hisar, India\",\"description\":\"\\u0905\\u092e\\u0930 \\u0915\\u0930\\u0942\\u0902 \\u0938\\u0924\\u0932\\u094b\\u0915 \\u092a\\u0920\\u093e\\u0901\\u090a, \\u0924\\u093e\\u0924\\u0948\\u0902 \\u092c\\u0928\\u094d\\u0926\\u0940 \\u091b\\u094b\\u0921\\u093c \\u0915\\u0939\\u093e\\u090a\\u0901\",\"url\":\"http:\\\/\\\/t.co\\\/q48PTmNW9Y\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"http:\\\/\\\/t.co\\\/q48PTmNW9Y\",\"expanded_url\":\"http:\\\/\\\/www.jagatgururampalji.org\",\"display_url\":\"jagatgururampalji.org\",\"indices\":[0,22]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":50282,\"friends_count\":3,\"listed_count\":93,\"created_at\":\"Sun Nov 22 19:27:42 +0000 2009\",\"favourites_count\":634,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":2405,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"FFF04D\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme19\\\/bg.gif\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme19\\\/bg.gif\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1191924069840502784\\\/aA1V1BV__normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1191924069840502784\\\/aA1V1BV__normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/91851084\\\/1539069376\",\"profile_link_color\":\"0099CC\",\"profile_sidebar_border_color\":\"FFF8AD\",\"profile_sidebar_fill_color\":\"F6FFD1\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":47,\"favorite_count\":87,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"hi\"},\"retweet_count\":1,\"favorite_count\":1,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"en\"},\"is_quote_status\":true,\"quoted_status_id\":1254204588133019648,\"quoted_status_id_str\":\"1254204588133019648\",\"retweet_count\":1,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"en\"},{\"created_at\":\"Sun Apr 26 00:32:23 +0000 2020\",\"id\":1254206656809926656,\"id_str\":\"1254206656809926656\",\"text\":\"CC: @ABC @CBSNews @NBCNews @MSNBC @CNN https:\\\/\\\/t.co\\\/Y6BpPdxQpa\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"ABC\",\"name\":\"ABC News\",\"id\":28785486,\"id_str\":\"28785486\",\"indices\":[4,8]},{\"screen_name\":\"CBSNews\",\"name\":\"CBS News\",\"id\":15012486,\"id_str\":\"15012486\",\"indices\":[9,17]},{\"screen_name\":\"NBCNews\",\"name\":\"NBC News\",\"id\":14173315,\"id_str\":\"14173315\",\"indices\":[18,26]},{\"screen_name\":\"MSNBC\",\"name\":\"MSNBC\",\"id\":2836421,\"id_str\":\"2836421\",\"indices\":[27,33]},{\"screen_name\":\"CNN\",\"name\":\"CNN\",\"id\":759251,\"id_str\":\"759251\",\"indices\":[34,38]}],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/Y6BpPdxQpa\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/RepAdamSchiff\\\/status\\\/1253481322141679619\",\"display_url\":\"twitter.com\\\/RepAdamSchiff\\\/\\u2026\",\"indices\":[39,62]}]},\"metadata\":{\"iso_language_code\":\"und\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/mobile.twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web App\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":1181369330690342912,\"id_str\":\"1181369330690342912\",\"name\":\"Citizen, Interrupted (again)\",\"screen_name\":\"NYCwonk\",\"location\":\"Manhattan, NY\",\"description\":\"Don't blame me, I voted for the e-mail lady. \\nSame old me. New account. Who dis?\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":116,\"friends_count\":263,\"listed_count\":1,\"created_at\":\"Tue Oct 08 00:43:02 +0000 2019\",\"favourites_count\":1556,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":6591,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"000000\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1229976132918939648\\\/KCJjWNUW_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1229976132918939648\\\/KCJjWNUW_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/1181369330690342912\\\/1579923707\",\"profile_link_color\":\"1B95E0\",\"profile_sidebar_border_color\":\"000000\",\"profile_sidebar_fill_color\":\"000000\",\"profile_text_color\":\"000000\",\"profile_use_background_image\":false,\"has_extended_profile\":false,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":true,\"quoted_status_id\":1253481322141679619,\"quoted_status_id_str\":\"1253481322141679619\",\"quoted_status\":{\"created_at\":\"Fri Apr 24 00:30:10 +0000 2020\",\"id\":1253481322141679619,\"id_str\":\"1253481322141679619\",\"text\":\"A week ago I asked whether it was responsible to carry Trump\\u2019s nightly stream of consciousness on live TV.\\n\\nToday,\\u2026 https:\\\/\\\/t.co\\\/sXD3mko7y8\",\"truncated\":true,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/sXD3mko7y8\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/i\\\/web\\\/status\\\/1253481322141679619\",\"display_url\":\"twitter.com\\\/i\\\/web\\\/status\\\/1\\u2026\",\"indices\":[116,139]}]},\"metadata\":{\"iso_language_code\":\"und\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":29501253,\"id_str\":\"29501253\",\"name\":\"Adam Schiff\",\"screen_name\":\"RepAdamSchiff\",\"location\":\"Burbank, CA\",\"description\":\"Representing California's 28th Congressional District. Chairman of the House Intelligence Committee (@HouseIntel).\",\"url\":\"https:\\\/\\\/t.co\\\/uxaSLX8uQ7\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/uxaSLX8uQ7\",\"expanded_url\":\"http:\\\/\\\/schiff.house.gov\\\/\",\"display_url\":\"schiff.house.gov\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":2205582,\"friends_count\":776,\"listed_count\":9698,\"created_at\":\"Tue Apr 07 17:54:35 +0000 2009\",\"favourites_count\":153,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":true,\"statuses_count\":5683,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"2578B8\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/816361054699667458\\\/0DVL6HrY_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/816361054699667458\\\/0DVL6HrY_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/29501253\\\/1547736718\",\"profile_link_color\":\"2578B8\",\"profile_sidebar_border_color\":\"FFFFFF\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":false,\"has_extended_profile\":false,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":true,\"quoted_status_id\":1253451487415619586,\"quoted_status_id_str\":\"1253451487415619586\",\"retweet_count\":28471,\"favorite_count\":92742,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"en\"},\"retweet_count\":0,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"und\"},{\"created_at\":\"Sun Apr 26 00:32:23 +0000 2020\",\"id\":1254206656759468032,\"id_str\":\"1254206656759468032\",\"text\":\"RT @bighitzip: taehyung - profile https:\\\/\\\/t.co\\\/s2sJ2XLhX3\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"bighitzip\",\"name\":\"ARMY.ZIP\",\"id\":1253937691898478596,\"id_str\":\"1253937691898478596\",\"indices\":[3,13]}],\"urls\":[],\"media\":[{\"id\":1253966623028854784,\"id_str\":\"1253966623028854784\",\"indices\":[34,57],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWb7__XUwAAoi52.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWb7__XUwAAoi52.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/s2sJ2XLhX3\",\"display_url\":\"pic.twitter.com\\\/s2sJ2XLhX3\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/bighitzip\\\/status\\\/1253966635460726789\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"medium\":{\"w\":800,\"h\":1200,\"resize\":\"fit\"},\"large\":{\"w\":1000,\"h\":1500,\"resize\":\"fit\"},\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":453,\"h\":680,\"resize\":\"fit\"}},\"source_status_id\":1253966635460726789,\"source_status_id_str\":\"1253966635460726789\",\"source_user_id\":1253937691898478596,\"source_user_id_str\":\"1253937691898478596\"}]},\"extended_entities\":{\"media\":[{\"id\":1253966623028854784,\"id_str\":\"1253966623028854784\",\"indices\":[34,57],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWb7__XUwAAoi52.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWb7__XUwAAoi52.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/s2sJ2XLhX3\",\"display_url\":\"pic.twitter.com\\\/s2sJ2XLhX3\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/bighitzip\\\/status\\\/1253966635460726789\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"medium\":{\"w\":800,\"h\":1200,\"resize\":\"fit\"},\"large\":{\"w\":1000,\"h\":1500,\"resize\":\"fit\"},\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":453,\"h\":680,\"resize\":\"fit\"}},\"source_status_id\":1253966635460726789,\"source_status_id_str\":\"1253966635460726789\",\"source_user_id\":1253937691898478596,\"source_user_id_str\":\"1253937691898478596\"},{\"id\":1253966623028899841,\"id_str\":\"1253966623028899841\",\"indices\":[34,57],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWb7__XVcAEufDY.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWb7__XVcAEufDY.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/s2sJ2XLhX3\",\"display_url\":\"pic.twitter.com\\\/s2sJ2XLhX3\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/bighitzip\\\/status\\\/1253966635460726789\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"medium\":{\"w\":799,\"h\":1200,\"resize\":\"fit\"},\"small\":{\"w\":453,\"h\":680,\"resize\":\"fit\"},\"large\":{\"w\":1000,\"h\":1501,\"resize\":\"fit\"}},\"source_status_id\":1253966635460726789,\"source_status_id_str\":\"1253966635460726789\",\"source_user_id\":1253937691898478596,\"source_user_id_str\":\"1253937691898478596\"}]},\"metadata\":{\"iso_language_code\":\"tl\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/android\\\" rel=\\\"nofollow\\\"\\u003eTwitter for Android\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":1108896926,\"id_str\":\"1108896926\",\"name\":\"Mustiallati\",\"screen_name\":\"mustialati\",\"location\":\"Pekanbaru,indonesia\",\"description\":\"ig : mustialati\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":354,\"friends_count\":142,\"listed_count\":0,\"created_at\":\"Mon Jan 21 12:23:57 +0000 2013\",\"favourites_count\":1542,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":10558,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"A49AAB\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1251522363465728001\\\/lLcE3j-6_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1251522363465728001\\\/lLcE3j-6_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/1108896926\\\/1529771720\",\"profile_link_color\":\"9944DD\",\"profile_sidebar_border_color\":\"FFFFFF\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Sat Apr 25 08:38:38 +0000 2020\",\"id\":1253966635460726789,\"id_str\":\"1253966635460726789\",\"text\":\"taehyung - profile https:\\\/\\\/t.co\\\/s2sJ2XLhX3\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[],\"media\":[{\"id\":1253966623028854784,\"id_str\":\"1253966623028854784\",\"indices\":[19,42],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWb7__XUwAAoi52.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWb7__XUwAAoi52.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/s2sJ2XLhX3\",\"display_url\":\"pic.twitter.com\\\/s2sJ2XLhX3\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/bighitzip\\\/status\\\/1253966635460726789\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"medium\":{\"w\":800,\"h\":1200,\"resize\":\"fit\"},\"large\":{\"w\":1000,\"h\":1500,\"resize\":\"fit\"},\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":453,\"h\":680,\"resize\":\"fit\"}}}]},\"extended_entities\":{\"media\":[{\"id\":1253966623028854784,\"id_str\":\"1253966623028854784\",\"indices\":[19,42],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWb7__XUwAAoi52.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWb7__XUwAAoi52.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/s2sJ2XLhX3\",\"display_url\":\"pic.twitter.com\\\/s2sJ2XLhX3\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/bighitzip\\\/status\\\/1253966635460726789\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"medium\":{\"w\":800,\"h\":1200,\"resize\":\"fit\"},\"large\":{\"w\":1000,\"h\":1500,\"resize\":\"fit\"},\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":453,\"h\":680,\"resize\":\"fit\"}}},{\"id\":1253966623028899841,\"id_str\":\"1253966623028899841\",\"indices\":[19,42],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWb7__XVcAEufDY.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWb7__XVcAEufDY.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/s2sJ2XLhX3\",\"display_url\":\"pic.twitter.com\\\/s2sJ2XLhX3\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/bighitzip\\\/status\\\/1253966635460726789\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"medium\":{\"w\":799,\"h\":1200,\"resize\":\"fit\"},\"small\":{\"w\":453,\"h\":680,\"resize\":\"fit\"},\"large\":{\"w\":1000,\"h\":1501,\"resize\":\"fit\"}}}]},\"metadata\":{\"iso_language_code\":\"tl\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/mobile.twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web App\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":1253966632663150592,\"in_reply_to_status_id_str\":\"1253966632663150592\",\"in_reply_to_user_id\":1253937691898478596,\"in_reply_to_user_id_str\":\"1253937691898478596\",\"in_reply_to_screen_name\":\"bighitzip\",\"user\":{\"id\":1253937691898478596,\"id_str\":\"1253937691898478596\",\"name\":\"ARMY.ZIP\",\"screen_name\":\"bighitzip\",\"location\":\"\",\"description\":\"https:\\\/\\\/t.co\\\/V6KgbWseoc\",\"url\":null,\"entities\":{\"description\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/V6KgbWseoc\",\"expanded_url\":\"http:\\\/\\\/bts-armyzip.weverse.io\",\"display_url\":\"bts-armyzip.weverse.io\",\"indices\":[0,23]}]}},\"protected\":false,\"followers_count\":14175,\"friends_count\":0,\"listed_count\":83,\"created_at\":\"Sat Apr 25 06:43:44 +0000 2020\",\"favourites_count\":0,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":15,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"F5F8FA\",\"profile_background_image_url\":null,\"profile_background_image_url_https\":null,\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1253939404940423169\\\/1zJGW8Gm_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1253939404940423169\\\/1zJGW8Gm_normal.jpg\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":2064,\"favorite_count\":7227,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"tl\"},\"is_quote_status\":false,\"retweet_count\":2064,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"tl\"},{\"created_at\":\"Sun Apr 26 00:32:23 +0000 2020\",\"id\":1254206656755482628,\"id_str\":\"1254206656755482628\",\"text\":\"@bealadriel77 Voy, voy, es que se me peta Twitter con tanta petici\\u00f3n y respuesta, jaja. Ahora mismo te env\\u00edo MD \\ud83d\\ude0a\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"bealadriel77\",\"name\":\"Beatriz Jimenez Sanz\",\"id\":611069726,\"id_str\":\"611069726\",\"indices\":[0,13]}],\"urls\":[]},\"metadata\":{\"iso_language_code\":\"es\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/android\\\" rel=\\\"nofollow\\\"\\u003eTwitter for Android\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":1254205823057829890,\"in_reply_to_status_id_str\":\"1254205823057829890\",\"in_reply_to_user_id\":611069726,\"in_reply_to_user_id_str\":\"611069726\",\"in_reply_to_screen_name\":\"bealadriel77\",\"user\":{\"id\":95011355,\"id_str\":\"95011355\",\"name\":\"Ylenia\",\"screen_name\":\"Ylenia_07\",\"location\":\"\",\"description\":\"\\ud83d\\udeaf\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":557,\"friends_count\":297,\"listed_count\":16,\"created_at\":\"Sun Dec 06 14:51:57 +0000 2009\",\"favourites_count\":11709,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":92707,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"709397\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme9\\\/bg.gif\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme9\\\/bg.gif\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1237899870779965440\\\/D8lv3mv8_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1237899870779965440\\\/D8lv3mv8_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/95011355\\\/1583450679\",\"profile_link_color\":\"8C8284\",\"profile_sidebar_border_color\":\"FFFFFF\",\"profile_sidebar_fill_color\":\"252429\",\"profile_text_color\":\"666666\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":0,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"es\"},{\"created_at\":\"Sun Apr 26 00:32:23 +0000 2020\",\"id\":1254206656684195842,\"id_str\":\"1254206656684195842\",\"text\":\"So any woman will do? Even an evil murdering one? https:\\\/\\\/t.co\\\/cRcsbmXw9O\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/cRcsbmXw9O\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/sethabramson\\\/status\\\/1254180308989235201\",\"display_url\":\"twitter.com\\\/sethabramson\\\/s\\u2026\",\"indices\":[50,73]}]},\"metadata\":{\"iso_language_code\":\"en\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/iphone\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":728469625,\"id_str\":\"728469625\",\"name\":\"commonsense\",\"screen_name\":\"commonsense258\",\"location\":\"\",\"description\":\"I love sports and current events. Oh and my Yorkie thinks he's human and I'm okay with that.\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":1449,\"friends_count\":438,\"listed_count\":51,\"created_at\":\"Tue Jul 31 14:08:02 +0000 2012\",\"favourites_count\":503592,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":false,\"statuses_count\":256669,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/799401203872518144\\\/Pz99ggy5_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/799401203872518144\\\/Pz99ggy5_normal.jpg\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":true,\"quoted_status_id\":1254180308989235201,\"quoted_status_id_str\":\"1254180308989235201\",\"quoted_status\":{\"created_at\":\"Sat Apr 25 22:47:41 +0000 2020\",\"id\":1254180308989235201,\"id_str\":\"1254180308989235201\",\"text\":\"Still processing the possibility that North Korea will have its first woman leader before the United States\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[]},\"metadata\":{\"iso_language_code\":\"en\",\"result_type\":\"recent\"},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\/download\\\/android\\\" rel=\\\"nofollow\\\"\\u003eTwitter for Android\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":3223426134,\"id_str\":\"3223426134\",\"name\":\"Seth Abramson (@\\ud83c\\udfe0)\",\"screen_name\":\"SethAbramson\",\"location\":\"All views mine.\",\"description\":\"Attorney. @Newsweek columnist. Professor. Author of New York Times bestsellers Proof of Conspiracy (https:\\\/\\\/t.co\\\/jPbI2P5OQ0) & Proof of Collusion (https:\\\/\\\/t.co\\\/YUd8v4GoNp).\",\"url\":\"https:\\\/\\\/t.co\\\/BgxDeUKKGK\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/BgxDeUKKGK\",\"expanded_url\":\"http:\\\/\\\/www.sethabramson.net\\\/bio\",\"display_url\":\"sethabramson.net\\\/bio\",\"indices\":[0,23]}]},\"description\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/jPbI2P5OQ0\",\"expanded_url\":\"http:\\\/\\\/amzn.to\\\/2sQBWYL\",\"display_url\":\"amzn.to\\\/2sQBWYL\",\"indices\":[100,123]},{\"url\":\"https:\\\/\\\/t.co\\\/YUd8v4GoNp\",\"expanded_url\":\"http:\\\/\\\/amzn.to\\\/39WyLz5\",\"display_url\":\"amzn.to\\\/39WyLz5\",\"indices\":[147,170]}]}},\"protected\":false,\"followers_count\":800707,\"friends_count\":25,\"listed_count\":7598,\"created_at\":\"Fri May 22 16:19:26 +0000 2015\",\"favourites_count\":3,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":true,\"statuses_count\":74721,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"000000\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1188673360231833601\\\/8lwhEkl9_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/1188673360231833601\\\/8lwhEkl9_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/3223426134\\\/1583422472\",\"profile_link_color\":\"F01405\",\"profile_sidebar_border_color\":\"000000\",\"profile_sidebar_fill_color\":\"000000\",\"profile_text_color\":\"000000\",\"profile_use_background_image\":false,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":915,\"favorite_count\":4887,\"favorited\":false,\"retweeted\":false,\"lang\":\"en\"},\"retweet_count\":0,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"en\"}],\"search_metadata\":{\"completed_in\":0.141,\"max_id\":1254206657657257984,\"max_id_str\":\"1254206657657257984\",\"next_results\":\"?max_id=1254206656684195841&q=twitter&include_entities=1\",\"query\":\"twitter\",\"refresh_url\":\"?since_id=1254206657657257984&q=twitter&include_entities=1\",\"count\":15,\"since_id\":0,\"since_id_str\":\"0\"}}" - } -}] \ No newline at end of file diff --git a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testOauth2BearerToken.json b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testOauth2BearerToken.json deleted file mode 100644 index 67c47775b..000000000 --- a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testOauth2BearerToken.json +++ /dev/null @@ -1,49 +0,0 @@ -[{ - "request": { - "method": "GET", - "url": "https:\/\/api.twitter.com\/1.1\/statuses\/user_timeline.json?screen_name=twitterapi", - "headers": { - "Host": "api.twitter.com", - "Accept": "application\/json", - "Authorization": "Bearer AAAAAAAAAAAAAAAAAAAAAFobAAAAAAAAjPes3FlPiFKh9HaIg%2Fw80waE0s8%3DQqxjhHDgZyjihGIK7olugzbpS0R1Gg8KNhzmer58a6oVbsSGc0", - "Expect": null - } - }, - "response": { - "status": { - "http_version": "2", - "code": "200", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-disposition": "attachment; filename=json.json", - "content-encoding": "gzip", - "content-length": "5813", - "content-type": "application\/json;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:31:10 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:31:10 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_KEOd+4RSJKhY\/zL1nJqQjA==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:10 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, guest_id=v1%3A158786107019843003; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:10 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "200 OK", - "strict-transport-security": "max-age=631138519", - "x-access-level": "read", - "x-app-rate-limit-limit": "100000", - "x-app-rate-limit-remaining": "99993", - "x-app-rate-limit-reset": "1587934974", - "x-connection-hash": "ed574879e196a7f193fd49c8b71c2056", - "x-content-type-options": "nosniff", - "x-frame-options": "SAMEORIGIN", - "x-rate-limit-limit": "1500", - "x-rate-limit-remaining": "1497", - "x-rate-limit-reset": "1587861581", - "x-response-time": "62", - "x-transaction": "00c660e200263b3e", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "0" - }, - "body": "[{\"created_at\":\"Mon Mar 23 22:14:35 +0000 2020\",\"id\":1242213180060758016,\"id_str\":\"1242213180060758016\",\"text\":\"RT @TwitterDev: As we work to keep our employees safe during COVID-19, you are likely to experience longer than usual review times for deve\\u2026\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"TwitterDev\",\"name\":\"Twitter Dev\",\"id\":2244994945,\"id_str\":\"2244994945\",\"indices\":[3,14]}],\"urls\":[]},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/mobile.twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web App\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":6253282,\"id_str\":\"6253282\",\"name\":\"Twitter API\",\"screen_name\":\"TwitterAPI\",\"location\":\"San Francisco, CA\",\"description\":\"The Real Twitter API. Tweets about API changes, service issues and our Developer Platform. Don't get an answer? It's on my website.\",\"url\":\"https:\\\/\\\/t.co\\\/8IkCzCDr19\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/8IkCzCDr19\",\"expanded_url\":\"https:\\\/\\\/developer.twitter.com\",\"display_url\":\"developer.twitter.com\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":6084394,\"friends_count\":12,\"listed_count\":12763,\"created_at\":\"Wed May 23 06:01:13 +0000 2007\",\"favourites_count\":30,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":true,\"statuses_count\":3680,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/942858479592554497\\\/BbazLO9L_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/942858479592554497\\\/BbazLO9L_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/6253282\\\/1497491515\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Mon Mar 23 22:01:13 +0000 2020\",\"id\":1242209814706438144,\"id_str\":\"1242209814706438144\",\"text\":\"As we work to keep our employees safe during COVID-19, you are likely to experience longer than usual review times\\u2026 https:\\\/\\\/t.co\\\/Oo1t07UH4Z\",\"truncated\":true,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/Oo1t07UH4Z\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/i\\\/web\\\/status\\\/1242209814706438144\",\"display_url\":\"twitter.com\\\/i\\\/web\\\/status\\\/1\\u2026\",\"indices\":[116,139]}]},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/mobile.twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web App\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":2244994945,\"id_str\":\"2244994945\",\"name\":\"Twitter Dev\",\"screen_name\":\"TwitterDev\",\"location\":\"127.0.0.1\",\"description\":\"The voice of Twitter's #DevRel team, and your official source for updates, news, & events about Twitter's API.\\n\\nNeed help? Visit https:\\\/\\\/t.co\\\/DVDf7qKyS9\",\"url\":\"https:\\\/\\\/t.co\\\/3ZX3TNiZCY\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/3ZX3TNiZCY\",\"expanded_url\":\"https:\\\/\\\/developer.twitter.com\\\/en\\\/community\",\"display_url\":\"developer.twitter.com\\\/en\\\/community\",\"indices\":[0,23]}]},\"description\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/DVDf7qKyS9\",\"expanded_url\":\"http:\\\/\\\/twittercommunity.com\",\"display_url\":\"twittercommunity.com\",\"indices\":[129,152]}]}},\"protected\":false,\"followers_count\":507649,\"friends_count\":1808,\"listed_count\":1672,\"created_at\":\"Sat Dec 14 04:35:55 +0000 2013\",\"favourites_count\":2182,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":true,\"statuses_count\":3540,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"FFFFFF\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/880136122604507136\\\/xHrnqf1T_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/880136122604507136\\\/xHrnqf1T_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/2244994945\\\/1498675817\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"FFFFFF\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":false,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":40,\"favorite_count\":113,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"en\"},\"is_quote_status\":false,\"retweet_count\":40,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"en\"},{\"created_at\":\"Mon Mar 23 16:28:09 +0000 2020\",\"id\":1242125997081673728,\"id_str\":\"1242125997081673728\",\"text\":\"RT @TwitterDev: A few months ago, we added Tweet annotations to the Labs\\u2019 streaming endpoints. These annotations help uncover details about\\u2026\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"TwitterDev\",\"name\":\"Twitter Dev\",\"id\":2244994945,\"id_str\":\"2244994945\",\"indices\":[3,14]}],\"urls\":[]},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/mobile.twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web App\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":6253282,\"id_str\":\"6253282\",\"name\":\"Twitter API\",\"screen_name\":\"TwitterAPI\",\"location\":\"San Francisco, CA\",\"description\":\"The Real Twitter API. Tweets about API changes, service issues and our Developer Platform. Don't get an answer? It's on my website.\",\"url\":\"https:\\\/\\\/t.co\\\/8IkCzCDr19\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/8IkCzCDr19\",\"expanded_url\":\"https:\\\/\\\/developer.twitter.com\",\"display_url\":\"developer.twitter.com\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":6084394,\"friends_count\":12,\"listed_count\":12763,\"created_at\":\"Wed May 23 06:01:13 +0000 2007\",\"favourites_count\":30,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":true,\"statuses_count\":3680,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/942858479592554497\\\/BbazLO9L_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/942858479592554497\\\/BbazLO9L_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/6253282\\\/1497491515\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Mon Mar 23 16:26:08 +0000 2020\",\"id\":1242125486844604425,\"id_str\":\"1242125486844604425\",\"text\":\"A few months ago, we added Tweet annotations to the Labs\\u2019 streaming endpoints. These annotations help uncover detai\\u2026 https:\\\/\\\/t.co\\\/ViHyvQ4Y8S\",\"truncated\":true,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/ViHyvQ4Y8S\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/i\\\/web\\\/status\\\/1242125486844604425\",\"display_url\":\"twitter.com\\\/i\\\/web\\\/status\\\/1\\u2026\",\"indices\":[117,140]}]},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/mobile.twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web App\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":2244994945,\"id_str\":\"2244994945\",\"name\":\"Twitter Dev\",\"screen_name\":\"TwitterDev\",\"location\":\"127.0.0.1\",\"description\":\"The voice of Twitter's #DevRel team, and your official source for updates, news, & events about Twitter's API.\\n\\nNeed help? Visit https:\\\/\\\/t.co\\\/DVDf7qKyS9\",\"url\":\"https:\\\/\\\/t.co\\\/3ZX3TNiZCY\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/3ZX3TNiZCY\",\"expanded_url\":\"https:\\\/\\\/developer.twitter.com\\\/en\\\/community\",\"display_url\":\"developer.twitter.com\\\/en\\\/community\",\"indices\":[0,23]}]},\"description\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/DVDf7qKyS9\",\"expanded_url\":\"http:\\\/\\\/twittercommunity.com\",\"display_url\":\"twittercommunity.com\",\"indices\":[129,152]}]}},\"protected\":false,\"followers_count\":507649,\"friends_count\":1808,\"listed_count\":1672,\"created_at\":\"Sat Dec 14 04:35:55 +0000 2013\",\"favourites_count\":2182,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":true,\"statuses_count\":3540,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"FFFFFF\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/880136122604507136\\\/xHrnqf1T_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/880136122604507136\\\/xHrnqf1T_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/2244994945\\\/1498675817\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"FFFFFF\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":false,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":true,\"quoted_status_id\":1204497856679202816,\"quoted_status_id_str\":\"1204497856679202816\",\"quoted_status\":{\"created_at\":\"Tue Dec 10 20:27:22 +0000 2019\",\"id\":1204497856679202816,\"id_str\":\"1204497856679202816\",\"text\":\"You may have seen the recent announcement about following Topics on Twitter. Today, we\\u2019re excited to provide API su\\u2026 https:\\\/\\\/t.co\\\/ZlJUjmHIBe\",\"truncated\":true,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/ZlJUjmHIBe\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/i\\\/web\\\/status\\\/1204497856679202816\",\"display_url\":\"twitter.com\\\/i\\\/web\\\/status\\\/1\\u2026\",\"indices\":[117,140]}]},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/mobile.twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web App\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":2244994945,\"id_str\":\"2244994945\",\"name\":\"Twitter Dev\",\"screen_name\":\"TwitterDev\",\"location\":\"127.0.0.1\",\"description\":\"The voice of Twitter's #DevRel team, and your official source for updates, news, & events about Twitter's API.\\n\\nNeed help? Visit https:\\\/\\\/t.co\\\/DVDf7qKyS9\",\"url\":\"https:\\\/\\\/t.co\\\/3ZX3TNiZCY\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/3ZX3TNiZCY\",\"expanded_url\":\"https:\\\/\\\/developer.twitter.com\\\/en\\\/community\",\"display_url\":\"developer.twitter.com\\\/en\\\/community\",\"indices\":[0,23]}]},\"description\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/DVDf7qKyS9\",\"expanded_url\":\"http:\\\/\\\/twittercommunity.com\",\"display_url\":\"twittercommunity.com\",\"indices\":[129,152]}]}},\"protected\":false,\"followers_count\":507649,\"friends_count\":1808,\"listed_count\":1672,\"created_at\":\"Sat Dec 14 04:35:55 +0000 2013\",\"favourites_count\":2182,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":true,\"statuses_count\":3540,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"FFFFFF\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/880136122604507136\\\/xHrnqf1T_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/880136122604507136\\\/xHrnqf1T_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/2244994945\\\/1498675817\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"FFFFFF\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":false,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":91,\"favorite_count\":245,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"en\"},\"retweet_count\":32,\"favorite_count\":75,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"en\"},\"is_quote_status\":true,\"quoted_status_id\":1204497856679202816,\"quoted_status_id_str\":\"1204497856679202816\",\"retweet_count\":32,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"en\"},{\"created_at\":\"Tue Mar 10 17:57:58 +0000 2020\",\"id\":1237437557337513984,\"id_str\":\"1237437557337513984\",\"text\":\"RT @TwitterDev: We \\u2764\\ufe0f the incredible research people do using Twitter data to study topics like spam, abuse, and other areas related to the\\u2026\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"TwitterDev\",\"name\":\"Twitter Dev\",\"id\":2244994945,\"id_str\":\"2244994945\",\"indices\":[3,14]}],\"urls\":[]},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/mobile.twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web App\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":6253282,\"id_str\":\"6253282\",\"name\":\"Twitter API\",\"screen_name\":\"TwitterAPI\",\"location\":\"San Francisco, CA\",\"description\":\"The Real Twitter API. Tweets about API changes, service issues and our Developer Platform. Don't get an answer? It's on my website.\",\"url\":\"https:\\\/\\\/t.co\\\/8IkCzCDr19\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/8IkCzCDr19\",\"expanded_url\":\"https:\\\/\\\/developer.twitter.com\",\"display_url\":\"developer.twitter.com\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":6084394,\"friends_count\":12,\"listed_count\":12763,\"created_at\":\"Wed May 23 06:01:13 +0000 2007\",\"favourites_count\":30,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":true,\"statuses_count\":3680,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/942858479592554497\\\/BbazLO9L_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/942858479592554497\\\/BbazLO9L_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/6253282\\\/1497491515\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Tue Mar 10 17:47:53 +0000 2020\",\"id\":1237435017883762689,\"id_str\":\"1237435017883762689\",\"text\":\"We \\u2764\\ufe0f the incredible research people do using Twitter data to study topics like spam, abuse, and other areas relate\\u2026 https:\\\/\\\/t.co\\\/NpF4h9DaSq\",\"truncated\":true,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/NpF4h9DaSq\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/i\\\/web\\\/status\\\/1237435017883762689\",\"display_url\":\"twitter.com\\\/i\\\/web\\\/status\\\/1\\u2026\",\"indices\":[117,140]}]},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/mobile.twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web App\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":1237435016134656006,\"in_reply_to_status_id_str\":\"1237435016134656006\",\"in_reply_to_user_id\":2244994945,\"in_reply_to_user_id_str\":\"2244994945\",\"in_reply_to_screen_name\":\"TwitterDev\",\"user\":{\"id\":2244994945,\"id_str\":\"2244994945\",\"name\":\"Twitter Dev\",\"screen_name\":\"TwitterDev\",\"location\":\"127.0.0.1\",\"description\":\"The voice of Twitter's #DevRel team, and your official source for updates, news, & events about Twitter's API.\\n\\nNeed help? Visit https:\\\/\\\/t.co\\\/DVDf7qKyS9\",\"url\":\"https:\\\/\\\/t.co\\\/3ZX3TNiZCY\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/3ZX3TNiZCY\",\"expanded_url\":\"https:\\\/\\\/developer.twitter.com\\\/en\\\/community\",\"display_url\":\"developer.twitter.com\\\/en\\\/community\",\"indices\":[0,23]}]},\"description\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/DVDf7qKyS9\",\"expanded_url\":\"http:\\\/\\\/twittercommunity.com\",\"display_url\":\"twittercommunity.com\",\"indices\":[129,152]}]}},\"protected\":false,\"followers_count\":507649,\"friends_count\":1808,\"listed_count\":1672,\"created_at\":\"Sat Dec 14 04:35:55 +0000 2013\",\"favourites_count\":2182,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":true,\"statuses_count\":3540,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"FFFFFF\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/880136122604507136\\\/xHrnqf1T_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/880136122604507136\\\/xHrnqf1T_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/2244994945\\\/1498675817\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"FFFFFF\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":false,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":25,\"favorite_count\":72,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"en\"},\"is_quote_status\":false,\"retweet_count\":25,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"en\"},{\"created_at\":\"Wed Feb 26 17:33:41 +0000 2020\",\"id\":1232720402700521474,\"id_str\":\"1232720402700521474\",\"text\":\"RT @TwitterDev: In November, we gave people the ability to hide replies to their Tweets. Starting today, we\\u2019re opening this feature up to d\\u2026\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"TwitterDev\",\"name\":\"Twitter Dev\",\"id\":2244994945,\"id_str\":\"2244994945\",\"indices\":[3,14]}],\"urls\":[]},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/mobile.twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web App\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":6253282,\"id_str\":\"6253282\",\"name\":\"Twitter API\",\"screen_name\":\"TwitterAPI\",\"location\":\"San Francisco, CA\",\"description\":\"The Real Twitter API. Tweets about API changes, service issues and our Developer Platform. Don't get an answer? It's on my website.\",\"url\":\"https:\\\/\\\/t.co\\\/8IkCzCDr19\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/8IkCzCDr19\",\"expanded_url\":\"https:\\\/\\\/developer.twitter.com\",\"display_url\":\"developer.twitter.com\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":6084394,\"friends_count\":12,\"listed_count\":12763,\"created_at\":\"Wed May 23 06:01:13 +0000 2007\",\"favourites_count\":30,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":true,\"statuses_count\":3680,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/942858479592554497\\\/BbazLO9L_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/942858479592554497\\\/BbazLO9L_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/6253282\\\/1497491515\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Wed Feb 26 17:32:51 +0000 2020\",\"id\":1232720193182412800,\"id_str\":\"1232720193182412800\",\"text\":\"In November, we gave people the ability to hide replies to their Tweets. Starting today, we\\u2019re opening this feature\\u2026 https:\\\/\\\/t.co\\\/aN8kan0Lsw\",\"truncated\":true,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/aN8kan0Lsw\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/i\\\/web\\\/status\\\/1232720193182412800\",\"display_url\":\"twitter.com\\\/i\\\/web\\\/status\\\/1\\u2026\",\"indices\":[117,140]}]},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/mobile.twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web App\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":2244994945,\"id_str\":\"2244994945\",\"name\":\"Twitter Dev\",\"screen_name\":\"TwitterDev\",\"location\":\"127.0.0.1\",\"description\":\"The voice of Twitter's #DevRel team, and your official source for updates, news, & events about Twitter's API.\\n\\nNeed help? Visit https:\\\/\\\/t.co\\\/DVDf7qKyS9\",\"url\":\"https:\\\/\\\/t.co\\\/3ZX3TNiZCY\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/3ZX3TNiZCY\",\"expanded_url\":\"https:\\\/\\\/developer.twitter.com\\\/en\\\/community\",\"display_url\":\"developer.twitter.com\\\/en\\\/community\",\"indices\":[0,23]}]},\"description\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/DVDf7qKyS9\",\"expanded_url\":\"http:\\\/\\\/twittercommunity.com\",\"display_url\":\"twittercommunity.com\",\"indices\":[129,152]}]}},\"protected\":false,\"followers_count\":507649,\"friends_count\":1808,\"listed_count\":1672,\"created_at\":\"Sat Dec 14 04:35:55 +0000 2013\",\"favourites_count\":2182,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":true,\"statuses_count\":3540,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"FFFFFF\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/880136122604507136\\\/xHrnqf1T_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/880136122604507136\\\/xHrnqf1T_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/2244994945\\\/1498675817\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"FFFFFF\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":false,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":147,\"favorite_count\":388,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"en\"},\"is_quote_status\":false,\"retweet_count\":147,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"en\"},{\"created_at\":\"Mon Jan 06 20:23:49 +0000 2020\",\"id\":1214281438092238855,\"id_str\":\"1214281438092238855\",\"text\":\"RT @TwitterDev: Hello\\u2026 is it me you\\u2019re searching for? \\ud83d\\udd0e\\n\\nSearch the conversation as it unfolds with this new addition to Labs. We're making\\u2026\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"TwitterDev\",\"name\":\"Twitter Dev\",\"id\":2244994945,\"id_str\":\"2244994945\",\"indices\":[3,14]}],\"urls\":[]},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/mobile.twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web App\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":6253282,\"id_str\":\"6253282\",\"name\":\"Twitter API\",\"screen_name\":\"TwitterAPI\",\"location\":\"San Francisco, CA\",\"description\":\"The Real Twitter API. Tweets about API changes, service issues and our Developer Platform. Don't get an answer? It's on my website.\",\"url\":\"https:\\\/\\\/t.co\\\/8IkCzCDr19\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/8IkCzCDr19\",\"expanded_url\":\"https:\\\/\\\/developer.twitter.com\",\"display_url\":\"developer.twitter.com\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":6084394,\"friends_count\":12,\"listed_count\":12763,\"created_at\":\"Wed May 23 06:01:13 +0000 2007\",\"favourites_count\":30,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":true,\"statuses_count\":3680,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/942858479592554497\\\/BbazLO9L_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/942858479592554497\\\/BbazLO9L_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/6253282\\\/1497491515\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Mon Jan 06 20:22:05 +0000 2020\",\"id\":1214281000932593667,\"id_str\":\"1214281000932593667\",\"text\":\"Hello\\u2026 is it me you\\u2019re searching for? \\ud83d\\udd0e\\n\\nSearch the conversation as it unfolds with this new addition to Labs. We'r\\u2026 https:\\\/\\\/t.co\\\/XaqD1JJ5kF\",\"truncated\":true,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/XaqD1JJ5kF\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/i\\\/web\\\/status\\\/1214281000932593667\",\"display_url\":\"twitter.com\\\/i\\\/web\\\/status\\\/1\\u2026\",\"indices\":[117,140]}]},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/mobile.twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web App\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":2244994945,\"id_str\":\"2244994945\",\"name\":\"Twitter Dev\",\"screen_name\":\"TwitterDev\",\"location\":\"127.0.0.1\",\"description\":\"The voice of Twitter's #DevRel team, and your official source for updates, news, & events about Twitter's API.\\n\\nNeed help? Visit https:\\\/\\\/t.co\\\/DVDf7qKyS9\",\"url\":\"https:\\\/\\\/t.co\\\/3ZX3TNiZCY\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/3ZX3TNiZCY\",\"expanded_url\":\"https:\\\/\\\/developer.twitter.com\\\/en\\\/community\",\"display_url\":\"developer.twitter.com\\\/en\\\/community\",\"indices\":[0,23]}]},\"description\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/DVDf7qKyS9\",\"expanded_url\":\"http:\\\/\\\/twittercommunity.com\",\"display_url\":\"twittercommunity.com\",\"indices\":[129,152]}]}},\"protected\":false,\"followers_count\":507649,\"friends_count\":1808,\"listed_count\":1672,\"created_at\":\"Sat Dec 14 04:35:55 +0000 2013\",\"favourites_count\":2182,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":true,\"statuses_count\":3540,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"FFFFFF\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/880136122604507136\\\/xHrnqf1T_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/880136122604507136\\\/xHrnqf1T_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/2244994945\\\/1498675817\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"FFFFFF\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":false,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":64,\"favorite_count\":165,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"en\"},\"is_quote_status\":false,\"retweet_count\":64,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"en\"},{\"created_at\":\"Fri Jan 03 17:21:34 +0000 2020\",\"id\":1213148410145992704,\"id_str\":\"1213148410145992704\",\"text\":\"RT @TwitterDev: Today, we\\u2019re sharing a few small improvements to make it easier for academic researchers to get started with the Twitter AP\\u2026\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"TwitterDev\",\"name\":\"Twitter Dev\",\"id\":2244994945,\"id_str\":\"2244994945\",\"indices\":[3,14]}],\"urls\":[]},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/mobile.twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web App\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":6253282,\"id_str\":\"6253282\",\"name\":\"Twitter API\",\"screen_name\":\"TwitterAPI\",\"location\":\"San Francisco, CA\",\"description\":\"The Real Twitter API. Tweets about API changes, service issues and our Developer Platform. Don't get an answer? It's on my website.\",\"url\":\"https:\\\/\\\/t.co\\\/8IkCzCDr19\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/8IkCzCDr19\",\"expanded_url\":\"https:\\\/\\\/developer.twitter.com\",\"display_url\":\"developer.twitter.com\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":6084394,\"friends_count\":12,\"listed_count\":12763,\"created_at\":\"Wed May 23 06:01:13 +0000 2007\",\"favourites_count\":30,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":true,\"statuses_count\":3680,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/942858479592554497\\\/BbazLO9L_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/942858479592554497\\\/BbazLO9L_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/6253282\\\/1497491515\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Fri Jan 03 17:17:23 +0000 2020\",\"id\":1213147357551816704,\"id_str\":\"1213147357551816704\",\"text\":\"Today, we\\u2019re sharing a few small improvements to make it easier for academic researchers to get started with the Tw\\u2026 https:\\\/\\\/t.co\\\/WhV7rP54GM\",\"truncated\":true,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/WhV7rP54GM\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/i\\\/web\\\/status\\\/1213147357551816704\",\"display_url\":\"twitter.com\\\/i\\\/web\\\/status\\\/1\\u2026\",\"indices\":[117,140]}]},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/mobile.twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web App\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":2244994945,\"id_str\":\"2244994945\",\"name\":\"Twitter Dev\",\"screen_name\":\"TwitterDev\",\"location\":\"127.0.0.1\",\"description\":\"The voice of Twitter's #DevRel team, and your official source for updates, news, & events about Twitter's API.\\n\\nNeed help? Visit https:\\\/\\\/t.co\\\/DVDf7qKyS9\",\"url\":\"https:\\\/\\\/t.co\\\/3ZX3TNiZCY\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/3ZX3TNiZCY\",\"expanded_url\":\"https:\\\/\\\/developer.twitter.com\\\/en\\\/community\",\"display_url\":\"developer.twitter.com\\\/en\\\/community\",\"indices\":[0,23]}]},\"description\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/DVDf7qKyS9\",\"expanded_url\":\"http:\\\/\\\/twittercommunity.com\",\"display_url\":\"twittercommunity.com\",\"indices\":[129,152]}]}},\"protected\":false,\"followers_count\":507649,\"friends_count\":1808,\"listed_count\":1672,\"created_at\":\"Sat Dec 14 04:35:55 +0000 2013\",\"favourites_count\":2182,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":true,\"statuses_count\":3540,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"FFFFFF\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/880136122604507136\\\/xHrnqf1T_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/880136122604507136\\\/xHrnqf1T_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/2244994945\\\/1498675817\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"FFFFFF\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":false,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":214,\"favorite_count\":448,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"en\"},\"is_quote_status\":false,\"retweet_count\":214,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"en\"},{\"created_at\":\"Tue Dec 10 20:34:57 +0000 2019\",\"id\":1204499768459661312,\"id_str\":\"1204499768459661312\",\"text\":\"RT @TwitterDev: You may have seen the recent announcement about following Topics on Twitter. Today, we\\u2019re excited to provide API support fo\\u2026\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"TwitterDev\",\"name\":\"Twitter Dev\",\"id\":2244994945,\"id_str\":\"2244994945\",\"indices\":[3,14]}],\"urls\":[]},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/mobile.twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web App\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":6253282,\"id_str\":\"6253282\",\"name\":\"Twitter API\",\"screen_name\":\"TwitterAPI\",\"location\":\"San Francisco, CA\",\"description\":\"The Real Twitter API. Tweets about API changes, service issues and our Developer Platform. Don't get an answer? It's on my website.\",\"url\":\"https:\\\/\\\/t.co\\\/8IkCzCDr19\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/8IkCzCDr19\",\"expanded_url\":\"https:\\\/\\\/developer.twitter.com\",\"display_url\":\"developer.twitter.com\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":6084394,\"friends_count\":12,\"listed_count\":12763,\"created_at\":\"Wed May 23 06:01:13 +0000 2007\",\"favourites_count\":30,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":true,\"statuses_count\":3680,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/942858479592554497\\\/BbazLO9L_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/942858479592554497\\\/BbazLO9L_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/6253282\\\/1497491515\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Tue Dec 10 20:27:22 +0000 2019\",\"id\":1204497856679202816,\"id_str\":\"1204497856679202816\",\"text\":\"You may have seen the recent announcement about following Topics on Twitter. Today, we\\u2019re excited to provide API su\\u2026 https:\\\/\\\/t.co\\\/ZlJUjmHIBe\",\"truncated\":true,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/ZlJUjmHIBe\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/i\\\/web\\\/status\\\/1204497856679202816\",\"display_url\":\"twitter.com\\\/i\\\/web\\\/status\\\/1\\u2026\",\"indices\":[117,140]}]},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/mobile.twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web App\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":2244994945,\"id_str\":\"2244994945\",\"name\":\"Twitter Dev\",\"screen_name\":\"TwitterDev\",\"location\":\"127.0.0.1\",\"description\":\"The voice of Twitter's #DevRel team, and your official source for updates, news, & events about Twitter's API.\\n\\nNeed help? Visit https:\\\/\\\/t.co\\\/DVDf7qKyS9\",\"url\":\"https:\\\/\\\/t.co\\\/3ZX3TNiZCY\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/3ZX3TNiZCY\",\"expanded_url\":\"https:\\\/\\\/developer.twitter.com\\\/en\\\/community\",\"display_url\":\"developer.twitter.com\\\/en\\\/community\",\"indices\":[0,23]}]},\"description\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/DVDf7qKyS9\",\"expanded_url\":\"http:\\\/\\\/twittercommunity.com\",\"display_url\":\"twittercommunity.com\",\"indices\":[129,152]}]}},\"protected\":false,\"followers_count\":507649,\"friends_count\":1808,\"listed_count\":1672,\"created_at\":\"Sat Dec 14 04:35:55 +0000 2013\",\"favourites_count\":2182,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":true,\"statuses_count\":3540,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"FFFFFF\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/880136122604507136\\\/xHrnqf1T_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/880136122604507136\\\/xHrnqf1T_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/2244994945\\\/1498675817\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"FFFFFF\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":false,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":91,\"favorite_count\":245,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"en\"},\"is_quote_status\":false,\"retweet_count\":91,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"en\"},{\"created_at\":\"Tue Oct 29 19:39:40 +0000 2019\",\"id\":1189265562821640193,\"id_str\":\"1189265562821640193\",\"text\":\"RT @TwitterDev: Study a sample of timely, relevant Tweets as they happen, with the newest release in Twitter Developer Labs. https:\\\/\\\/t.co\\\/m\\u2026\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"TwitterDev\",\"name\":\"Twitter Dev\",\"id\":2244994945,\"id_str\":\"2244994945\",\"indices\":[3,14]}],\"urls\":[]},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/mobile.twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web App\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":6253282,\"id_str\":\"6253282\",\"name\":\"Twitter API\",\"screen_name\":\"TwitterAPI\",\"location\":\"San Francisco, CA\",\"description\":\"The Real Twitter API. Tweets about API changes, service issues and our Developer Platform. Don't get an answer? It's on my website.\",\"url\":\"https:\\\/\\\/t.co\\\/8IkCzCDr19\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/8IkCzCDr19\",\"expanded_url\":\"https:\\\/\\\/developer.twitter.com\",\"display_url\":\"developer.twitter.com\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":6084394,\"friends_count\":12,\"listed_count\":12763,\"created_at\":\"Wed May 23 06:01:13 +0000 2007\",\"favourites_count\":30,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":true,\"statuses_count\":3680,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/942858479592554497\\\/BbazLO9L_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/942858479592554497\\\/BbazLO9L_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/6253282\\\/1497491515\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Tue Oct 29 19:37:15 +0000 2019\",\"id\":1189264953368338432,\"id_str\":\"1189264953368338432\",\"text\":\"Study a sample of timely, relevant Tweets as they happen, with the newest release in Twitter Developer Labs.\\u2026 https:\\\/\\\/t.co\\\/Y5QMh8rNoh\",\"truncated\":true,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/Y5QMh8rNoh\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/i\\\/web\\\/status\\\/1189264953368338432\",\"display_url\":\"twitter.com\\\/i\\\/web\\\/status\\\/1\\u2026\",\"indices\":[110,133]}]},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/mobile.twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web App\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":2244994945,\"id_str\":\"2244994945\",\"name\":\"Twitter Dev\",\"screen_name\":\"TwitterDev\",\"location\":\"127.0.0.1\",\"description\":\"The voice of Twitter's #DevRel team, and your official source for updates, news, & events about Twitter's API.\\n\\nNeed help? Visit https:\\\/\\\/t.co\\\/DVDf7qKyS9\",\"url\":\"https:\\\/\\\/t.co\\\/3ZX3TNiZCY\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/3ZX3TNiZCY\",\"expanded_url\":\"https:\\\/\\\/developer.twitter.com\\\/en\\\/community\",\"display_url\":\"developer.twitter.com\\\/en\\\/community\",\"indices\":[0,23]}]},\"description\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/DVDf7qKyS9\",\"expanded_url\":\"http:\\\/\\\/twittercommunity.com\",\"display_url\":\"twittercommunity.com\",\"indices\":[129,152]}]}},\"protected\":false,\"followers_count\":507649,\"friends_count\":1808,\"listed_count\":1672,\"created_at\":\"Sat Dec 14 04:35:55 +0000 2013\",\"favourites_count\":2182,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":true,\"statuses_count\":3540,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"FFFFFF\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/880136122604507136\\\/xHrnqf1T_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/880136122604507136\\\/xHrnqf1T_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/2244994945\\\/1498675817\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"FFFFFF\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":false,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":45,\"favorite_count\":139,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"en\"},\"is_quote_status\":false,\"retweet_count\":45,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"en\"},{\"created_at\":\"Wed Sep 18 16:41:39 +0000 2019\",\"id\":1174362863118372867,\"id_str\":\"1174362863118372867\",\"text\":\"RT @TwitterDev: Today in Twitter Developer Labs we\\u2019re releasing a new way to filter Tweets in real-time. This is one of the most popular fe\\u2026\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"TwitterDev\",\"name\":\"Twitter Dev\",\"id\":2244994945,\"id_str\":\"2244994945\",\"indices\":[3,14]}],\"urls\":[]},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/mobile.twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web App\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":6253282,\"id_str\":\"6253282\",\"name\":\"Twitter API\",\"screen_name\":\"TwitterAPI\",\"location\":\"San Francisco, CA\",\"description\":\"The Real Twitter API. Tweets about API changes, service issues and our Developer Platform. Don't get an answer? It's on my website.\",\"url\":\"https:\\\/\\\/t.co\\\/8IkCzCDr19\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/8IkCzCDr19\",\"expanded_url\":\"https:\\\/\\\/developer.twitter.com\",\"display_url\":\"developer.twitter.com\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":6084394,\"friends_count\":12,\"listed_count\":12763,\"created_at\":\"Wed May 23 06:01:13 +0000 2007\",\"favourites_count\":30,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":true,\"statuses_count\":3680,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/942858479592554497\\\/BbazLO9L_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/942858479592554497\\\/BbazLO9L_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/6253282\\\/1497491515\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Wed Sep 18 16:36:10 +0000 2019\",\"id\":1174361480734466048,\"id_str\":\"1174361480734466048\",\"text\":\"Today in Twitter Developer Labs we\\u2019re releasing a new way to filter Tweets in real-time. This is one of the most po\\u2026 https:\\\/\\\/t.co\\\/RElmBW5XxM\",\"truncated\":true,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/RElmBW5XxM\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/i\\\/web\\\/status\\\/1174361480734466048\",\"display_url\":\"twitter.com\\\/i\\\/web\\\/status\\\/1\\u2026\",\"indices\":[117,140]}]},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/mobile.twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web App\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":2244994945,\"id_str\":\"2244994945\",\"name\":\"Twitter Dev\",\"screen_name\":\"TwitterDev\",\"location\":\"127.0.0.1\",\"description\":\"The voice of Twitter's #DevRel team, and your official source for updates, news, & events about Twitter's API.\\n\\nNeed help? Visit https:\\\/\\\/t.co\\\/DVDf7qKyS9\",\"url\":\"https:\\\/\\\/t.co\\\/3ZX3TNiZCY\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/3ZX3TNiZCY\",\"expanded_url\":\"https:\\\/\\\/developer.twitter.com\\\/en\\\/community\",\"display_url\":\"developer.twitter.com\\\/en\\\/community\",\"indices\":[0,23]}]},\"description\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/DVDf7qKyS9\",\"expanded_url\":\"http:\\\/\\\/twittercommunity.com\",\"display_url\":\"twittercommunity.com\",\"indices\":[129,152]}]}},\"protected\":false,\"followers_count\":507649,\"friends_count\":1808,\"listed_count\":1672,\"created_at\":\"Sat Dec 14 04:35:55 +0000 2013\",\"favourites_count\":2182,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":true,\"statuses_count\":3540,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"FFFFFF\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/880136122604507136\\\/xHrnqf1T_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/880136122604507136\\\/xHrnqf1T_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/2244994945\\\/1498675817\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"FFFFFF\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":false,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":107,\"favorite_count\":231,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"en\"},\"is_quote_status\":false,\"retweet_count\":107,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"en\"},{\"created_at\":\"Tue Aug 27 17:30:39 +0000 2019\",\"id\":1166402661282746368,\"id_str\":\"1166402661282746368\",\"text\":\"RT @TwitterDev: Our latest Twitter Developer Labs release helps you quickly assess the impact of your Tweets. Today, we\\u2019re releasing \\n\\n\\u2728a n\\u2026\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"TwitterDev\",\"name\":\"Twitter Dev\",\"id\":2244994945,\"id_str\":\"2244994945\",\"indices\":[3,14]}],\"urls\":[]},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/mobile.twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web App\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":6253282,\"id_str\":\"6253282\",\"name\":\"Twitter API\",\"screen_name\":\"TwitterAPI\",\"location\":\"San Francisco, CA\",\"description\":\"The Real Twitter API. Tweets about API changes, service issues and our Developer Platform. Don't get an answer? It's on my website.\",\"url\":\"https:\\\/\\\/t.co\\\/8IkCzCDr19\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/8IkCzCDr19\",\"expanded_url\":\"https:\\\/\\\/developer.twitter.com\",\"display_url\":\"developer.twitter.com\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":6084394,\"friends_count\":12,\"listed_count\":12763,\"created_at\":\"Wed May 23 06:01:13 +0000 2007\",\"favourites_count\":30,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":true,\"statuses_count\":3680,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/942858479592554497\\\/BbazLO9L_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/942858479592554497\\\/BbazLO9L_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/6253282\\\/1497491515\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Tue Aug 27 17:25:06 +0000 2019\",\"id\":1166401263170281472,\"id_str\":\"1166401263170281472\",\"text\":\"Our latest Twitter Developer Labs release helps you quickly assess the impact of your Tweets. Today, we\\u2019re releasin\\u2026 https:\\\/\\\/t.co\\\/a8PaA1wg5A\",\"truncated\":true,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/a8PaA1wg5A\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/i\\\/web\\\/status\\\/1166401263170281472\",\"display_url\":\"twitter.com\\\/i\\\/web\\\/status\\\/1\\u2026\",\"indices\":[117,140]}]},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/mobile.twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web App\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":2244994945,\"id_str\":\"2244994945\",\"name\":\"Twitter Dev\",\"screen_name\":\"TwitterDev\",\"location\":\"127.0.0.1\",\"description\":\"The voice of Twitter's #DevRel team, and your official source for updates, news, & events about Twitter's API.\\n\\nNeed help? Visit https:\\\/\\\/t.co\\\/DVDf7qKyS9\",\"url\":\"https:\\\/\\\/t.co\\\/3ZX3TNiZCY\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/3ZX3TNiZCY\",\"expanded_url\":\"https:\\\/\\\/developer.twitter.com\\\/en\\\/community\",\"display_url\":\"developer.twitter.com\\\/en\\\/community\",\"indices\":[0,23]}]},\"description\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/DVDf7qKyS9\",\"expanded_url\":\"http:\\\/\\\/twittercommunity.com\",\"display_url\":\"twittercommunity.com\",\"indices\":[129,152]}]}},\"protected\":false,\"followers_count\":507649,\"friends_count\":1808,\"listed_count\":1672,\"created_at\":\"Sat Dec 14 04:35:55 +0000 2013\",\"favourites_count\":2182,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":true,\"statuses_count\":3540,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"FFFFFF\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/880136122604507136\\\/xHrnqf1T_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/880136122604507136\\\/xHrnqf1T_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/2244994945\\\/1498675817\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"FFFFFF\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":false,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":56,\"favorite_count\":165,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"en\"},\"is_quote_status\":false,\"retweet_count\":56,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"en\"},{\"created_at\":\"Fri Aug 16 17:25:53 +0000 2019\",\"id\":1162415194749882368,\"id_str\":\"1162415194749882368\",\"text\":\"RT @TwitterDev: As of today, we\\u2019re simplifying permissions for third-party apps. Most developers won't be impacted, but if your app uses th\\u2026\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"TwitterDev\",\"name\":\"Twitter Dev\",\"id\":2244994945,\"id_str\":\"2244994945\",\"indices\":[3,14]}],\"urls\":[]},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter for iPhone\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":6253282,\"id_str\":\"6253282\",\"name\":\"Twitter API\",\"screen_name\":\"TwitterAPI\",\"location\":\"San Francisco, CA\",\"description\":\"The Real Twitter API. Tweets about API changes, service issues and our Developer Platform. Don't get an answer? It's on my website.\",\"url\":\"https:\\\/\\\/t.co\\\/8IkCzCDr19\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/8IkCzCDr19\",\"expanded_url\":\"https:\\\/\\\/developer.twitter.com\",\"display_url\":\"developer.twitter.com\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":6084394,\"friends_count\":12,\"listed_count\":12763,\"created_at\":\"Wed May 23 06:01:13 +0000 2007\",\"favourites_count\":30,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":true,\"statuses_count\":3680,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/942858479592554497\\\/BbazLO9L_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/942858479592554497\\\/BbazLO9L_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/6253282\\\/1497491515\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Fri Aug 16 17:07:22 +0000 2019\",\"id\":1162410535121387525,\"id_str\":\"1162410535121387525\",\"text\":\"As of today, we\\u2019re simplifying permissions for third-party apps. Most developers won't be impacted, but if your app\\u2026 https:\\\/\\\/t.co\\\/VemT1Licd9\",\"truncated\":true,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/VemT1Licd9\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/i\\\/web\\\/status\\\/1162410535121387525\",\"display_url\":\"twitter.com\\\/i\\\/web\\\/status\\\/1\\u2026\",\"indices\":[117,140]}]},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/mobile.twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web App\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":2244994945,\"id_str\":\"2244994945\",\"name\":\"Twitter Dev\",\"screen_name\":\"TwitterDev\",\"location\":\"127.0.0.1\",\"description\":\"The voice of Twitter's #DevRel team, and your official source for updates, news, & events about Twitter's API.\\n\\nNeed help? Visit https:\\\/\\\/t.co\\\/DVDf7qKyS9\",\"url\":\"https:\\\/\\\/t.co\\\/3ZX3TNiZCY\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/3ZX3TNiZCY\",\"expanded_url\":\"https:\\\/\\\/developer.twitter.com\\\/en\\\/community\",\"display_url\":\"developer.twitter.com\\\/en\\\/community\",\"indices\":[0,23]}]},\"description\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/DVDf7qKyS9\",\"expanded_url\":\"http:\\\/\\\/twittercommunity.com\",\"display_url\":\"twittercommunity.com\",\"indices\":[129,152]}]}},\"protected\":false,\"followers_count\":507649,\"friends_count\":1808,\"listed_count\":1672,\"created_at\":\"Sat Dec 14 04:35:55 +0000 2013\",\"favourites_count\":2182,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":true,\"statuses_count\":3540,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"FFFFFF\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/880136122604507136\\\/xHrnqf1T_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/880136122604507136\\\/xHrnqf1T_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/2244994945\\\/1498675817\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"FFFFFF\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":false,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":33,\"favorite_count\":95,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"en\"},\"is_quote_status\":false,\"retweet_count\":33,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"en\"},{\"created_at\":\"Thu Aug 15 16:24:23 +0000 2019\",\"id\":1162037328442875904,\"id_str\":\"1162037328442875904\",\"text\":\"RT @TwitterDev: #iterating: We recently released a long-requested feature in Twitter Developer Labs: \\n\\n\\ud83d\\udcccDeveloper\\u2019s can now request a user\\u2019\\u2026\",\"truncated\":false,\"entities\":{\"hashtags\":[{\"text\":\"iterating\",\"indices\":[16,26]}],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"TwitterDev\",\"name\":\"Twitter Dev\",\"id\":2244994945,\"id_str\":\"2244994945\",\"indices\":[3,14]}],\"urls\":[]},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/mobile.twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web App\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":6253282,\"id_str\":\"6253282\",\"name\":\"Twitter API\",\"screen_name\":\"TwitterAPI\",\"location\":\"San Francisco, CA\",\"description\":\"The Real Twitter API. Tweets about API changes, service issues and our Developer Platform. Don't get an answer? It's on my website.\",\"url\":\"https:\\\/\\\/t.co\\\/8IkCzCDr19\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/8IkCzCDr19\",\"expanded_url\":\"https:\\\/\\\/developer.twitter.com\",\"display_url\":\"developer.twitter.com\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":6084394,\"friends_count\":12,\"listed_count\":12763,\"created_at\":\"Wed May 23 06:01:13 +0000 2007\",\"favourites_count\":30,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":true,\"statuses_count\":3680,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/942858479592554497\\\/BbazLO9L_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/942858479592554497\\\/BbazLO9L_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/6253282\\\/1497491515\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Thu Aug 15 16:20:05 +0000 2019\",\"id\":1162036247314833408,\"id_str\":\"1162036247314833408\",\"text\":\"#iterating: We recently released a long-requested feature in Twitter Developer Labs: \\n\\n\\ud83d\\udcccDeveloper\\u2019s can now request\\u2026 https:\\\/\\\/t.co\\\/rRlVHaBTs2\",\"truncated\":true,\"entities\":{\"hashtags\":[{\"text\":\"iterating\",\"indices\":[0,10]}],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/rRlVHaBTs2\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/i\\\/web\\\/status\\\/1162036247314833408\",\"display_url\":\"twitter.com\\\/i\\\/web\\\/status\\\/1\\u2026\",\"indices\":[117,140]}]},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/mobile.twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web App\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":2244994945,\"id_str\":\"2244994945\",\"name\":\"Twitter Dev\",\"screen_name\":\"TwitterDev\",\"location\":\"127.0.0.1\",\"description\":\"The voice of Twitter's #DevRel team, and your official source for updates, news, & events about Twitter's API.\\n\\nNeed help? Visit https:\\\/\\\/t.co\\\/DVDf7qKyS9\",\"url\":\"https:\\\/\\\/t.co\\\/3ZX3TNiZCY\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/3ZX3TNiZCY\",\"expanded_url\":\"https:\\\/\\\/developer.twitter.com\\\/en\\\/community\",\"display_url\":\"developer.twitter.com\\\/en\\\/community\",\"indices\":[0,23]}]},\"description\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/DVDf7qKyS9\",\"expanded_url\":\"http:\\\/\\\/twittercommunity.com\",\"display_url\":\"twittercommunity.com\",\"indices\":[129,152]}]}},\"protected\":false,\"followers_count\":507649,\"friends_count\":1808,\"listed_count\":1672,\"created_at\":\"Sat Dec 14 04:35:55 +0000 2013\",\"favourites_count\":2182,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":true,\"statuses_count\":3540,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"FFFFFF\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/880136122604507136\\\/xHrnqf1T_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/880136122604507136\\\/xHrnqf1T_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/2244994945\\\/1498675817\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"FFFFFF\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":false,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":27,\"favorite_count\":95,\"favorited\":false,\"retweeted\":false,\"lang\":\"en\"},\"is_quote_status\":false,\"retweet_count\":27,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"en\"},{\"created_at\":\"Wed Jul 31 19:23:15 +0000 2019\",\"id\":1156646525121916928,\"id_str\":\"1156646525121916928\",\"text\":\"RT @TwitterDev: #iterating: Today we are releasing an update to Twitter Developer Labs, with a few new features we think you\\u2019ll find useful\\u2026\",\"truncated\":false,\"entities\":{\"hashtags\":[{\"text\":\"iterating\",\"indices\":[16,26]}],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"TwitterDev\",\"name\":\"Twitter Dev\",\"id\":2244994945,\"id_str\":\"2244994945\",\"indices\":[3,14]}],\"urls\":[]},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/mobile.twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web App\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":6253282,\"id_str\":\"6253282\",\"name\":\"Twitter API\",\"screen_name\":\"TwitterAPI\",\"location\":\"San Francisco, CA\",\"description\":\"The Real Twitter API. Tweets about API changes, service issues and our Developer Platform. Don't get an answer? It's on my website.\",\"url\":\"https:\\\/\\\/t.co\\\/8IkCzCDr19\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/8IkCzCDr19\",\"expanded_url\":\"https:\\\/\\\/developer.twitter.com\",\"display_url\":\"developer.twitter.com\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":6084394,\"friends_count\":12,\"listed_count\":12763,\"created_at\":\"Wed May 23 06:01:13 +0000 2007\",\"favourites_count\":30,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":true,\"statuses_count\":3680,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/942858479592554497\\\/BbazLO9L_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/942858479592554497\\\/BbazLO9L_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/6253282\\\/1497491515\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Wed Jul 31 19:20:25 +0000 2019\",\"id\":1156645810156650496,\"id_str\":\"1156645810156650496\",\"text\":\"#iterating: Today we are releasing an update to Twitter Developer Labs, with a few new features we think you\\u2019ll fin\\u2026 https:\\\/\\\/t.co\\\/VVp7rv6FIM\",\"truncated\":true,\"entities\":{\"hashtags\":[{\"text\":\"iterating\",\"indices\":[0,10]}],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/VVp7rv6FIM\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/i\\\/web\\\/status\\\/1156645810156650496\",\"display_url\":\"twitter.com\\\/i\\\/web\\\/status\\\/1\\u2026\",\"indices\":[117,140]}]},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/mobile.twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web App\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":2244994945,\"id_str\":\"2244994945\",\"name\":\"Twitter Dev\",\"screen_name\":\"TwitterDev\",\"location\":\"127.0.0.1\",\"description\":\"The voice of Twitter's #DevRel team, and your official source for updates, news, & events about Twitter's API.\\n\\nNeed help? Visit https:\\\/\\\/t.co\\\/DVDf7qKyS9\",\"url\":\"https:\\\/\\\/t.co\\\/3ZX3TNiZCY\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/3ZX3TNiZCY\",\"expanded_url\":\"https:\\\/\\\/developer.twitter.com\\\/en\\\/community\",\"display_url\":\"developer.twitter.com\\\/en\\\/community\",\"indices\":[0,23]}]},\"description\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/DVDf7qKyS9\",\"expanded_url\":\"http:\\\/\\\/twittercommunity.com\",\"display_url\":\"twittercommunity.com\",\"indices\":[129,152]}]}},\"protected\":false,\"followers_count\":507649,\"friends_count\":1808,\"listed_count\":1672,\"created_at\":\"Sat Dec 14 04:35:55 +0000 2013\",\"favourites_count\":2182,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":true,\"statuses_count\":3540,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"FFFFFF\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/880136122604507136\\\/xHrnqf1T_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/880136122604507136\\\/xHrnqf1T_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/2244994945\\\/1498675817\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"FFFFFF\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":false,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":40,\"favorite_count\":105,\"favorited\":false,\"retweeted\":false,\"lang\":\"en\"},\"is_quote_status\":false,\"retweet_count\":40,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"en\"},{\"created_at\":\"Wed Jul 24 15:56:09 +0000 2019\",\"id\":1154057692723519494,\"id_str\":\"1154057692723519494\",\"text\":\"TLS 1.2 reminder: this change will be enacted as of tomorrow, July 25, 2019. Please reference our developer forum p\\u2026 https:\\\/\\\/t.co\\\/8YgCwYoE3q\",\"truncated\":true,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/8YgCwYoE3q\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/i\\\/web\\\/status\\\/1154057692723519494\",\"display_url\":\"twitter.com\\\/i\\\/web\\\/status\\\/1\\u2026\",\"indices\":[117,140]}]},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/mobile.twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web App\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":6253282,\"id_str\":\"6253282\",\"name\":\"Twitter API\",\"screen_name\":\"TwitterAPI\",\"location\":\"San Francisco, CA\",\"description\":\"The Real Twitter API. Tweets about API changes, service issues and our Developer Platform. Don't get an answer? It's on my website.\",\"url\":\"https:\\\/\\\/t.co\\\/8IkCzCDr19\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/8IkCzCDr19\",\"expanded_url\":\"https:\\\/\\\/developer.twitter.com\",\"display_url\":\"developer.twitter.com\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":6084394,\"friends_count\":12,\"listed_count\":12763,\"created_at\":\"Wed May 23 06:01:13 +0000 2007\",\"favourites_count\":30,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":true,\"statuses_count\":3680,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/942858479592554497\\\/BbazLO9L_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/942858479592554497\\\/BbazLO9L_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/6253282\\\/1497491515\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":true,\"quoted_status_id\":1138569964032385025,\"quoted_status_id_str\":\"1138569964032385025\",\"quoted_status\":{\"created_at\":\"Tue Jun 11 22:13:27 +0000 2019\",\"id\":1138569964032385025,\"id_str\":\"1138569964032385025\",\"text\":\"Starting July 15, 2019, all connections to the Twitter API (and all other Twitter domains) will require TLS 1.2. Re\\u2026 https:\\\/\\\/t.co\\\/qMtoumuG1e\",\"truncated\":true,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/qMtoumuG1e\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/i\\\/web\\\/status\\\/1138569964032385025\",\"display_url\":\"twitter.com\\\/i\\\/web\\\/status\\\/1\\u2026\",\"indices\":[117,140]}]},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web Client\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":6253282,\"id_str\":\"6253282\",\"name\":\"Twitter API\",\"screen_name\":\"TwitterAPI\",\"location\":\"San Francisco, CA\",\"description\":\"The Real Twitter API. Tweets about API changes, service issues and our Developer Platform. Don't get an answer? It's on my website.\",\"url\":\"https:\\\/\\\/t.co\\\/8IkCzCDr19\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/8IkCzCDr19\",\"expanded_url\":\"https:\\\/\\\/developer.twitter.com\",\"display_url\":\"developer.twitter.com\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":6084394,\"friends_count\":12,\"listed_count\":12763,\"created_at\":\"Wed May 23 06:01:13 +0000 2007\",\"favourites_count\":30,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":true,\"statuses_count\":3680,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/942858479592554497\\\/BbazLO9L_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/942858479592554497\\\/BbazLO9L_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/6253282\\\/1497491515\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":93,\"favorite_count\":114,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"en\"},\"retweet_count\":113,\"favorite_count\":122,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"en\"},{\"created_at\":\"Wed Jul 17 15:54:45 +0000 2019\",\"id\":1151520624315174912,\"id_str\":\"1151520624315174912\",\"text\":\"RT @TwitterDev: Academic research is some of the most impactful work that happens with the Twitter API. As we plan for the future of our de\\u2026\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"TwitterDev\",\"name\":\"Twitter Dev\",\"id\":2244994945,\"id_str\":\"2244994945\",\"indices\":[3,14]}],\"urls\":[]},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/about.twitter.com\\\/products\\\/tweetdeck\\\" rel=\\\"nofollow\\\"\\u003eTweetDeck\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":6253282,\"id_str\":\"6253282\",\"name\":\"Twitter API\",\"screen_name\":\"TwitterAPI\",\"location\":\"San Francisco, CA\",\"description\":\"The Real Twitter API. Tweets about API changes, service issues and our Developer Platform. Don't get an answer? It's on my website.\",\"url\":\"https:\\\/\\\/t.co\\\/8IkCzCDr19\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/8IkCzCDr19\",\"expanded_url\":\"https:\\\/\\\/developer.twitter.com\",\"display_url\":\"developer.twitter.com\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":6084394,\"friends_count\":12,\"listed_count\":12763,\"created_at\":\"Wed May 23 06:01:13 +0000 2007\",\"favourites_count\":30,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":true,\"statuses_count\":3680,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/942858479592554497\\\/BbazLO9L_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/942858479592554497\\\/BbazLO9L_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/6253282\\\/1497491515\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Wed Jul 17 15:53:43 +0000 2019\",\"id\":1151520361529430016,\"id_str\":\"1151520361529430016\",\"text\":\"Academic research is some of the most impactful work that happens with the Twitter API. As we plan for the future o\\u2026 https:\\\/\\\/t.co\\\/dG3PmGWAJ4\",\"truncated\":true,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/dG3PmGWAJ4\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/i\\\/web\\\/status\\\/1151520361529430016\",\"display_url\":\"twitter.com\\\/i\\\/web\\\/status\\\/1\\u2026\",\"indices\":[117,140]}]},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/mobile.twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web App\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":2244994945,\"id_str\":\"2244994945\",\"name\":\"Twitter Dev\",\"screen_name\":\"TwitterDev\",\"location\":\"127.0.0.1\",\"description\":\"The voice of Twitter's #DevRel team, and your official source for updates, news, & events about Twitter's API.\\n\\nNeed help? Visit https:\\\/\\\/t.co\\\/DVDf7qKyS9\",\"url\":\"https:\\\/\\\/t.co\\\/3ZX3TNiZCY\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/3ZX3TNiZCY\",\"expanded_url\":\"https:\\\/\\\/developer.twitter.com\\\/en\\\/community\",\"display_url\":\"developer.twitter.com\\\/en\\\/community\",\"indices\":[0,23]}]},\"description\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/DVDf7qKyS9\",\"expanded_url\":\"http:\\\/\\\/twittercommunity.com\",\"display_url\":\"twittercommunity.com\",\"indices\":[129,152]}]}},\"protected\":false,\"followers_count\":507649,\"friends_count\":1808,\"listed_count\":1672,\"created_at\":\"Sat Dec 14 04:35:55 +0000 2013\",\"favourites_count\":2182,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":true,\"statuses_count\":3540,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"FFFFFF\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/880136122604507136\\\/xHrnqf1T_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/880136122604507136\\\/xHrnqf1T_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/2244994945\\\/1498675817\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"FFFFFF\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":false,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":423,\"favorite_count\":674,\"favorited\":false,\"retweeted\":false,\"lang\":\"en\"},\"is_quote_status\":false,\"retweet_count\":423,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"en\"},{\"created_at\":\"Mon Jun 24 17:50:46 +0000 2019\",\"id\":1143214899109277697,\"id_str\":\"1143214899109277697\",\"text\":\"We\\u2019ve spoken with all developers who\\u2019ve contacted us to discuss these new rate limits and elevations, and as of tod\\u2026 https:\\\/\\\/t.co\\\/w8WoepBjeU\",\"truncated\":true,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/w8WoepBjeU\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/i\\\/web\\\/status\\\/1143214899109277697\",\"display_url\":\"twitter.com\\\/i\\\/web\\\/status\\\/1\\u2026\",\"indices\":[117,140]}]},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web Client\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":1141392777600806912,\"in_reply_to_status_id_str\":\"1141392777600806912\",\"in_reply_to_user_id\":6253282,\"in_reply_to_user_id_str\":\"6253282\",\"in_reply_to_screen_name\":\"TwitterAPI\",\"user\":{\"id\":6253282,\"id_str\":\"6253282\",\"name\":\"Twitter API\",\"screen_name\":\"TwitterAPI\",\"location\":\"San Francisco, CA\",\"description\":\"The Real Twitter API. Tweets about API changes, service issues and our Developer Platform. Don't get an answer? It's on my website.\",\"url\":\"https:\\\/\\\/t.co\\\/8IkCzCDr19\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/8IkCzCDr19\",\"expanded_url\":\"https:\\\/\\\/developer.twitter.com\",\"display_url\":\"developer.twitter.com\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":6084394,\"friends_count\":12,\"listed_count\":12763,\"created_at\":\"Wed May 23 06:01:13 +0000 2007\",\"favourites_count\":30,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":true,\"statuses_count\":3680,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/942858479592554497\\\/BbazLO9L_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/942858479592554497\\\/BbazLO9L_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/6253282\\\/1497491515\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":37,\"favorite_count\":85,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"en\"},{\"created_at\":\"Wed Jun 19 17:10:18 +0000 2019\",\"id\":1141392777600806912,\"id_str\":\"1141392777600806912\",\"text\":\"Request limit change: today, we're implementing a change to two commonly used Twitter standard API endpoints - user\\u2026 https:\\\/\\\/t.co\\\/ymDvv7r8lB\",\"truncated\":true,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/ymDvv7r8lB\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/i\\\/web\\\/status\\\/1141392777600806912\",\"display_url\":\"twitter.com\\\/i\\\/web\\\/status\\\/1\\u2026\",\"indices\":[117,140]}]},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web Client\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":6253282,\"id_str\":\"6253282\",\"name\":\"Twitter API\",\"screen_name\":\"TwitterAPI\",\"location\":\"San Francisco, CA\",\"description\":\"The Real Twitter API. Tweets about API changes, service issues and our Developer Platform. Don't get an answer? It's on my website.\",\"url\":\"https:\\\/\\\/t.co\\\/8IkCzCDr19\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/8IkCzCDr19\",\"expanded_url\":\"https:\\\/\\\/developer.twitter.com\",\"display_url\":\"developer.twitter.com\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":6084394,\"friends_count\":12,\"listed_count\":12763,\"created_at\":\"Wed May 23 06:01:13 +0000 2007\",\"favourites_count\":30,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":true,\"statuses_count\":3680,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/942858479592554497\\\/BbazLO9L_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/942858479592554497\\\/BbazLO9L_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/6253282\\\/1497491515\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":true,\"quoted_status_id\":1141390793657266176,\"quoted_status_id_str\":\"1141390793657266176\",\"quoted_status\":{\"created_at\":\"Wed Jun 19 17:02:25 +0000 2019\",\"id\":1141390793657266176,\"id_str\":\"1141390793657266176\",\"text\":\"\\u2757\\ufe0fToday, user and mentions timeline request limits go into effect. If you want to learn more about this change, tak\\u2026 https:\\\/\\\/t.co\\\/kFzCKybdkD\",\"truncated\":true,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/kFzCKybdkD\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/i\\\/web\\\/status\\\/1141390793657266176\",\"display_url\":\"twitter.com\\\/i\\\/web\\\/status\\\/1\\u2026\",\"indices\":[117,140]}]},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web Client\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":2244994945,\"id_str\":\"2244994945\",\"name\":\"Twitter Dev\",\"screen_name\":\"TwitterDev\",\"location\":\"127.0.0.1\",\"description\":\"The voice of Twitter's #DevRel team, and your official source for updates, news, & events about Twitter's API.\\n\\nNeed help? Visit https:\\\/\\\/t.co\\\/DVDf7qKyS9\",\"url\":\"https:\\\/\\\/t.co\\\/3ZX3TNiZCY\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/3ZX3TNiZCY\",\"expanded_url\":\"https:\\\/\\\/developer.twitter.com\\\/en\\\/community\",\"display_url\":\"developer.twitter.com\\\/en\\\/community\",\"indices\":[0,23]}]},\"description\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/DVDf7qKyS9\",\"expanded_url\":\"http:\\\/\\\/twittercommunity.com\",\"display_url\":\"twittercommunity.com\",\"indices\":[129,152]}]}},\"protected\":false,\"followers_count\":507649,\"friends_count\":1808,\"listed_count\":1672,\"created_at\":\"Sat Dec 14 04:35:55 +0000 2013\",\"favourites_count\":2182,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":true,\"statuses_count\":3540,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"FFFFFF\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/880136122604507136\\\/xHrnqf1T_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/880136122604507136\\\/xHrnqf1T_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/2244994945\\\/1498675817\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"FFFFFF\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":false,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":true,\"quoted_status_id\":1108050885639168000,\"quoted_status_id_str\":\"1108050885639168000\",\"retweet_count\":19,\"favorite_count\":48,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"en\"},\"retweet_count\":82,\"favorite_count\":89,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"en\"},{\"created_at\":\"Wed Jun 12 17:36:26 +0000 2019\",\"id\":1138862637394137093,\"id_str\":\"1138862637394137093\",\"text\":\"Reminder: only 1\\u20e3 week until the rate limit change to user and mentions timeline endpoints will go into effect. If\\u2026 https:\\\/\\\/t.co\\\/JAUtpAZotb\",\"truncated\":true,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/JAUtpAZotb\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/i\\\/web\\\/status\\\/1138862637394137093\",\"display_url\":\"twitter.com\\\/i\\\/web\\\/status\\\/1\\u2026\",\"indices\":[116,139]}]},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web Client\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":6253282,\"id_str\":\"6253282\",\"name\":\"Twitter API\",\"screen_name\":\"TwitterAPI\",\"location\":\"San Francisco, CA\",\"description\":\"The Real Twitter API. Tweets about API changes, service issues and our Developer Platform. Don't get an answer? It's on my website.\",\"url\":\"https:\\\/\\\/t.co\\\/8IkCzCDr19\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/8IkCzCDr19\",\"expanded_url\":\"https:\\\/\\\/developer.twitter.com\",\"display_url\":\"developer.twitter.com\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":6084394,\"friends_count\":12,\"listed_count\":12763,\"created_at\":\"Wed May 23 06:01:13 +0000 2007\",\"favourites_count\":30,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":true,\"statuses_count\":3680,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/942858479592554497\\\/BbazLO9L_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/942858479592554497\\\/BbazLO9L_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/6253282\\\/1497491515\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":38,\"favorite_count\":62,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"en\"},{\"created_at\":\"Tue Jun 11 22:13:27 +0000 2019\",\"id\":1138569964032385025,\"id_str\":\"1138569964032385025\",\"text\":\"Starting July 15, 2019, all connections to the Twitter API (and all other Twitter domains) will require TLS 1.2. Re\\u2026 https:\\\/\\\/t.co\\\/qMtoumuG1e\",\"truncated\":true,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/qMtoumuG1e\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/i\\\/web\\\/status\\\/1138569964032385025\",\"display_url\":\"twitter.com\\\/i\\\/web\\\/status\\\/1\\u2026\",\"indices\":[117,140]}]},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web Client\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":6253282,\"id_str\":\"6253282\",\"name\":\"Twitter API\",\"screen_name\":\"TwitterAPI\",\"location\":\"San Francisco, CA\",\"description\":\"The Real Twitter API. Tweets about API changes, service issues and our Developer Platform. Don't get an answer? It's on my website.\",\"url\":\"https:\\\/\\\/t.co\\\/8IkCzCDr19\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/8IkCzCDr19\",\"expanded_url\":\"https:\\\/\\\/developer.twitter.com\",\"display_url\":\"developer.twitter.com\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":6084394,\"friends_count\":12,\"listed_count\":12763,\"created_at\":\"Wed May 23 06:01:13 +0000 2007\",\"favourites_count\":30,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":true,\"statuses_count\":3680,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/942858479592554497\\\/BbazLO9L_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/942858479592554497\\\/BbazLO9L_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/6253282\\\/1497491515\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":93,\"favorite_count\":114,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"en\"},{\"created_at\":\"Tue Jun 11 18:00:27 +0000 2019\",\"id\":1138506294485168129,\"id_str\":\"1138506294485168129\",\"text\":\"RT @TwitterDev: \\ud83c\\udfba da-dada-DAH! We\\u2019re introducing the first Twitter Developer Labs endpoints: \\n\\n\\u2728GET\\\/users and GET\\\/tweets \\u2728\\n\\nLabs is now ope\\u2026\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[{\"screen_name\":\"TwitterDev\",\"name\":\"Twitter Dev\",\"id\":2244994945,\"id_str\":\"2244994945\",\"indices\":[3,14]}],\"urls\":[]},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web Client\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":6253282,\"id_str\":\"6253282\",\"name\":\"Twitter API\",\"screen_name\":\"TwitterAPI\",\"location\":\"San Francisco, CA\",\"description\":\"The Real Twitter API. Tweets about API changes, service issues and our Developer Platform. Don't get an answer? It's on my website.\",\"url\":\"https:\\\/\\\/t.co\\\/8IkCzCDr19\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/8IkCzCDr19\",\"expanded_url\":\"https:\\\/\\\/developer.twitter.com\",\"display_url\":\"developer.twitter.com\",\"indices\":[0,23]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":6084394,\"friends_count\":12,\"listed_count\":12763,\"created_at\":\"Wed May 23 06:01:13 +0000 2007\",\"favourites_count\":30,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":false,\"verified\":true,\"statuses_count\":3680,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/942858479592554497\\\/BbazLO9L_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/942858479592554497\\\/BbazLO9L_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/6253282\\\/1497491515\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweeted_status\":{\"created_at\":\"Tue Jun 11 17:59:13 +0000 2019\",\"id\":1138505981460193280,\"id_str\":\"1138505981460193280\",\"text\":\"\\ud83c\\udfba da-dada-DAH! We\\u2019re introducing the first Twitter Developer Labs endpoints: \\n\\n\\u2728GET\\\/users and GET\\\/tweets \\u2728\\n\\nLabs is\\u2026 https:\\\/\\\/t.co\\\/HTpnpwCRMl\",\"truncated\":true,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/HTpnpwCRMl\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/i\\\/web\\\/status\\\/1138505981460193280\",\"display_url\":\"twitter.com\\\/i\\\/web\\\/status\\\/1\\u2026\",\"indices\":[117,140]}]},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web Client\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":2244994945,\"id_str\":\"2244994945\",\"name\":\"Twitter Dev\",\"screen_name\":\"TwitterDev\",\"location\":\"127.0.0.1\",\"description\":\"The voice of Twitter's #DevRel team, and your official source for updates, news, & events about Twitter's API.\\n\\nNeed help? Visit https:\\\/\\\/t.co\\\/DVDf7qKyS9\",\"url\":\"https:\\\/\\\/t.co\\\/3ZX3TNiZCY\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/3ZX3TNiZCY\",\"expanded_url\":\"https:\\\/\\\/developer.twitter.com\\\/en\\\/community\",\"display_url\":\"developer.twitter.com\\\/en\\\/community\",\"indices\":[0,23]}]},\"description\":{\"urls\":[{\"url\":\"https:\\\/\\\/t.co\\\/DVDf7qKyS9\",\"expanded_url\":\"http:\\\/\\\/twittercommunity.com\",\"display_url\":\"twittercommunity.com\",\"indices\":[129,152]}]}},\"protected\":false,\"followers_count\":507649,\"friends_count\":1808,\"listed_count\":1672,\"created_at\":\"Sat Dec 14 04:35:55 +0000 2013\",\"favourites_count\":2182,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":true,\"statuses_count\":3540,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"FFFFFF\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/880136122604507136\\\/xHrnqf1T_normal.jpg\",\"profile_image_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_images\\\/880136122604507136\\\/xHrnqf1T_normal.jpg\",\"profile_banner_url\":\"https:\\\/\\\/pbs.twimg.com\\\/profile_banners\\\/2244994945\\\/1498675817\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"FFFFFF\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":false,\"has_extended_profile\":true,\"default_profile\":false,\"default_profile_image\":false,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"regular\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":105,\"favorite_count\":255,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"en\"},\"is_quote_status\":false,\"retweet_count\":105,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"en\"}]" - } -}] \ No newline at end of file diff --git a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testOauth2Token.json b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testOauth2Token.json deleted file mode 100644 index 82331b599..000000000 --- a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testOauth2Token.json +++ /dev/null @@ -1,46 +0,0 @@ -[{ - "request": { - "method": "POST", - "url": "https:\/\/api.twitter.com\/oauth2\/token", - "headers": { - "Host": "api.twitter.com", - "Accept": "application\/json", - "Authorization": "Basic YXdKZk5ENHpGR2FwR09GS2Zkamc6TGZrbU5TUlBJWHdrUWtaVUI5RE5XU3p4NUxJYWl2U2tuVjRyeG5nb2pKYw==", - "Expect": null - }, - "body": "grant_type=client_credentials" - }, - "response": { - "status": { - "http_version": "2", - "code": "200", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-disposition": "attachment; filename=json.json", - "content-encoding": "gzip", - "content-length": "152", - "content-type": "application\/json;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:31:09 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:31:09 GMT", - "ml": "A", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_NF00blSG9GZe8w8KpZvUDA==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:09 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, guest_id=v1%3A158786106988547101; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:09 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "200 OK", - "strict-transport-security": "max-age=631138519", - "x-connection-hash": "34e2373c53e7f9e0e80fe6af071dd6b8", - "x-content-type-options": "nosniff", - "x-frame-options": "DENY", - "x-response-time": "20", - "x-transaction": "007d4d19009f7a59", - "x-tsa-request-body-time": "0", - "x-twitter-response-tags": "BouncerCompliant", - "x-ua-compatible": "IE=edge,chrome=1", - "x-xss-protection": "0" - }, - "body": "{\"token_type\":\"bearer\",\"access_token\":\"AAAAAAAAAAAAAAAAAAAAAFobAAAAAAAAjPes3FlPiFKh9HaIg%2Fw80waE0s8%3DQqxjhHDgZyjihGIK7olugzbpS0R1Gg8KNhzmer58a6oVbsSGc0\"}" - } -}] \ No newline at end of file diff --git a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testOauth2TokenInvalidate.json b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testOauth2TokenInvalidate.json deleted file mode 100644 index f112d7a5c..000000000 --- a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testOauth2TokenInvalidate.json +++ /dev/null @@ -1,46 +0,0 @@ -[{ - "request": { - "method": "POST", - "url": "https:\/\/api.twitter.com\/oauth2\/invalidate_token", - "headers": { - "Host": "api.twitter.com", - "Accept": "application\/json", - "Authorization": "Basic YXdKZk5ENHpGR2FwR09GS2Zkamc6TGZrbU5TUlBJWHdrUWtaVUI5RE5XU3p4NUxJYWl2U2tuVjRyeG5nb2pKYw==", - "Expect": null - }, - "body": "access_token=AAAAAAAAAAAAAAAAAAAAAFobAAAAAAAAjPes3FlPiFKh9HaIg%2Fw80waE0s8%3DQqxjhHDgZyjihGIK7olugzbpS0R1Gg8KNhzmer58a6oVbsSGc0" - }, - "response": { - "status": { - "http_version": "2", - "code": "200", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-disposition": "attachment; filename=json.json", - "content-encoding": "gzip", - "content-length": "135", - "content-type": "application\/json;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:31:10 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:31:10 GMT", - "ml": "A", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_8Iv+DqoXk8DVAVDoUVltSA==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:10 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, guest_id=v1%3A158786107054950627; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:10 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "200 OK", - "strict-transport-security": "max-age=631138519", - "x-connection-hash": "18b7327592f746230c1c016c344dd14d", - "x-content-type-options": "nosniff", - "x-frame-options": "DENY", - "x-response-time": "19", - "x-transaction": "00c5257f00b7d371", - "x-tsa-request-body-time": "0", - "x-twitter-response-tags": "BouncerCompliant", - "x-ua-compatible": "IE=edge,chrome=1", - "x-xss-protection": "0" - }, - "body": "{\"access_token\":\"AAAAAAAAAAAAAAAAAAAAAFobAAAAAAAAjPes3FlPiFKh9HaIg%2Fw80waE0s8%3DQqxjhHDgZyjihGIK7olugzbpS0R1Gg8KNhzmer58a6oVbsSGc0\"}" - } -}] \ No newline at end of file diff --git a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testOauthAccessTokenTokenException.json b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testOauthAccessTokenTokenException.json deleted file mode 100644 index 791d8387f..000000000 --- a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testOauthAccessTokenTokenException.json +++ /dev/null @@ -1,45 +0,0 @@ -[{ - "request": { - "method": "POST", - "url": "https:\/\/api.twitter.com\/oauth\/access_token", - "headers": { - "Host": "api.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"CE545gAAAAAAABtaAAABcbPlJBQ\", oauth_verifier=\"fake_oauth_verifier\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"0bcdtKs3nffzbE5abwaVjCI1HPw%3D\"", - "Expect": null - } - }, - "response": { - "status": { - "http_version": "2", - "code": "401", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-encoding": "gzip", - "content-length": "93", - "content-security-policy": "default-src 'none'; connect-src 'self'; font-src https:\/\/abs.twimg.com https:\/\/abs-0.twimg.com data:; frame-src 'self' twitter:; img-src https:\/\/abs.twimg.com https:\/\/*.twimg.com https:\/\/pbs.twimg.com data:; media-src 'none'; object-src 'none'; script-src https:\/\/abs.twimg.com https:\/\/abs-0.twimg.com https:\/\/twitter.com https:\/\/mobile.twitter.com; style-src https:\/\/abs.twimg.com https:\/\/abs-0.twimg.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=NVQWGYLXFVWG6Z3JNY%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:31:11 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:31:11 GMT", - "ml": "A", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_n0ZAgT2oLIc0HI23qMIGCA==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:11 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, guest_id=v1%3A158786107147893563; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:11 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "401 Unauthorized", - "strict-transport-security": "max-age=631138519", - "www-authenticate": "OAuth realm=\"https:\/\/api.twitter.com\"", - "x-connection-hash": "90157d4bdfce3a9b90fd408819c767bc", - "x-content-type-options": "nosniff", - "x-frame-options": "SAMEORIGIN", - "x-response-time": "41", - "x-transaction": "0080cead006a758d", - "x-twitter-response-tags": "BouncerCompliant", - "x-ua-compatible": "IE=edge,chrome=1", - "x-xss-protection": "0" - }, - "body": "Error processing your OAuth request: Invalid oauth_verifier parameter" - } -}] \ No newline at end of file diff --git a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testOauthRequestToken.json b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testOauthRequestToken.json deleted file mode 100644 index 479692851..000000000 --- a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testOauthRequestToken.json +++ /dev/null @@ -1,44 +0,0 @@ -[{ - "request": { - "method": "POST", - "url": "https:\/\/api.twitter.com\/oauth\/request_token", - "headers": { - "Host": "api.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_callback=\"https%3A%2F%2Ftwitteroauth.com%2Fcallback.php\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"LR7ZVqY%2Fcdisw1w3zssKI6Yjbls%3D\"", - "Expect": null - } - }, - "response": { - "status": { - "http_version": "2", - "code": "200", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-encoding": "gzip", - "content-length": "127", - "content-security-policy": "default-src 'none'; connect-src 'self'; font-src https:\/\/abs.twimg.com https:\/\/abs-0.twimg.com data:; frame-src 'self' twitter:; img-src https:\/\/abs.twimg.com https:\/\/*.twimg.com https:\/\/pbs.twimg.com data:; media-src 'none'; object-src 'none'; script-src https:\/\/abs.twimg.com https:\/\/abs-0.twimg.com https:\/\/twitter.com https:\/\/mobile.twitter.com; style-src https:\/\/abs.twimg.com https:\/\/abs-0.twimg.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=NVQWGYLXFVWG6Z3JNY%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:31:10 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:31:10 GMT", - "ml": "A", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_mrnWVDThJvkLcAe4hmX0ng==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:10 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, guest_id=v1%3A158786107085601318; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:10 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "200 OK", - "strict-transport-security": "max-age=631138519", - "x-connection-hash": "bf00d267c647790cd34d8cd4a28f9895", - "x-content-type-options": "nosniff", - "x-frame-options": "SAMEORIGIN", - "x-response-time": "24", - "x-transaction": "0095391f006dd965", - "x-twitter-response-tags": "BouncerCompliant", - "x-ua-compatible": "IE=edge,chrome=1", - "x-xss-protection": "0" - }, - "body": "oauth_token=CE545gAAAAAAABtaAAABcbPlJBQ&oauth_token_secret=tTVYBva8AlQu0JxVudzbf9oHXAbIARg5&oauth_callback_confirmed=true" - } -}] \ No newline at end of file diff --git a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testOauthRequestTokenException.json b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testOauthRequestTokenException.json deleted file mode 100644 index 1b91f1862..000000000 --- a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testOauthRequestTokenException.json +++ /dev/null @@ -1,43 +0,0 @@ -[{ - "request": { - "method": "POST", - "url": "https:\/\/api.twitter.com\/oauth\/request_token", - "headers": { - "Host": "api.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"CONSUMER_KEY\", oauth_callback=\"https%3A%2F%2Ftwitteroauth.com%2Fcallback.php\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"wOUt6ZyVGpWnQhsHNWqcr%2BpOWAw%3D\"", - "Expect": null - } - }, - "response": { - "status": { - "http_version": "2", - "code": "401", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-disposition": "attachment; filename=json.json", - "content-encoding": "gzip", - "content-length": "89", - "content-type": "application\/json; charset=utf-8", - "date": "Sun, 26 Apr 2020 00:31:11 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:31:11 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_Vz8Os736+fzUwkQGIeIKuw==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:11 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, guest_id=v1%3A158786107116335546; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:11 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "401 Unauthorized", - "strict-transport-security": "max-age=631138519", - "www-authenticate": "OAuth realm=\"https:\/\/api.twitter.com\", api_error_code=32", - "x-connection-hash": "d620dbb5b35e124662532c3ef8e89c88", - "x-content-type-options": "nosniff", - "x-frame-options": "SAMEORIGIN", - "x-response-time": "6", - "x-transaction": "00bf1248004cdafa", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "0" - }, - "body": "{\"errors\":[{\"code\":32,\"message\":\"Could not authenticate you.\"}]}" - } -}] \ No newline at end of file diff --git a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testPostDirectMessagesEventsNew.json b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testPostDirectMessagesEventsNew.json deleted file mode 100644 index eb71ec872..000000000 --- a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testPostDirectMessagesEventsNew.json +++ /dev/null @@ -1,46 +0,0 @@ -[{ - "request": { - "method": "POST", - "url": "https:\/\/api.twitter.com\/1.1\/direct_messages\/events\/new.json", - "headers": { - "Host": "api.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"3457NqeumGmcalZLF091L9lt7F8%3D\"", - "Expect": null, - "Content-type": "application\/json" - }, - "body": "{\"event\":{\"type\":\"message_create\",\"message_create\":{\"target\":{\"recipient_id\":\"93915746\"},\"message_data\":{\"text\":\"Hello World!\"}}}}" - }, - "response": { - "status": { - "http_version": "2", - "code": "200", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-disposition": "attachment; filename=json.json", - "content-encoding": "gzip", - "content-length": "206", - "content-type": "application\/json;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:31:51 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:31:51 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_Tfqxs0gur2QR4FFIZ3Wq6w==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:51 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786111185015666; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:51 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "200 OK", - "strict-transport-security": "max-age=631138519", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "bb4f30d1c6406b2cd5d25f20fccfdc1a", - "x-content-type-options": "nosniff", - "x-frame-options": "SAMEORIGIN", - "x-response-time": "70", - "x-transaction": "0057fa4c00fb95a1", - "x-tsa-request-body-time": "0", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "0" - }, - "body": "{\"event\":{\"type\":\"message_create\",\"id\":\"1254206523385032714\",\"created_timestamp\":\"1587861111862\",\"message_create\":{\"target\":{\"recipient_id\":\"93915746\"},\"sender_id\":\"93915746\",\"message_data\":{\"text\":\"Hello World!\",\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[]}}}}}" - } -}] \ No newline at end of file diff --git a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testPostFavoritesCreate.json b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testPostFavoritesCreate.json deleted file mode 100644 index a303a6d6d..000000000 --- a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testPostFavoritesCreate.json +++ /dev/null @@ -1,45 +0,0 @@ -[{ - "request": { - "method": "POST", - "url": "https:\/\/api.twitter.com\/1.1\/favorites\/create.json", - "headers": { - "Host": "api.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"EA30eIQPgat0Aw%2F59GyltEiE4Xg%3D\"", - "Expect": null - }, - "body": "id=6242973112" - }, - "response": { - "status": { - "http_version": "2", - "code": "200", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-disposition": "attachment; filename=json.json", - "content-encoding": "gzip", - "content-length": "755", - "content-type": "application\/json;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:31:51 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:31:51 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_Jz87HIDSEIpDevFMBlDD7g==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:51 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786111115490266; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:51 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "200 OK", - "strict-transport-security": "max-age=631138519", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "7368af4d238e5c36df5379afb1bed3af", - "x-content-type-options": "nosniff", - "x-frame-options": "SAMEORIGIN", - "x-response-time": "72", - "x-transaction": "0012beac0086638b", - "x-tsa-request-body-time": "0", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "0" - }, - "body": "{\"created_at\":\"Tue Dec 01 18:38:07 +0000 2009\",\"id\":6242973112,\"id_str\":\"6242973112\",\"text\":\"Test!\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[]},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web Client\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":93915746,\"id_str\":\"93915746\",\"name\":\"OAuth Library Test\",\"screen_name\":\"oauthlibtest\",\"location\":\"\",\"description\":\"\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":58,\"friends_count\":2,\"listed_count\":6,\"created_at\":\"Tue Dec 01 18:37:44 +0000 2009\",\"favourites_count\":1,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":5,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/sticky\\\/default_profile_images\\\/default_profile_normal.png\",\"profile_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/sticky\\\/default_profile_images\\\/default_profile_normal.png\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":true,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":2258,\"favorite_count\":76,\"favorited\":true,\"retweeted\":false,\"lang\":\"en\"}" - } -}] \ No newline at end of file diff --git a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testPostFavoritesDestroy.json b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testPostFavoritesDestroy.json deleted file mode 100644 index 0d0c8785c..000000000 --- a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testPostFavoritesDestroy.json +++ /dev/null @@ -1,45 +0,0 @@ -[{ - "request": { - "method": "POST", - "url": "https:\/\/api.twitter.com\/1.1\/favorites\/destroy.json", - "headers": { - "Host": "api.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"w3Nti04O5BMi8bySXjmO8%2BW5Pus%3D\"", - "Expect": null - }, - "body": "id=6242973112" - }, - "response": { - "status": { - "http_version": "2", - "code": "200", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-disposition": "attachment; filename=json.json", - "content-encoding": "gzip", - "content-length": "753", - "content-type": "application\/json;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:31:51 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:31:51 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_s1J1pMUNrQO4\/v371oE9AQ==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:51 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786111151392082; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:51 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "200 OK", - "strict-transport-security": "max-age=631138519", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "a0dc865f09447e41b0d77e9eed981519", - "x-content-type-options": "nosniff", - "x-frame-options": "SAMEORIGIN", - "x-response-time": "44", - "x-transaction": "005d9083009bd4c9", - "x-tsa-request-body-time": "0", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "0" - }, - "body": "{\"created_at\":\"Tue Dec 01 18:38:07 +0000 2009\",\"id\":6242973112,\"id_str\":\"6242973112\",\"text\":\"Test!\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[]},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web Client\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":93915746,\"id_str\":\"93915746\",\"name\":\"OAuth Library Test\",\"screen_name\":\"oauthlibtest\",\"location\":\"\",\"description\":\"\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":58,\"friends_count\":2,\"listed_count\":6,\"created_at\":\"Tue Dec 01 18:37:44 +0000 2009\",\"favourites_count\":0,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":5,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/sticky\\\/default_profile_images\\\/default_profile_normal.png\",\"profile_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/sticky\\\/default_profile_images\\\/default_profile_normal.png\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":true,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":2258,\"favorite_count\":75,\"favorited\":false,\"retweeted\":false,\"lang\":\"en\"}" - } -}] \ No newline at end of file diff --git a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testPostStatusUpdateWithInvalidMediaThrowsException.json b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testPostStatusUpdateWithInvalidMediaThrowsException.json deleted file mode 100644 index 0637a088a..000000000 --- a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testPostStatusUpdateWithInvalidMediaThrowsException.json +++ /dev/null @@ -1 +0,0 @@ -[] \ No newline at end of file diff --git a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testPostStatusesDestroy.json b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testPostStatusesDestroy.json deleted file mode 100644 index 577c6d51a..000000000 --- a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testPostStatusesDestroy.json +++ /dev/null @@ -1,43 +0,0 @@ -[{ - "request": { - "method": "POST", - "url": "https:\/\/api.twitter.com\/1.1\/statuses\/destroy\/1254206657548226561.json", - "headers": { - "Host": "api.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"kyOKi3x9Ar3foSG5%2BN9XzBbnIOw%3D\"", - "Expect": null - } - }, - "response": { - "status": { - "http_version": "2", - "code": "200", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-disposition": "attachment; filename=json.json", - "content-encoding": "gzip", - "content-length": "804", - "content-type": "application\/json;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:32:24 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:32:24 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_juPKvfSeQeQoZAVeLglnhA==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:24 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786114418847477; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:24 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "200 OK", - "strict-transport-security": "max-age=631138519", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "f4375157b19d6cd139b9917a6d76d0b0", - "x-content-type-options": "nosniff", - "x-frame-options": "SAMEORIGIN", - "x-response-time": "198", - "x-transaction": "00f3e731001ccb87", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "0" - }, - "body": "{\"created_at\":\"Sun Apr 26 00:32:23 +0000 2020\",\"id\":1254206657548226561,\"id_str\":\"1254206657548226561\",\"text\":\"x\\u3053\\u3093\\u306b\\u3061\\u306f\\u4e16\\u754c 1587861062\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[]},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/twitteroauth.com\\\" rel=\\\"nofollow\\\"\\u003eTwitterOAuth dev\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":93915746,\"id_str\":\"93915746\",\"name\":\"OAuth Library Test\",\"screen_name\":\"oauthlibtest\",\"location\":\"\",\"description\":\"\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":58,\"friends_count\":2,\"listed_count\":6,\"created_at\":\"Tue Dec 01 18:37:44 +0000 2009\",\"favourites_count\":0,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":6,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/sticky\\\/default_profile_images\\\/default_profile_normal.png\",\"profile_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/sticky\\\/default_profile_images\\\/default_profile_normal.png\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":true,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":0,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"ja\"}" - } -}] \ No newline at end of file diff --git a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testPostStatusesUpdateUtf8.json b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testPostStatusesUpdateUtf8.json deleted file mode 100644 index 156e1ba0d..000000000 --- a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testPostStatusesUpdateUtf8.json +++ /dev/null @@ -1,45 +0,0 @@ -[{ - "request": { - "method": "POST", - "url": "https:\/\/api.twitter.com\/1.1\/statuses\/update.json", - "headers": { - "Host": "api.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"zIzkM9jxroYElpL1fPTyYnYE%2Bys%3D\"", - "Expect": null - }, - "body": "status=x%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF%E4%B8%96%E7%95%8C%201587861062" - }, - "response": { - "status": { - "http_version": "2", - "code": "200", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-disposition": "attachment; filename=json.json", - "content-encoding": "gzip", - "content-length": "804", - "content-type": "application\/json;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:32:23 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:32:23 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_8nFfK\/V8KyJDl1aminWCQw==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:23 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786114384224672; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:23 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "200 OK", - "strict-transport-security": "max-age=631138519", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "54c0be65e0c80b57d5b7c895e58061c8", - "x-content-type-options": "nosniff", - "x-frame-options": "SAMEORIGIN", - "x-response-time": "55", - "x-transaction": "00eb7dbc0057ef33", - "x-tsa-request-body-time": "0", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "0" - }, - "body": "{\"created_at\":\"Sun Apr 26 00:32:23 +0000 2020\",\"id\":1254206657548226561,\"id_str\":\"1254206657548226561\",\"text\":\"x\\u3053\\u3093\\u306b\\u3061\\u306f\\u4e16\\u754c 1587861062\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[]},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/twitteroauth.com\\\" rel=\\\"nofollow\\\"\\u003eTwitterOAuth dev\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":93915746,\"id_str\":\"93915746\",\"name\":\"OAuth Library Test\",\"screen_name\":\"oauthlibtest\",\"location\":\"\",\"description\":\"\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":58,\"friends_count\":2,\"listed_count\":6,\"created_at\":\"Tue Dec 01 18:37:44 +0000 2009\",\"favourites_count\":0,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":6,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/sticky\\\/default_profile_images\\\/default_profile_normal.png\",\"profile_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/sticky\\\/default_profile_images\\\/default_profile_normal.png\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":true,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":0,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"lang\":\"ja\"}" - } -}] \ No newline at end of file diff --git a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testPostStatusesUpdateWithMedia.json b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testPostStatusesUpdateWithMedia.json deleted file mode 100644 index 97867ada0..000000000 --- a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testPostStatusesUpdateWithMedia.json +++ /dev/null @@ -1,134 +0,0 @@ -[{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"AyX%2FVakyYmVj6PbE3aVfoOnMPAY%3D\"", - "Expect": null - }, - "body": "media=%2F9j%2F4AAQSkZJRgABAQEASABIAAD%2F4gxYSUNDX1BST0ZJTEUAAQEAAAxITGlubwIQAABtbnRyUkdCIFhZWiAHzgACAAkABgAxAABhY3NwTVNGVAAAAABJRUMgc1JHQgAAAAAAAAAAAAAAAAAA9tYAAQAAAADTLUhQICAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABFjcHJ0AAABUAAAADNkZXNjAAABhAAAAGx3dHB0AAAB8AAAABRia3B0AAACBAAAABRyWFlaAAACGAAAABRnWFlaAAACLAAAABRiWFlaAAACQAAAABRkbW5kAAACVAAAAHBkbWRkAAACxAAAAIh2dWVkAAADTAAAAIZ2aWV3AAAD1AAAACRsdW1pAAAD%2BAAAABRtZWFzAAAEDAAAACR0ZWNoAAAEMAAAAAxyVFJDAAAEPAAACAxnVFJDAAAEPAAACAxiVFJDAAAEPAAACAx0ZXh0AAAAAENvcHlyaWdodCAoYykgMTk5OCBIZXdsZXR0LVBhY2thcmQgQ29tcGFueQAAZGVzYwAAAAAAAAASc1JHQiBJRUM2MTk2Ni0yLjEAAAAAAAAAAAAAABJzUkdCIElFQzYxOTY2LTIuMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWFlaIAAAAAAAAPNRAAEAAAABFsxYWVogAAAAAAAAAAAAAAAAAAAAAFhZWiAAAAAAAABvogAAOPUAAAOQWFlaIAAAAAAAAGKZAAC3hQAAGNpYWVogAAAAAAAAJKAAAA%2BEAAC2z2Rlc2MAAAAAAAAAFklFQyBodHRwOi8vd3d3LmllYy5jaAAAAAAAAAAAAAAAFklFQyBodHRwOi8vd3d3LmllYy5jaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABkZXNjAAAAAAAAAC5JRUMgNjE5NjYtMi4xIERlZmF1bHQgUkdCIGNvbG91ciBzcGFjZSAtIHNSR0IAAAAAAAAAAAAAAC5JRUMgNjE5NjYtMi4xIERlZmF1bHQgUkdCIGNvbG91ciBzcGFjZSAtIHNSR0IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZGVzYwAAAAAAAAAsUmVmZXJlbmNlIFZpZXdpbmcgQ29uZGl0aW9uIGluIElFQzYxOTY2LTIuMQAAAAAAAAAAAAAALFJlZmVyZW5jZSBWaWV3aW5nIENvbmRpdGlvbiBpbiBJRUM2MTk2Ni0yLjEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHZpZXcAAAAAABOk%2FgAUXy4AEM8UAAPtzAAEEwsAA1yeAAAAAVhZWiAAAAAAAEwJVgBQAAAAVx%2FnbWVhcwAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAo8AAAACc2lnIAAAAABDUlQgY3VydgAAAAAAAAQAAAAABQAKAA8AFAAZAB4AIwAoAC0AMgA3ADsAQABFAEoATwBUAFkAXgBjAGgAbQByAHcAfACBAIYAiwCQAJUAmgCfAKQAqQCuALIAtwC8AMEAxgDLANAA1QDbAOAA5QDrAPAA9gD7AQEBBwENARMBGQEfASUBKwEyATgBPgFFAUwBUgFZAWABZwFuAXUBfAGDAYsBkgGaAaEBqQGxAbkBwQHJAdEB2QHhAekB8gH6AgMCDAIUAh0CJgIvAjgCQQJLAlQCXQJnAnECegKEAo4CmAKiAqwCtgLBAssC1QLgAusC9QMAAwsDFgMhAy0DOANDA08DWgNmA3IDfgOKA5YDogOuA7oDxwPTA%2BAD7AP5BAYEEwQgBC0EOwRIBFUEYwRxBH4EjASaBKgEtgTEBNME4QTwBP4FDQUcBSsFOgVJBVgFZwV3BYYFlgWmBbUFxQXVBeUF9gYGBhYGJwY3BkgGWQZqBnsGjAadBq8GwAbRBuMG9QcHBxkHKwc9B08HYQd0B4YHmQesB78H0gflB%2FgICwgfCDIIRghaCG4IggiWCKoIvgjSCOcI%2BwkQCSUJOglPCWQJeQmPCaQJugnPCeUJ%2BwoRCicKPQpUCmoKgQqYCq4KxQrcCvMLCwsiCzkLUQtpC4ALmAuwC8gL4Qv5DBIMKgxDDFwMdQyODKcMwAzZDPMNDQ0mDUANWg10DY4NqQ3DDd4N%2BA4TDi4OSQ5kDn8Omw62DtIO7g8JDyUPQQ9eD3oPlg%2BzD88P7BAJECYQQxBhEH4QmxC5ENcQ9RETETERTxFtEYwRqhHJEegSBxImEkUSZBKEEqMSwxLjEwMTIxNDE2MTgxOkE8UT5RQGFCcUSRRqFIsUrRTOFPAVEhU0FVYVeBWbFb0V4BYDFiYWSRZsFo8WshbWFvoXHRdBF2UXiReuF9IX9xgbGEAYZRiKGK8Y1Rj6GSAZRRlrGZEZtxndGgQaKhpRGncanhrFGuwbFBs7G2MbihuyG9ocAhwqHFIcexyjHMwc9R0eHUcdcB2ZHcMd7B4WHkAeah6UHr4e6R8THz4faR%2BUH78f6iAVIEEgbCCYIMQg8CEcIUghdSGhIc4h%2ByInIlUigiKvIt0jCiM4I2YjlCPCI%2FAkHyRNJHwkqyTaJQklOCVoJZclxyX3JicmVyaHJrcm6CcYJ0kneierJ9woDSg%2FKHEooijUKQYpOClrKZ0p0CoCKjUqaCqbKs8rAis2K2krnSvRLAUsOSxuLKIs1y0MLUEtdi2rLeEuFi5MLoIuty7uLyQvWi%2BRL8cv%2FjA1MGwwpDDbMRIxSjGCMbox8jIqMmMymzLUMw0zRjN%2FM7gz8TQrNGU0njTYNRM1TTWHNcI1%2FTY3NnI2rjbpNyQ3YDecN9c4FDhQOIw4yDkFOUI5fzm8Ofk6Njp0OrI67zstO2s7qjvoPCc8ZTykPOM9Ij1hPaE94D4gPmA%2BoD7gPyE%2FYT%2BiP%2BJAI0BkQKZA50EpQWpBrEHuQjBCckK1QvdDOkN9Q8BEA0RHRIpEzkUSRVVFmkXeRiJGZ0arRvBHNUd7R8BIBUhLSJFI10kdSWNJqUnwSjdKfUrESwxLU0uaS%2BJMKkxyTLpNAk1KTZNN3E4lTm5Ot08AT0lPk0%2FdUCdQcVC7UQZRUFGbUeZSMVJ8UsdTE1NfU6pT9lRCVI9U21UoVXVVwlYPVlxWqVb3V0RXklfgWC9YfVjLWRpZaVm4WgdaVlqmWvVbRVuVW%2BVcNVyGXNZdJ114XcleGl5sXr1fD19hX7NgBWBXYKpg%2FGFPYaJh9WJJYpxi8GNDY5dj62RAZJRk6WU9ZZJl52Y9ZpJm6Gc9Z5Nn6Wg%2FaJZo7GlDaZpp8WpIap9q92tPa6dr%2F2xXbK9tCG1gbbluEm5rbsRvHm94b9FwK3CGcOBxOnGVcfByS3KmcwFzXXO4dBR0cHTMdSh1hXXhdj52m3b4d1Z3s3gReG54zHkqeYl553pGeqV7BHtje8J8IXyBfOF9QX2hfgF%2BYn7CfyN%2FhH%2FlgEeAqIEKgWuBzYIwgpKC9INXg7qEHYSAhOOFR4Wrhg6GcobXhzuHn4gEiGmIzokziZmJ%2FopkisqLMIuWi%2FyMY4zKjTGNmI3%2FjmaOzo82j56QBpBukNaRP5GokhGSepLjk02TtpQglIqU9JVflcmWNJaflwqXdZfgmEyYuJkkmZCZ%2FJpomtWbQpuvnByciZz3nWSd0p5Anq6fHZ%2BLn%2FqgaaDYoUehtqImopajBqN2o%2BakVqTHpTilqaYapoum%2Fadup%2BCoUqjEqTepqaocqo%2BrAqt1q%2BmsXKzQrUStuK4trqGvFq%2BLsACwdbDqsWCx1rJLssKzOLOutCW0nLUTtYq2AbZ5tvC3aLfguFm40blKucK6O7q1uy67p7whvJu9Fb2Pvgq%2BhL7%2Fv3q%2F9cBwwOzBZ8Hjwl%2FC28NYw9TEUcTOxUvFyMZGxsPHQce%2FyD3IvMk6ybnKOMq3yzbLtsw1zLXNNc21zjbOts83z7jQOdC60TzRvtI%2F0sHTRNPG1EnUy9VO1dHWVdbY11zX4Nhk2OjZbNnx2nba%2B9uA3AXcit0Q3ZbeHN6i3ynfr%2BA24L3hROHM4lPi2%2BNj4%2Bvkc%2BT85YTmDeaW5x%2Fnqegy6LzpRunQ6lvq5etw6%2Fvshu0R7ZzuKO6070DvzPBY8OXxcvH%2F8ozzGfOn9DT0wvVQ9d72bfb794r4Gfio%2BTj5x%2FpX%2Buf7d%2FwH%2FJj9Kf26%2Fkv%2B3P9t%2F%2F%2F%2F2wBDAAEBAQEBAQEBAQEBAQECAgMCAgICAgQDAwIDBQQFBQUEBAQFBgcGBQUHBgQEBgkGBwgICAgIBQYJCgkICgcICAj%2F2wBDAQEBAQICAgQCAgQIBQQFCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAj%2FwAARCAKqBAADAREAAhEBAxEB%2F8QAHgAAAQQDAQEBAAAAAAAAAAAABQMEBgcCCAkBAAr%2FxABKEAABAwIFAgUBBQYFBAECAgsBAgMRAAQFBhIhMUFRBxMiYXGBCBQykaEjQrHB0fAVUmLh8QkWM3IkF0NTJWOCCnOSsjREGGSi%2F8QAHAEAAgMBAQEBAAAAAAAAAAAAAgMAAQQFBgcI%2F8QANBEAAgICAgICAgEDAwMEAwEBAAECEQMhEjEEQRNRImEyBRRxQoGhUpHBBiOx8BUz4UPx%2F9oADAMBAAIRAxEAPwD9WNu6lCSCgkkjedqd8iMuXFbsLsOiRAMczPAqvkRUoapD9LpHqKZ25IjajFCqnAONgNh81CGJd4iQY2moQSW%2BADCoETG1Qgkt%2BUhXqmetQgzccJGkGT%2FGoQZqeAMglSuJqEMUvlZAI1fHb4qEHKHBweRvJqEHrb4AHpO9QgYtngSFk7c0UOy4ummGrd5Ko0yoTJHanBTmn0SC1dmNRXt0jioV8bDdu%2BUJSFJJVMiDzRJvoGWL2yQNuKkAL268Vco0gHFLYXZWCBIgDqd6kWKb%2Bgo07ISNRVtxxNHwRcWvYTaeIUBBM7UKkloKS9oetqggp3PtRrJ6QA8Q5sDyO4q6T%2FyQUBB3G%2B%2FNXxZD4qB9IVPQCakU2Q%2BB9pgcVfFkPdQJOxJqlFkQkVwCOp2olB9mhtCK1KETE8Cqv6Ac1Q2WsHVzPWlT6FIHurJP%2BnpBmlpW6GJ12MnnATtCeBxTor0EpWDHSlRUkAzP50vIyOSQGdUZWlSimDyaAOEeXYPcdSsKSlRnqO9WxkoKqiMnHDJSVbnmKFuhbi0YeYlKRwT7%2FwB80qTt2UYTqggRPG9XCSXZDwFUkgHtzTFIqxZKyNjPczV0XY6bfKQTGodARxUDjkpaF1PJ22IVPbY1CpU9sXB1EGSn3qB%2FH%2BxdClyAmQn2%2FjUFtU6HrV0CYXJk89qqSbKHjbolSkuED4q0tEUpLoes3IWEpUozUC5t9hBLxSUJkwasCWP2P2nU6QU6o99qjYlxoepXMkbdNzzTIv0ULhckKEAijGwml2Khe8lIB7g71CSyfQqn1FJAKt9ugqMmNNsdtAwTAqEyMdI4Bgg9D9aVJ%2BhQsmNW5mOI6mq3RDMkjcpEjfuKogmoiY0jn9471CCMaTISVAxVBuWqEHNikjieetXHsOLGbpI1kQRz70c17HYwO4SVRBBI7UsCS2xB6EJhPQczxUoclrYJuClRUQTHFJdFRhTsEXKgEhJPTihE8d0R%2B6KRrklI7VCIAXCjKwAZ5qyRSu2R29cO%2FBHas77NsWiMXK9SlmEg1QdkdvXEgbpKwDyeaXk6GwlfZH7koEJSqJ3E0pug2DXHk7gBMe44rOWotjFbgUSZPPbarNDBz7nJBMDp3qn0UDXVmSVTPX3%2BDSAsa2M3ASqTERUHCbiwgEhBKQRSptMtKxuVaUlRCinqPelTWh4gpYIJMiBB%2BtKpkPAvSI9QE9qogoCITuSmN4qEMvUrkDuDNWnRB60VEJmSnpFNhkfQvIgiw6AoEhRPB3oi47iGELCkiN6goKsrSBuJA6TR%2FGw4P6CbCwEJAPsRNVHsW%2FoO2rq0iNJ08GegpxXBBtl0SnkGahFGugy04kiSNKesnmoDcvoK26twJ%2FnNOukR2wkh1O43PtVKaK4McpXPq3AJ2oynGj5S9lAmD%2FCh5FMYvq2I346nirTLirYEuVgDV04HtUY5AC5M7AxzM1YLgRm%2B31agUnjmhataAVIit6kKPp57d6qK0MUr2Rq8CiCFbx%2BtDIZKSaRE7psQdoj2mgAIzdIOsbaY3qEGIT6tRGqTyT7UE3eiC6QNXqIn2%2FpQxiyBm0XCQYkbc9PimkJDZqA0lSAZjT7VAJxsltpAQmUkfTinKVin0SJsiEEpPt80cOzMgsykg6wkqH5bVoclVIsMpR6QEye9PM4oAJ6AcbbxRw7IKGCCFTE9BxTSMwASrUAN5Ik9qhmzrQg4iCICQT0qGeKpDRaABJSomO1HF0HGVGCgADMHpJq4F4hEJI7EA89qYNG5HBMpPMEUMlZUlaoarQlROrb5NJYgYup2V6Ve%2B1QgzcYCtRKSoioQYPNpCdwRzMVCKr2DHQgBSdBMDnrSnBjeaBrwkRBP0oGHYKuFEhXqSRHHeqbogJegBZEg%2FEf80ljYRrYBvFiVAwD3%2FWKoMFuKPq3SOvHNA5olg953SpUqKeuw2H1%2FKlRdOyG37KiQmYidttproJgTlsJsrPvp3M9B%2Fe9UpKxTHodJmNxxzWiLXoQo1%2FIWS6SAFap4G9WE8d9CanydgQk8RUJGKWpCCn4ASFAnqJ4oXNIpRt%2FoQW%2BkEgKOxP1pamxvwjVb4JIBgE9uKcKnGnQ083qlQCu9QE8CjqTqWCZJ%2BtQg4ac4UVQY%2FKoQfNPd%2FwA%2B1SiBhlaZ%2FEDzVphQ%2Fkg2w6JGlenpApsW%2FY%2FkH7V4gEEyT%2BZohPyNdh1hew07Hrt1q0wXkvokFo4okErUqfaiTvTEyl6DbDkgjWQqhfYNBJpQgRHemxkUFG3QYAWsGKqUH2Hy1Q%2BS5J%2FEZHagirIsbHSXCUgaxPTpRK0U4tGfmKImTvxR%2FICZhREbgGfyqRyEMpA2mDROdvRDzWkcbn4qcmQTU4ONUAVTbolia3FcAk%2FWlcmRDVa1aoBB%2BtU5Nh0hk4ohKvwgdaKEfZGrBbqgAPUlInirk1RUVsFXDygqEqEfFKGOKBVwpZB%2FakGDVjFir2DXEp2OsH26VQXxasaLUlIUEGT%2FABpTti%2F8IbKcUCTqgzvRKKGRgqPA9pgc79O9XwQXBCjLskyo%2FETVqKK%2BRLQsHARCOZ7VYLmntjkLQYBSJjmoUnEzU4gqEdu3FQp16FmnVCEyQf41AvlY5S7sk6jNJabAbt2OW3dWwOodp3qcWQesvuJnkyeCaNRVECQUCJB2%2FLelvsg%2BbuUk6SUwI3mnpjYStbHKVjYklQO%2FPSrBnH66CLTkkKjfqBUTMslQQbWkggwT2H9KbFhrj7F0qEGNNEXKnpDhDh3445B3qF44tdj1rZMkg8b1AZtDhIP%2BYgfNJl2LQulQBkECaolGRKjtIjnc1eiGJUSZnao9EEVq4gJNUWv2NVkIOpcFUwOtElqx0arQwdUUpJmCOBPNU5MetK2DS5oMp3B5FCLWT3QwfeEmVKB%2BaknSDjOwQ85zv7mDSGwpSpaA924BsVADnjmpYm3dkeunNleob7b1RQDuXIEaie%2B9XoKMG9kbv3NJUNR9qzyVGuCrsity6TsDIB4FVYYBvHk6VJ1QZkgilXbphw7I1cvlJVpIIidzS5V0NAS7slagtwhRPE8VnCUpf%2FUILfASRqBT0NRBJyehg46FEhJBPYVYxJ%2BxOJCZWTsY6RSH2HjGazEiRJ49jVIaNiozOnUeIis8n9hwYg%2BdJWdSoOx2qDbGpUsrKUkaQTB%2BlQh6lwKBJEjjjr89qTJUyGcyZI2ImJoSCoUQdiUiNhUIOG1jVBO%2F5UUOymrCLSyYhW3z1pxSpBBh5SFgEyOfioX2GWlwASowaLmywmw9vKVeqQBQp10A4ph1i40gSQR12oubBqL0g4wsHSoK4%2FuKYr9gBu3XEJ1emiIFGlqBA1bd5ouTIEWySArUNQ425o09EHIJAAKtuNqByZDMuKPfsSaJSZGM31CSCYTv1o0yAd8E7K9R6%2B1WQC3ZATpkjnaaCbohGbs6yVkjWAJ3qktaBUERm9jVKikRsYMxUx9FXuiM3ISFKHJmTNXNBkZuwCpRO%2B8ilEI7cNgymVJ9Q561CAlxrdUa4%2FPrVWQzaJ1Eqgke3H0qpX0iBa32MJEQdgaJJrshIrWZClEH55qEJRYzpBEFM8kbGmwQmSXolDOo6d%2Bm5o46ZncH6DLI2RCykA89Ip9ewWgwhUpSuSPmtIHBCwhXO08QKtOuhbW9C2kg8ncGT3o4ybZR8U6dpgcUwy5nY3WmEkkQI4qGdS3QyVqE7gke1QIbqlQPAPST%2BlEnRabXQkvRHr2EzttTYuw1k1sQWqSPWT81dBxlYitKuxI9jwaRLsS%2Bxovg8z7CqKGbo2UCoTztUIMnW0gH17DfioRAl4EAmT%2BXH5VCAp9My2lRA6UMooOMn0BbhJG4IUmeI4pDVjQQ%2Fqg6laenNIfYXNkduUErjfuJ3PxVONjYytAS6KtUgwBuYpMoUHFWB31q0LJJSrmJ5qhyRua0rYEA81rxaVGXih62vZtUjZXFMSBlH6HCHo2MJFEm10Lo9Lv4kzAnmatzYSlQ2LvqOwSQI7VfNhcU%2BxEr1GRExvvQEqhNawrcaj33q49k%2BRsSLoAKiNPua0Myym5CKl6dp25qgT1KzpT6gAf0qEF21wCkAaeeetQg%2FYUqR6UjeY9qKLLTpNBZhYmPfYDpQlBxhxQBWlJIn4q4umWnTsN27hkbxG8jtTwp0SS2eUQSQkcb1BDjsMMO6QNykdN5g1Ycseg00sL0lIJ9%2BtUStBhp3bcA%2B4oovYmt0EGXYOrTJ%2BacV6seoWFgA6QPf%2BVKaoOMqHCFEAgBHfniqbYanehwlwQVFH68VSYDx6Fkr2OqRP1iiSQLRl5gmBMmjtFGGskAFEHehlL6IJqWlIgwB%2FChbZdbobl1ZCtOyR2qrDdIRUtKSQQCaJQBbsYOLAI%2FzdhTR1JA51RIJ0FRPNZyk0CXidW%2Fp3g9zUCSvQLuVHUSADG9QZlfoYK1DVqTG351C4xpUxmtUq2ERt8VGHY0W4DKfLUE8SN%2BtQS8hilSgVA%2Bkjf4qA8n9i2r0%2BkEEn5iKhcnEXQSlSSFEHuBINQGPEcIUDxEfTeoNWNCgO6gQOT7QKhXxo9SsApiQrrFXQahQ4S4PSIKiOOkVApJdMVQqYWCQTzvNCsiRnmqdIfNup3MK1AdqVF0XDtD1NwTA%2FD36U5faI4%2FQ8bc1Ef5uZioDQ%2FZe8shKz1qDI%2FxoKtvl2ZIkfrViuKu2EWXlbGT0n2qCpV6CKSJ702LskJUxdAVIIhXxRDPkQRaWVDSADHWqbAckxxqWRBIPvFTiTS2eoKogEERuKGVEtXs98wyQUgjvNTiU4r7EVvBGoqP5VOCIoMSD4hM8mfao4E4MTde1CUiRM1SgHFNdgh5zWowTp4iqn2HKTY3dWlKff3oLHQWgHcOAFQTBnkxzUoOl0DXXIBJMf0pMqMzSvQAvHkoE7R%2Fe1CQi1zeJOr1QQOZ%2FSoSgFdX6Ep1GFbdKjdbGQTWyH3eIpAWpSk89%2F0pFmjlZG3cQCwdKoV37%2B1LnGxsX9kdxC9SnUAJEbkkbUPxjYyshl5izaVqBX%2BEf5tqVkSH9K0RteLpLhgg77RSLFrL9nr2LpShISpJVsJ4Iqw1lPra%2BbdTqWoH2qDIux8bpGkRCT0ilzXsdGNCPnk6iRPWY4oGy7ES5JlKwoe38qTkhZSd9iS1RBKhIMGRSadj8fQyUr1GRG8zPTtFGGe%2BYqSSDE71KXsh6hwSQAk77E9KVNJPRBcK%2Bu%2FSP50FEF2%2FXBjcHfbirpog%2FaWEnbZJP5mj%2BQr4%2FwBBJtQVAkA8wanyfoLg0E2XgABM%2FIo0yqfsKMOwUxv9aJV7AcfaDLDipAUT7Vf4gtfXZIbZ0CEkwKZJpIFxoNMOARKoH50tSaL5aoMMuat%2F3pn4o4ysEIsrPGkHbfanRlRB4FEcp68UfJEFgqek9o70q3ZBi8qSr0pQePmjjP7ICXiQdt%2B21HyRAPdkFMFJ1RtuJNBkIRm6UVK7Cd460SjSIR69MFQSN56bVUOgK2Rm9VBIIPQGKBSoN9EZuidRMEHfpQsq2BLjaTExvseKGn9lgdwySmCZ2mN6jxPsYsfs9Qj1BISCo7zEzVwg0DKFKwlbSTukT360dNIihZIbVInUQT2mhTLeN%2FZKbMEhMg8dd6emZuLJJbErRACo6id6tdipv1QcaCtCQSdPUk8U9i2qQabPoCimFSNq0gtXodJ1FQ2JERvUFyikLBIB0gfPtT10LZ8UgADY9x0q2c9JCBbhMbSDJqDMfY0cb5OxPNQGMHQ0W2QSkDSNyBFQpDdZUNtIUmmQSYcEmtjRSQR6QY%2FjTBiVGBB4ISKXKPsk3oaqTJA0jYRud6WIGykpIOqVHrvxUIM1pTCoC9PEd6hAW6lOoxpmDwYqEBVwITICSQajImBnhsT6B3BoHCKGKbAFyhMqBSVjYxSJq%2BhiANygAKEBPMe1Kj9hQdEfukOLIVqWBOwA2H%2FNXNWPjJEffbSVGVKkEnbpSZNJ9B%2FIzcZm4A9IMe4p8GgZQQQSuDIImN6ZYEVoUQsTpMR2jmrJxMS5JI1HsIqmweKG63QDOv6RVckFpCPngKJUo%2B221EU2mJKeTvpVvMQDtUKcV6Ei4epjbY0XJiVjX0eqcmRqST7f1o4z%2BypYv9j5Ko0atUdd6YzPyQ6Q5uJ1ajvzVBJj23XCkkqJTtVx7Iu9hhlR2EgfrFFOvQUq9Bu2JMcnfeRQAhhhzVuD7RT437L2yQWzxTsZHeasik10H0LBAOokDpUGZFoM2q9CSAqPrAqzNKX0FWF7J6b95qhYSZcSQmTAo4y%2ByVQ7bdIiSAaKUkQeIfkBJiCJI96ppei06FAtvospI5ih4hqYoFBO4cUPipxJ8h6CQZU4UkiqaK5J9nhO26zyeO1UTkl0ea0JUQDMgdatE5sRW9AgK0imRgC3Y2W4YgAk8VfF32MjD2MlOK3SqBvHO9DJteySX2xB5xKSSTG%2B1LfYG70ClqB1yTv71DVjW7A7hOvXpnckb1Bd%2Bxqok7QlIA%2Bag6MrWwc5rk7AH5q0yThyQ0XJSnSogdYqGWON2YhJJMAT16VQ3ixZtKkyDA%2BDUJ8Vi8hQKZAE%2FnUCWH9iqVEK%2FEo7SPmoNSSWjNKtGqVHTNQiMQ6PUZg%2B4NJaaM1P2ZpdhQKYPcxVWEpNdMWadKgACrjb2NUUPEu9QZqJEHrdwlMBR1fSmWy1JrodoWCroBTCh82%2FyBAHSoQKMPKC9Klb%2FNQJflphVDitQIUlQ6TzUBlCtBNhxZKdR9PeeaOLFSiE21xBJnvNNTBUb6HzbkfvATyKGSfoJY2Kl3bcfmaKguFexQHiSY96rsq09DB68bC9AWB89KskENn71sIWUuJEdOajl6GAc4rCk%2BpAHaglJoh89i0IgLSDwZNBzZBiq%2BDi1ftB%2BdU3fYz4xk%2FetpUoeZJ4MniqGJaoCv4gI9K079KXMCcqegc5foAMkJMbyaByYpKyG4zjLTesF5Ox78mqIiurnMjafMBeQkgnYdKrkhuOFaTIdfZtYUhyLiUDseKGTVGpQdFd4lnNtTgQHgd%2FmlFxSXsTazOkoSS4kah%2B9tHvVS60MUN7INj2dmGWntL6iSd5pX5eg2q%2FiVd%2F3ul5bqfPRBHeg4odCHR6vNbSLdTheVPSD0oJY7GLE6BaM5odWEedpk9TVPH%2By1jf2SmwzEw4n0uIme9LYStB1nHm1oAC9J%2BeajRTyfYRt8W8wg6wJgf70Dh9FRduwk3d6oBJj55oXEcKOPBQO4ieppEosbj6ECoqEqVqFA9dhmIMyd%2BaX8iIKpUoQAoKMz229qlxfZBYKmPUBzE0tNkF21hJkKIJPXirtkHSFAqG%2FwDtVB82PWnEg7bCJHSpbAe%2BwihYJ1H0xtt%2FGmqSS2UkFmHjqKdXsJHNGWF2Hdh6kTPTeoQPMuSlCkmDM81CmrJBbOKXCpAG3WapKhUlT0G2HBqAMBPeiUmugQihZWFer8qcnZTaQ9bd2HqST79fmmRSrZZn5kH8R223%2FpQsg2WokFWoT89KogPfUClQCt471dPsqV%2BgLcGSqVkdZ3qN%2FYFyI5dFIBlZA496vmxiRGruCTue%2B1WrrRKIvfrA2KvSeKAlv0BX4KVKI1KM%2FWhn1o0NIBOklRnUOeelLt%2BgOCGSgFLSZSUzO1U02XyR62FH0mSJniJqqAnL0h6ykegHbf8AKijdkhIPWyZWnaekxTipTfolFsggSSdqKLpmdTJFatylIMgHp2FOUipOySWyE6UJnaDsTUv6EzUfQSaBHBj57VtjfsAfNpB9IJ368UYqdjoJPqAG55NNhfsyZ5tdGBbUOlMZmTXoTU0BOyk9d6ojVjVbR5kSegqwoSUdUNFoMkagSBwDVBS4ehk42ASklMmrToBOuhq5pnUHNJjiYmmxb9joNvsQUBJJB0%2Fxogv8jJxJUTySNxtyaRJbENUNHCDA4I6%2B9UUxo7q3KnJ%2BtO0NqANeIKtiR0BpVClbBrsqB9W4nptVEoCvggzqHbiRS5vdDYx1vsCPiVKggn2pY2NXsBXidKTpEL9zFUkl0McEAHxCFAnc7R0NVPomkwDctrC1LHM8CkOCZdfs2tadIkBCUmJ2E7VdM0Wh4249BGgT0M0SlQD4jjzST6ht04Iq3kfomhop1U6gVzPBHNVyYaSERcKXrCyOOZqqYqaQk47JTwTsSYpy6EuAmp08wCO8b1YUVRiHCZE781C5OjJKudwonb4qMDsdIUTCQN%2BOOPenRlZXxIcNlPpBTJidqITkxtbXQRaUR0gAdKlilt0F2CrnaKKSp0FKNBm3VMhQG%2B%2F0oQQywVJIGwSTuR0pykgozoNW0kpSoyBtFE2gSRsrmNUHtFC5ByyJqgkw4QCkJSkg8g0QvNFIKtPRBMEk7CKglJsetvpBUnSEjrG8VYfAftvpXJghMVGDKNDpKtJkRHsKiYIsFjiRHYmm80Qz85Q%2FyH2oZUgk9noePKk%2BoHaIobX0MaXs8Dyz1KD24mpa%2BgG19CZc3nVFS19EtfRipYHA296OM77AE1K3JO2%2B1U5l2xFxQTtIE9hsaWWk2MH3QUkJBCie3FWFGNdjDdWsnbjeqHwkktg53beIB2G9QGUadDOCnaFHpECoXF0xBwHY6U9uZqD7Gi0GSUEzG4AqCpS3owGpIIlRI3kioXzRkkBQMyodieKgZmdgr0mek8CoQzSSJHpkck1CGJkhXqAqEElKI2BVPWlSlYlzswLm%2FGk9SDQAizbpOkpMpjvxUIPGnd5MjeKhB8hSVCIAPuKLkyBBDgWYUJ96imyDlC1JJEAT%2Fc0yL0QKtrSsbJIcniiBkwmy6qAHBHQGOKg6E1VBdl0pH4eDtUEOFhNpXmImRPxFMhL0Uvx2Pkq07Rud6YEpWZuu7CDBjrUC%2FwAibt0G2VqWYgHjrULX6KqxXNTdrcrCnAJ2oeSBSSBVznBhLIUpwAH3ihlLdlkXczoyCFB1AOoxBBmqlKxsFqxre59YDik%2BakxCaAZYuc7WrLAX5qSY2GrioXxYF%2F77ZefCQ%2BgFXHqpcpMS22%2BKHruZWwlBC5E778UDk32R4ZohWNZ8YtlL%2FboA454qg4Qa2ylcweJaFl7Q%2BkgciagEZJuyocV8RwjzdNwkA7D1c1DT8TeyC3via2EKT50kgqPEE0Eq6odwfsrQ%2BJKXLhZU4g6Vbgn9aXwkX8Zlc%2BKqUNa0up0gH%2B%2FrtU4v6HKGrKfzh4qq%2B7Oj7wkubCNQ2p%2BOK9gkKyz4hKxC6dStYgCdzyKTkjH0OxNtklu89esthz9nEfi477CkxijS7B9nnFSnnCHwtMEkmrcEKkmiZ4LnRSCUKWkjeCOBtQ%2FGVZOrLNi1gqDpSkGOOaX8VeiJk6wfM6XVJCnDq%2FKKXONMvluyd2eMhw6gtJEcTS3XsPmE03wXqUFFHP4h%2BdA6odjmuh%2Bi6OhB3EcmsuWIy0EG3CqFbk8d5pEo0ixUrCSNQSAeT1pdhKLMg4d9wY4qyOLXYshyeZ6%2F2KgIul0pCQQk7ztUIO2XNSdtwZ2%2FrUIFWVg6SQIFQgQZXJBTpCjE0%2BPQfDVhhlcEeoAjrPFWDT%2Bg3auwUKIBJ2J71CiQWjqgeRoj8qgLx%2Bw9brhXSKJV7FJ0FmnQZB9In86ZzSDSTHaVkK2naeRVfIBJUZeZAjcD5q%2BaBsTW50j8zRJ30RAu4eEEbGiUtUWCLl4JKydyek70DRCO3KgSSCImNxxVltkevYJJSAB8VG3RRFMSWS4kEQZ4oFyLjGwW6oDYpM%2FwoZt9DUmvYFdMq33UOtDF0ENdCVEHpxFE8rK4oySkCU6E%2FrVRm0A4fQSt0JJCtSe4IFF8jKcA7asRpiNHIP8AfWmIXJkjtBAQSACdqNJMFxSJPZoO6CkqP8aYlQqRIGQQkzqJmZA5o4qzOEmwYJHYT1rT8hB%2BhuSk6Cnbf3o4ytWKm%2FQ%2F0ggTB9z0rTHoRkk0fBG3qlJ4PvtVsyN2JLZA6AE781ChopColSTFQg2dZmfTJjf2qEGDrMSVAHrIqEGjjQVsYHsDTFMNTGa2wBK9UR2q1OwlPdDJ5IAWI9AAj2%2F2oZg5Owa6AZA5M0AA0dE6gCeJIHNQgHdIHUEx1qETfoGPObKSkiB77VGEpL2gZcFMwZn%2B96VJNjo76BD3UwBuNqHiwlF2BrkBUyUp2mOlUNsAPI3VyR0J7VTQuSXYEumySqEzJ46cUlrYcWzZZtyDBVqI5p5odIdNvKSIKjz3mKCULYDaa0OfOQJ%2Fdnnp%2BVLkqAEFvk6QUyobD3FXw9suxuVnfcgdelM5oobKUE%2BoFXPHel229EEVPKmdyJimOJDxDqQANSR36Cooi3j%2FAGOErhXJ4ogE6HiCNAPJMUS09Bc2O2TpgEwCZI96ahcsz6CVuZ3gGOnerEBa2OqCConv2qMjYbttoEE9fpUIGmVJ5MgdqhAw07BA9RBp3FMObVaDVu7KQPMJ5G4FS%2FtC6%2BgmhQIJBG8bVFJDcjTHjbp4UN%2Fc0dCwk0vUB6t%2B5FQjytKh6l4oKdOlInffmqBi3LseJfQEhWvc7c81BfFmZfgbmB%2BpqBRj9nouEaUnZSjvA4q7JwFvOQdgZHzUBkjEugGQARO1UCfFwCQTHx3qFpCC7lKFHdKj09qgfxiSrrYFIM%2B5qE4DVbilk%2F5e3aoMoRKzB2UepkxULUbMVysQfWOxjaoX8bGRAJUANMe3FQGWuxqtEEKCiEnaO1QFS%2BhsswSTsekdKg%2BM77Ei2CYUd9%2Bn86gVJiZBSIExzt1qASh9H2kkEHUI3ioXijXZ5POpRVHQxtUCSowkg7kxH5VCxMqIEr2HNU2kVyXsbrUlBIO3WTSBCG6ngVECQofp8VCCiVhRBEpneoQdtuEySY7gGoQfsulMg7%2FHFQgRac3AJ3HbvUIEm1ApGqZ5J7VabJ7of2q1FSoUDHQ9RTwMgTS6UKSTunn6VAooLoUlSdUmdjzzUCk9hO2eSlOnfT170SYmV9iwvEJcCJAP8qNSbK4sQv8AFGWEIKlFInvxVOYawv2Q%2FGsysNYdcu6xASevWhsbCPFmn2b8%2BBeNqYZcJbSAr5NC2CV9j%2FiX92ZcT54CUpMQZiqTQ1yiVkvxlYCFu%2FekrIkKBP4asYov0RK%2B8abdKws3iTAC4SqajQXxsYYn492zdqAborVAEHb60EYy9sJY01sVyr4yM394gfegVzsOJHf4qpoqOKi1MV8WmbRjUu6CFBBMatp70Few%2BTa2jW%2FOXjdKiGrtRVEkhexFUt9C1jt2imXfGH72lYVd%2BszCSrdR4q6YSxr0Vzj3iU6h1tsXJDhSSCVRPtUTSexsFb0VxjPiY8kuMm7V5gG4G4%2FvahlJN6RshjK3f8XmLe5XbM3YN0pWkJUqYHXjiglJskor2xRXiW6LVx526cCUmEjp3pSnZElWin8yeJa7vzm03JUHOY6VpWWKXQrg7r0Hcr50etGgVvoSVp1EahKR71nypS%2FRoUqLEwzOv%2BIOlpbyUxG5MaQTzUjCloZCZLFXrrS3G0rWREyf3v7moFKVdh3B8RfbQlalKcEbmf13qCpJFmYXjWhhBU4ErI3jp81TkkUkydYfjbjR0l0FcyT2ikSabKLIwXHfMbQQ6TPAnms08fsZSZYdpiYlClQkkSJ6UtwL4Egsr5TjiDrOk8QJg0qa0HCF6JUw%2BNElRUBP5VkcWzUo%2Bj5TqyTqcjvttFVxY1KtC7S42Kt%2BhH86FoqfQ582AEzqPMnvUEiqHBySByPrUSvsg%2BZdMeqSCdux71bjXRdBJDgSRuQP41RGE2nNIBUQJ434qNstSoJsPAFMrO9XGbC5hu2d9QJKiCeKanYtIP27%2BkQR6uh6URbi62HLe4BiSkDqZqCJRoJtP%2Bo%2BqJ61Ckx8h6AAFmTvUGqnsWDvRR%2FM7VEXSMX30pBAXtxMVb10DOugO%2B6CZBjoPmmRYoE3C9UwSZ2iibS7GY17YHeUgHYhU7UHyFOABulp9RJJHeKvl7opRIhduSsEkd%2FignmYcY07AN1ewTBH0AoFK9hgV26khKFao5ParIZta1D1FXSoJlJ9DtKYOoaZM8%2F37VA4Bi3Sk6VnSDzHJNXHsufQetW5AUQrmR1mtCFuK%2BySWiCVoE6RwY%2BKZGNCZTJPbBWvWSSrmO1GC2qDKEkwk77UcDKEm0qA2EUxkCrQMJBkTxWlK%2BhM1seJa6Kkp6AdfitBnzp%2BhYNcgK0%2FG81DKYqZKRATJ6fFFGvYUWr2Nl26Z3BM7%2FFW4%2FRbjbtDNxmCfSsmPoaFoFquxi63PcTFUUMbhkkKKFrIiRttTU0W6pDMpVsFCB7HmpKSrRQweZ6pE%2FyqoyXsKKbdgl9oQRuCdz%2FtQyVMpprsGvCQTJHWKEoCOgeqDojp0qEBDpI1Akkzx14oJXehkXH2CnlkbaieaHmxsZL0gW6uACkqFByYfyAe4dJJSSJ6cVSdgydgZ1adRMkCKstSSQJuQF7QoEb7GkS7GRyI2GQkAEhWkEdetLhk2aWhRK1mTKSPmtHMCSVCxdKYHqIjtImpzQtJsZKuFavSrft1NA7fQ1RVbE%2FMVuQUDvJqcJfROKEi6pRJUEwdxO9Go0BNUIKcHCVAVUpNApGTbvq2hSifmq%2BRkHaHJPpgD9P%2BaZF6BaQ%2FbXJP4SaJOiwiwRIJgj86ZGVujJlW7CbZjSZB7HvRsSmmFrQpSPxSqNhULDTJIBCiopPO1QgXZJUB9ahAwwR6TyB7bVdkCrC0CEyNjPHWo2QKNLICZiOQaog%2BQqQJEjpNXbIOkQdyZ6iaJZGRWO0umAET1%2BtT5H7CU2vYslYIT6vfir%2BQF23bFgsGSCJ%2Bear5GQ%2B1EDYz7Daj5Ih9qWRMpA%2BdqnNEMm3lSsFW89OtEn9ATYn94WCYMH%2BFSwqR8FmCVQkGPrVWi0t0eBYJI2T9eRVhqFtr6PFLTzE9eeKhfBezArSiBPf6VA3JJCTiwpKiDqEjpFQFZF9Dcr07pCYPWagmhu4sqMFU7TFQiQiQFSkkmfeahZ9p1AgcfH61B0P4o88uCI0jqIqBGBSUygahPc8ioQxWkSqFJJnrUINlbEwQD3jaoQarJhWogn5%2FSgmtWJyfyGq1KVq3A3ncUoGxqpUKMxERP1q%2BL7CUG1Z8hxPIUYG24qgRw26YkkARwKhB%2B08qCDEn2qECbb8kAgTERPNFFWyD9p1UjTpA4MbTRuKRS07CbLpCgtKoM7%2B1HyT6JJWFWnyolJI3jftUC4tIWN993keYmAJjmoA6EWcwtpK0a0zxM0VjIwddWB7zNLSLpQ89IA4giPrVqYMlK1orDxA8TbXDrVrVcthWqDBpbf0NyxajRrPnXx2s2sMumU3aZAVI1f71XL7CxtRVs0cxnx6tUYlduuXSZKTEq3iicb9l48Um9IqLM%2FjQb%2ByuHE3cKA3AVHt%2BVL1E1x8STe%2BzXnE%2FGZ6xQUvXTKE9T5m8bdqvmg%2F7dp0iDX3jS7cXOpVyQyU7Aqn6%2B1Klnp0Ph4za0CXfFUveTovAt9Qn1LgnpRRy2HPxaVksyT4tu4Xeh9%2B6W2mdpVM1eWaS0BCNrssHNvji%2B5ahxq4Tp2BPmbR2pSnFrYLxtlLYp4jv3gKnn0FtRJMKOw6dfegedRVJhQwO6QFdz6xY2iHnnwq53CRPUfx2msk%2FJkumaY%2BN9ldZg8UEPOJAughaiU7GQlIHIoVkkv5AvDFfxK3x7xQLCW2xcErLZSoD%2Bv1pkfJS6Isb9Fe5PzIrGMfN1du%2BQC56lGQCkHtR4%2FITkKyeO07Zei75p1GJoU5pQjZsE8J7wf41qyvWkRLVFLKxcrxW7K0rSkToVx87GkFj61zGtTiUtuaFEckkAjtVN12WkXXk%2FFHnlMwUwCFq5%2FKaqOVVoL45JmyFjiDd1bpc1pOkATG5%2BtI%2FuN0NtEmwW4S6hWso0glM7RHSmRy2VZLrH0KUAQ2BE%2B9FKNiFk92SdF8UBsBwpSTE8TSXGpDoytWWDgN%2BpRt5VI5VB4%2BlVPoInzGNpDo0nTHyf%2BaT3ojZNsExZLzqla088g%2FyrLlfEdiV9FksXiS3pK%2F1PFZeTXfQy66HLNylxRgyme%2FFE5ojjJsf%2FeEjVqIA6DiaVJp7DSrs%2BbeCiQkJSeknpVWXyQ9acBgSCneRztUAlGgi0TpG5kdhztUsAJNOfugjTO2%2B351A4xseIeAIG3PQ71AvjQSZeSVACINQr4w9bOhQTwkdfaqWglBrsM2zwEJA6SREz%2FtToOwgwh0EJIWDG%2FejFyh9D5u%2BKVaZCiOnb%2B96gt4n2EEXaSAdRT79qgPGRmu%2FATsoKPtUFOLvoZLviYCQB0O9QtQvsaKeWoSo%2B%2FtVp1sYo1tDV55ImCOdgOtMmtEk09J7A9xctoCllwJ6880otKiD4tmBi3DpK0Ij%2FVuap5KVEWN3yK9dx5q4ccc1kpJMDUBNDyTLQDF8q4d2CkJO46dP4Uuy6YStCpa4CJVEewFMjKyg20CYCietGQcpbnoASZg7EfBqEClpqmISDM7fzoo92KnK9EltUwBIiOZ5FPVAElswAUq2VBjmmxdipQaJFbglSYiQf50TTBokTLIURJEz1O1NjClYpwSVhFpKNypM7yOsU%2BEb2LCbTRHq0wrtTGLyBNpsJTsEADiTvT10KkL%2BVqO0R2G81ZjyvZ6beQNwkz8VALG67cGAQdXv%2FCjjIOM2tDNxjeRKpn3pr2Pe%2FQwdZCeRz%2BlBwQpxSXQMcQPUdA0%2B55olGgVNL0MnGgrUnZEddPFWHSktA91lQUpJAInbfmoiJJdg19pW5CZ24mkydlSknqIDum1pPpTI96KMLQpprsAXaVer0gDaBVSjQcoJAW4Qd4jegApsD3Q3ABCTxxsahSVAd6B%2BEzOwjmhljXdjoyb0CLhOxBgDn4pfH9hgp8jY6d%2Feo467ID3AoyIBKv0FKcPZC8UrWdxKgJ60jkjoGfm7jWnVOw3496GW1ohmXkgqCdIkQPmiiqQri0JKdBUIKlbVbYO0N1uIKvw79ievxVhKTEfNhQ5UZ232ouT%2BySv2NlOkH1gkR16VTdieH0ZNvBR0khJJg9RUj2Guh%2Bh3cAQn3p6QEk2EmlqgbyZ2moC41tBRhRCgk6Zj34ooxb6KlIMW%2FEAq9qezKFLeEkqhUdKogaZ3A9EHvtUIF2FkAatUdKhAnbkEAa%2BffcVCBVpUCRCqhAihfpA43BqEHiHh%2BGTI4qEHSXRumRJFQg5CwTtJBioQU84fhOnbpHFQh8p3YAqO08VCGfngkCVJPSahDMXA3CufaoQ8S%2FuSNiR0ooyaAmj4OwpRSY9u9W5sJHynVAJ0lST1k1cGl2WIFSjqk80fJEoz8xROogxxV2iUYyqYUSkE8jpVckQy1KIglcdjRLZBIwswoGepjmqIYckzISDFQh8BqIAkmoQwMxtpB96hEeA7wokngVAnL9nsAHv03qDV0JrTP4tPcVGyxqsgDYEK6iq5ID5EDlSNQIAHMxS5PYEpWxotQSJkke9XGSLjNJUNFrQZO4RuNqvloJ5F0JhYhMHtShQr5sRJkVCDhu5AkKmfc1aVuiDpvEEoIBOo9KviSgq3fJISZng1TRBdWKNsiVKHv6qKF3otK9H3%2BPWyASXgB1kxHxR2y1FkHzHnq2tEKShaUK%2F9qH5EP90UY74yMWz76XLlpELgyqP40SmgZSp0yuMxeONuzcOH722D3Cpq1JMvimafeMf2imFWLwRfgFJmSraQKXlkDkT6OfuZvtI3GI%2BdZs3q3VQQVBW5rPzf2PxQo1qxfxjvl4iU%2BaqVDSNSjNKlkrTZ0FBB1jxAeu8JcZW%2BWXFiIUvaKp5V7ZfxP0VFnvHLphpq5U4pafxyFSNxE0mXlaNUMLorlzNl3cNWaQtaUGTq5jrvSMUnJ2aEmSTCsb829YLtzLIRqII3%2BKfilJMmWKcRfE86DDyolagZPlwST%2Fe1am72cyainZE8Q8U1qQGU3S3UyJkmDNLyfxH4ZJOgkrxGbDTDYeAGrTEmJjrNc9OzTJ1NEfxrxGQq0vbu6vfMCNmU6og9%2B3YUC0wsjtUVBcZvv726cftn1uoLcKX%2FAJBxtVf3PLoqGBDSwzALy6U248XdKdKQsyfcntSs05RjcTRGKWiX4RjCre6Q804yGvMKEkEb0WBye5ElBUXpZ4%2BzfYW0224POUClQ4VzHNdiLT2jkyjJOiFXgdN8tlpSVEEFSp2idxNEWlZC8TxpbLt0lpRUtCRpInnrWTNjk2NhKvRtj4XqCcpKxC6blwoCEpjmeDVY16GRnI2Ay3dG3wxvzFJJ0k7GP%2Baa8bYcZO6ZNcrO6nVILpKAJTJmJofGirpg54Oi00pLTDbvnJUFCCQPwnit3OP0c3iz23uG%2FK0anFlJ323A96ROavQ2ESc5dvg4ggBXMcdazp7o0vHQSvMaDFxoBkjkE0M1SLjjb3ZN8u44haUuBRT3E7isWRX0aMarRaFnmG3GhK1gCJ4mTWJwdjeCJHa4007p9QgHqIn86FqiU70GGcSClEfumN5qFyr2FbV%2FXBUpRO1BKNuynBLsMNrQFAaSmduaba%2BiShYYtFoTCFEBJMHfg0ItxoclzylEEnY%2FmKtprsoVbuAITxv%2BtUNUkEGbghQ3M9iagyg2xeIhIkA%2FPT86HX0SwrbXidkmSAKtFBRGItoEqWAnoOKqV%2Bi6XsHvZktLfWpdwnbfc1VysqqGn%2FfNolWzrQ37807kwXJDRWdGHlBPnzv342q1kFtex6zmezSCovoEdZ5ouRSjYhc5yskklL6FTAJ1cVHIaopEXvfEXDLcEruWTE7zyarm%2FouiqMz%2BNOFWqVTdsiQdI1daS8nJAtfRr9iPjlaYndLtre5UtonkGszybpDIYrW9kqwTMv8AibklZ8pI2Oqo8g%2BWFUWVhq13S29O3vFOi2zP8bXsn1o2hOkIJ08k0wXkCiB6gs6lfzp8ehY5YUCuRzvII5%2FvtVkCdsEhRUTBMbUiDpgT6JLaDYepW2%2FM71tg7F0SSxI2OwHaK1JAuVEps0ATtuOverXYmWw4yykpTKQmOp6U4XLH9BtlqAITH02prmmgHF9ha2bCjABA34o072JyMJtJ2EpUDP509O%2BhTX2OA2PYH55ojOkk7oyLSlCYj5FQrNKLX4mHkkmQCduZiKuPYkZuW07FS%2BdhPFPHuCGD9oEkq9R94naoC1X%2BAQ4yklelsTG3PNQpSige5ark6YUD9DRKLYMZK7Gb7J0GU7ngg9qpoZzQHeaI2UlRT70PFClcmCrhlMqASdPcjihcfoKWOtoAXNsCJ0kbxz196W2BbI7cMbkQQT14qigK80OentULA9y0ZUEpOngmKjRAO%2BySFAgnbfbmgnBehkH6BLrBGoFAUQd46e1KHxW9g9xsFQ%2Fcj2O%2FzULkrLgQ6FBJgEdAea5x0JwSVo%2BU4XIlYFMjKkLPfMhMApJjptFU5q0LyPobqWkzsgK55pza9MFSY3UUpMkgpG%2B5qE5MTUsHVGjc%2B8VOD7KbfsbqdAUYMJ4G%2FHxVpWUZIcEjUoAzUaZB20uTE6FTJ7dP61XKiBRp0lQkCBxWgU2%2Bgxbq3B9I43Booya6BcXQZYcSqdJBprkkJ4P2F2lEEkE1FJFODqwyysGDqCv5%2B9XQIWZd2EmB2NQgRQ5z60n9KhAlbvBJ0zKdvkVCBNDnChEEd6hB0l6QkkyZkVCC6XTyJO229QgqLgiASdPzUIZl5SiFagOwqEPvvCt%2FUN%2FfioQ8FwZBChI71CGZuVgwQFfBqEPUXJgTsN6hBQXG0FUJ1flUIZpfncqg%2FwAqhDNL2rgyTNQhnrVAAVNQh75g36k9zz8VCGQO8D0zx7Vak0Q8UlCYIE%2FwpkZtkEyTvvzRkMgpQgkmJ6VCGJncnV3qEE1DcqkARUIZpG4jYfxqGhCS4BCTPtQya9guSWmMXFEJ2JJmNxVJRYt8fQPcVAMqGodOKUCD3V6lkhQXvPFSiDRa5JO5HSoQb6iDsrr1qEMgvSRx0Jg1CGS3SEyFEK5mrTogFub9DRIUtOobwalkWxo1mFLaFErAA6VCsn46fYMxnN7duwXfMSEgck1FKtj8OK%2Byl8Y8WGrW3e8y6GxO88dqJzYyOOXpmr2fvH9i1auVpvGyE6h%2BLg9xS1OlbRcsUqtmgniD9pcWzzzzF%2BhYKoIBEgk%2Fxpazpg44Of8AIo3MP2n7iWCu7WlKkaSQvj9aY58TTDxnHRrxnHxhusaYeSbnWVgpMbdfY%2B9LyZU%2BzXj8dt0UW5jlxbPLvjcF0AhQBMHjg1llnivdj14svREMYzd5mN4biGtHlvEKI4A3j61lyTT7GwxtPonC82Ofe7KyJKfMcKfQJ%2BnuKyZ5SW0aFjleyw884d95tMP%2FAG4Qh1CD7tpjjtNZZZZV2NSS2ylM0MKwdlYZUp1tKUpSQJ39z%2BdaPHzt6Ycsqn0RfJ%2BKXVzi%2FwB3S8spglZUfw%2B1dbx8ojPFuNIH%2BIGPW4LLbNwolCt4MGf607JlUdswfA5LRWqMfBZKH1uJuEjzU8cTuDWPJnsNYn1QAZzdeOG4bY1EJPoVHUnj3rJkzKKtj4%2BNJ9ja5xd9djbIN04VuLUdIOxI%2FlXMz%2BQ3%2FFkXi%2FsLsY01a4KlSgW7gwlYB3VvtHtSo2umOcXf4skNghtlNo6tJ%2FaQs%2BxNascm9tlzi%2FbGV9ijmFNuP7oTqIQVHSCQe1dCOWNGZ4J9xZb%2FAIb5qauGkXFyQ6EngRCj1P8AKnYZuTtF%2FwBu0rkWnfvB5tF3aNBKnjsP3QJ5rS81EhisqsWby8beFy3DbjmhajulA35NJyZ29GxLVG6WQWmf8JsrNoifK0pkEARxtz9aLHMqTiS6yzC3ZYkxYrDRUJkE7T12PWm5MtLQCkif5LxtL1zduNvENoeIKQOg4irw5HJ0xfkTVUXNY4wi9KmyuEJgg9z7e9HzRifeh2HHApXqcII45PfekTnsYiSYJfaVuNl3ZRB0hUkCkOe9EPcdvUechawBEAEHn9aXLKGpPpGVhmUYcpsOPkAp22mDSuaC5SXZOMNzY4tQDzgCTxvwaFzXo1ptk8sM1oUUILwKvwyDMf33rPJN7YxR%2By0MHxNVzpAWY6e9IlOifGWFaPhCAErBTuDFV8hFjDSLlPoEwP4UPNh0xx9%2BQz%2BIjzAdt%2BaJZBchZzFGy0y6haCQdJPeo8zYCil0NxjTbQCi4kKJ5PX6VPkGqCaPRmBAXpDpG%2FO1T5CpRpaCSMxMtJAcuGgO5P8AOq%2BT9FJL7GF94l4XhqCF3jKTzBVED86nyr2NjhT6ZTubftIZewltZdxG2QoAmAoSf1oJ5V%2FgZDCltmo2avtpYOh%2B7Rb4g36VAJPT55pLyS9GfLlSdIiSPtei6WFM3qktgzrJ9JFT5p%2FQj5P0Kn7YdpaO7XK3GwTq0q5gUyGWQXyxS2gbe%2Fbfs2WVOpulaAdISDyfzpnySfZPnx1aIHi%2F27LVrZV0pw7nSFHYxxtQvI%2BrI%2FKj0a5Z7%2F6hz1s6bdq5WhZBGlJJ%2BpM1XNrtgZPIg%2F4vZRdx9rnNecrkJN5cW1pOoqBO4BrNz%2FG0x2JV1s2u8GM5XuYjaBtDi0KUEhSzJVuP03rLj8q3xN2OS4nT%2FwAO8MeWy0p5SpHTk7962pb2U06dmyeGpaYQhIAUscdYrVGXoyTfokbLpKBMTJFNFSQRRCgdlaeNqtLYkIs6APSkgkCiutIgUZAmJ%2FpVwS9AT62H7ZRJQkTz0%2FhTE6EqFbsk9gr1fi1HaduK2xf2DNErsyDuDyRTF2KJIwJAAJAPP%2B9PIG2QCkCTvz89qpp%2BimrCrLYB1Qf4U6EWlsy5EEm0cAxTsfYoeob2ABATMj39qaKyukLBkk8wO8VaZkS9nimSTEg%2B8UcHY2MVViK7eXN5nYR%2FOmBjF2zJkQUmfrULcHQJetSIUUkSahnlFoHuNEz6VDf8qNTaKBbzZI0huI9Ug1ObKbBTzRKfVJMztQBOTfYHfZWEkAcnpULUmlSAdwwSVBQiTO1DwQcPsA3FsZVEc8cGo4oN9ANdukaiBAPWlUzMCn2NQO5O0bVKC4vsDP26xqSgCI4jaqaKTp6BDtooKPpM78Dk9qU8bfQ5TtWwe5bLTuCduJoXFrstSRN0vgjlWsH8z71zjo0YLuCmTpCoPXkfNQh4q7BCpIG9G8YLin2NnnwYAV6RzxvVwjRFBDdbxIESpBA5pgRn5iVJGyhv0Gw%2FWijJ9UIl2JKXqJVAjgd6LjFFHnmEBEJUrqapyIOm3UcEyOgmquL7QMpUEmV7ggED3qoui5TDbDoESDo256GmqaAcw3bOARKSCOd6tNegZMM27wIA2iOKsELWzqUjYz9ee1VRAq08FSJ5MbimqaFuDCbbvCTpnir%2BRFfGx%2B24AIgzMCTRoAIsvpGkkHt9KhB8h5IMzt13qEFA8CduY4qFWfC4gq3mI%2BtQsxVcbTIqEPFXIUoyogbGoQxFzyRBPBqFWZC5IJEe%2B%2FSoWKC4AMHSreahBVLwVJjUn2OwqEFUvCB0qEFkPJJIEiOYH8ahBZLxmNIB4qEFEuglJ%2FFvzPFQg5bcO0SOgJ4NQhmFJCjIBHbtUIZ%2BkknRB2mDzV2yCgPIEwDG5o4zIJOKP4RPPM7UxMgluVEGf4zUDgt2eKUQJSSJ6dqpqxklaoauKKgZMJ996W4MU4UrGLhIPA36zuKriCMXV7HifbrUUQ8Sd2C3lQZPHapN2wXK3YyU8kkj3I54oSjDUmNkwPaoQavOhCdRSB12qEYHucYQ0hWrYR32qFxjfRVWYs1t261K81EgSBNJk7ZshBIqDGPFO0YKiu40ax34Paqllot4%2BT6KozR4yss2LiHLoeXBKVFXTqKr5m9In9rT9mhXiL9oNmydxG2GIFxJBIIUYB7UEpevZocVBbNE88%2BP67xxy3F06ptS1HZU7%2FNDDLSpsVGDfRp3mvxGv7rEC2u4UUFQA9RB55PtRRmmHDE2%2FwBkfxvHrq6CNdypCU6VA8AdjSp5404o6GDxprbIhdZ3eRitpZ616CqT2MVjrZqfkU6Y8zDm919gsoIaUUwSkmKCUb7DXkJ9JlCDPN4MwssO3Di2WoE8aSVc1iy4UvyWzSoe0bK5VxBD%2BJ4Bduul13ziNzsokc%2FrQS8uTVNAJl55ozQ0i3QxcOBPlugFIVG0dPb4pXPWw3BVsi1xctY3qbuAEMPhJbnedjEH6GphyOLEpcTXq1zIzgGa7t3ZbaS4EoUrlSQR0rrYc7M2bJviVHjGOXONY0hC33PU6VOcwR0ietMlP2LcfZ9cYzbtYqWLhetCnRb%2FAItgCmgl1bHY8qjtjm2tnMMN75zSgFNqW0J5TGxArH5DuJsU1JWg3ibNt%2FgmEKsEpTcoY1OEfi1Hgn6zXPbS7KI3ZO3t3d2hdYcUwCEyBstXX8qJSjVUYpeRK6So2QvMuP2%2BG4fjKYas9ICSREmNtu1C1ro2qKav2U%2FnX75iT%2BF4U06EWrZCU6UiXFqM79xWzxnBGf4p3pkxwNy0w64s8Hw%2B4dcukDylkHrxNa55I%2FY5RpU2bz24w6%2ByBht6lhH%2BIJa0uNpTB1DafaqnOo6QpqinmsIucTzAcPsnHEpcSlZJT%2BM6unxxXO5O9MOLRsDlF64tL1%2B1W4pxxhMmen5Gung8ivexcY7qxG5xIPY0u70aV%2BeUxGwA5g9DIrQ8jk7YTiTPL%2BKqwvGHkMvB1l5GoQBpAjt3qmIlJN0i%2B8CxAuoSyj0upAO25J7j8xR42zTHEkqLPa1vJaWlEEA6j3Hv7c05V9C%2FhSAWG4qtnGyhSlFrUQAoQCe5rNka%2Bhul2Z5lxVTA1%2BZug7iNo%2FpWea0WoRS0QVWYS460UKAI39v79qSVwRMLTMaQUrUsBQE77fnUBXP6JrheaghbOtQUewG6Qfao4JqxiTWmbE5TzEhaGU%2BYIVxvFY8kGt0aF0XRYYsjykmQDyZPIpYuLrsdjG0I31o1RAPaqbHRTe0R3Fc7W9shZNw2YE87D6VYrhsjaPEWyQzdsrfaLmnUFatgQaptJWy%2BFukQi78XbOABcAwdJE9ayvyF6NaxJLojd74%2BYHhrZcdv20IEklSgJ%2BPepHyLGLE%2Fo18z39tDBMOQ4hGIMttpn%2F7m%2FHWKH5Mj9GfyYqCs0VzZ9uPMmYb121yup59BUoakmYO%2FSKbjxN7m9nGn%2FVXHSRGMOuvFPxLdSu7cvmGyZGx2323%2BIrVHwknaM%2F8Ae5Mmixct%2FZmzjjd395ulXamQSohRifpWqHjmbm4vZdn%2FAPjNjrtpbtBx1ttO4hMgd0z1pvwIv5pfQQb%2ByhiF6ylm1LqnArdZQAB9KYvEg9guUnsY4j9jt5i3U88X3RulZGxn2E7VF4ML0DKM1uzXvNf2UcxrdWxh7L5SskDSJmT1%2FrTP7aK00LlnmtESsPsBY0%2Fcf4hiyX1QoqATEn5J6UjL40P9KDwN3sbY59mu4yo6lhVopLKDt02rm5YNdHf8LLo21%2Bz5l1rDFIaUCjQpJSI3BrnTwVLkmdnC1JdHUjJz7aLVk6SCQE%2FFaYJtGfPoubDS4soOlUAbCtMTG5Nk1tWFKSC5KfpM04ByphZIKQARpHYGrEscNEDYJJE7e1QoItEEJMgD2q49lNWHrVadoB5EVsa0KSRJLNwp0%2BnmNp6U%2Fj7Av7JfYrEwAAJ3J5o4P2Jk9kpt1EDkFXB9q0Rdqyg4wRqAHt8VZAu0QrZJH8aen7MeXsLNbmAAYp6lYthBCPTHqCuZHWiMeaP5WOQkblWodTFQUeBO8iQO9HBhwlTMHElACtinjimjZSoZrQtWogEjjaoLeR%2Bhk82oHYKT8VCubB71qNUEFRPUdqtKxEpu%2Bga7agSQCk8H3qNbDhmr0B3bJQE7RxHaolZSkgTcMhAhRG%2FEDio40OjOlQCuGdOr06U9PmqKnKyP3DJ31I4HbrUBoBO2%2BpRhJKTtNWT%2FACDHWUkiBvx70qSZGDn7ULAICtX8fahdEBTtqSdJiAOfaaEgPXaCQANfczzQzjYUZUIedKUmSDNchs69CnmzJkFIO47ipaKMPMSoncR3olkIY6ykmCRHXar5sgmSmdU87TFTkyCSnFpIKUlaI2Pb9KcsmuxbgJh9RJ9Gsjn2mpysnBfYohSypMylO0TxVMn4jppwHSSR3k1VP7AlAItOKKEpMiep4iiFqAXtnCkpE9evf6VGwuIaZcBIAXEbnfijxoB4%2FoMsuSUbwPimguNBVDk8hJM1AQsw9KkpCjEjjpUIFGXCkFJXqiJqrLSHyHoATqAB6xTFNgyxodpeCyIUon2FX8gPxoch7upZ77VOT%2BiuCFg%2BSEyoFMTNU5sNRVHheTM6lA1FkZKRip9QTsqT3jYVfyAPF9GCn1JJEjjar%2BRA8GeF7YgkgRRU%2FsnyGX3lI3n27UE20%2BwopPYql%2FZKknaOlXCTb2FxXoWS8NvUEjpRiEOkvjYqUJneO1QscB5IkawT88VCDlLwTEKBA6e1QguhcwAQDUIOUOwJSqNu9Qg4S6ogwQD81CCocTP7sxImoQU1iInV02qEPNKZAJBHv0o4yZF2eKIPqATz06UzkhypdCClQmOYpbkwHJ3oZvLGlQJUOlVzYLk%2BmDXnNO44A23oQWDHXUSqVfFNnLQ6ctUgY64NR1HVtO9KFAh65CTIVJ6%2B9Qgmb5EEKVJHeqlKgoxT7YLvcUbCANQjjel%2FKHwS2yp8y5jRapdOtKQAY3oZzfaY%2BMV2aX%2BJXicMPTdlNwdG4J%2Fy79KWp2alji%2Bmc9c8faBbtnrm1N8pYB9KiYBM9d6RkyqxmOUYurNfM2faTbvsGWpVzcJcQogeox2jnis6zXqzVKcJdvZzz8RfGbELp7EHnMSJWSuAlRKT1%2Bnagjl5AxS9lE4d4jjEsRDTjzy1wNj16n%2BzQ870FGcF9EyxkNquvOQ8C3pS6ZP6UaX7HR8mHSGGJ4hpsmrpDy4WICT0%2FwCKGTrZIzc3t6K8Vi7CMZbS4tbiwhOnalPOkuT7NbwwapDrMOY2be31NIQteolM7E7jmua%2FLlKW%2BhfGUf4lKYbdt4hjl4HFlTpAUTxpJPSOlNh5UkqaNCzujdLLQbv8r4Td274S5ZAKKY9Q7z%2BXWsjybsbiUWrkS3Dre4zuFvNPhFoh4NKKv3RG%2B3WapTAyLdpGeZZwpeFlt1TiGUTrSYCYMQQOsfxpsVsxZJtPZQOOYe01jtu9Dri3i4SdzpSJJn6V0cWRONNhwhibtsrJ0hTGJYowrQl1RbbgEQRzt%2BlOqw3lxx0ho3btqOD3124ll5xzUT1CQP8AapnlUGkJcFJ3ZaOAlvF8Ot5cBcGpknY6RO0n4rjfLJ6bGQioukHsGy%2B9idpmK4UmUWDa3HUgRsJP5daDgO430YZPZD1vhDAbcX51wdAKd4J6D5NFFUZ3KMpdmxGerheGYNeYC6q3dcttAMAy332NOlkdUanj1o1sTdN32Or9akNMtKcKyQAI33%2FpSF%2BTE6RHMo5gt3fEK281wNFx1CUSfSBPNaFhcXcmLflQujoZaY4hjCVWbJQGjDvo3ngR7iTXQl5kHHizXSaujaDBfDO0usPcu7N2wOIYewhb2jlaTuY68n9KzKEWtMVLDr6KlxFjE8uNY9jzDSkgK0rUUTqjjfpVSSX5WLrfErmyxNu7y3cYooKW4Lj0k7STuf480%2FBn9tmqEOOiyLF22Td4birKwbQpASkbhKo3mtlrsKkXDgOZG2blCkOkkgBKQJneeaJN%2BhGWa9GweWMXw7ELhi1W6vzH2w2iTuT2ipJyXRgc39gHNDasDvGrxQgIfCFE7yJ4%2FLrWWcmdHHh59DrE1WmIWv3lohTSxBk7kHj6UpSbNC8Wl2a7OY4jBcWdYcMJUVJB5H%2B1Z5TdmZ6fEXxTOlnaeSTcJQFTPXbpNDLIaMML0xFjxGtFXluGrxBYCgFEGSTFCso%2BWGl2bPZG8SLPym13D7aVggCSBFKy5WBCq2XknxUw%2B0YSo3jYhPUiZPakqbZWOF9lc5q%2B0DheGtraRehT0GDP%2B9U50vyY1yjE1ezt9qO1sm3VNXTalqT%2B%2Br%2BH5VcZWriSKg1yZrcPtdKvscVbM3qhb6HEbKMqJTtt1FU5%2BmZlkSdopDHPtb3tkhwMYgqASRK95B6Ulx9oavK3s1kzv9q3M2LPLtrG7uXLl70ITrJSJ%2BO9SMGtsx%2BV5zkuI5yzlLxG8RHLFr%2F5iy8QXST33gH4IrYmcmcMmTrZ0%2B8Afsn26Puyr%2B0SVAgOE7lXciaJZKVGnB%2FT5Vc%2BzqLkPwUwPC2mGWGGg2mNSimJPatOKdKxzwV0bG4dkvCrRtDaGkJgifT%2FADrXHKmDpKmgi9l%2FDnFBCAhDSYABiitCZcfSDNlhGHD0NNNJbEzsN%2Fk1aYhpj64wHDrpOgNNkHsnmi5pdAOC%2BgfZeF2GXl35htAk8CQNzRrNbA%2BNL0S678K8KZs1xYoVG86aZ2Tkk%2BjRXx68NLdm0vnW2Jc5ECI9qy%2BThXGx%2BDPGM7NUPDzBcUtcX%2FaeYhsKJSDyme5rhvHez0kPJgujoNkdAUzbpdUSqU9YKtqmNNaJlqSs2OwhpCWkKUIrRCKezI4r0TJhQCVJE9pFNFtfYpskAbJMHpx8moDzSMwuR0JkbTUFyd9D9lwiCI54AqANBu1XEKKiEztA61p52CoEks1QptSSCJ2NaozTFTpvZK7NzSqNRk%2F3zVp7oVS46JXauAhJUSVe5p8H6FSlQdtyCSVQn6c0yylMOWq0q24TtFOh0Z8gbtyDBmPmnQ7FBRszBJ2%2BaaZszd16HSeQDMRxH8qtmZVZmEiSYWDz8UUEOhFNWeraBAKjtJpoclaEDaAgn97fimKAmhuu22nUr2qpQaKGTlulXpJUIPJFDtFOvYLdYWFqHIHtzUYNRBTzaoUANUHpxVA8V9gt%2B2mUqAMdDxTUr2xiI9eWwOsSojY%2FXtS2gk2ugLcM6StKtW%2B096oJTbewHc2oBCgZnoBwahUkvQJctAowZA6mpYIxXaqBVpKlJMcnc%2FFLaV7Lj3sHvWpCidJjvQyouaroYOWqTBGsjoKqgSAecYBkhRPXauBJ3s7km36PC%2BolJJAVxtUUSlBnvnqJJEap2HSjiqL%2BM8VchCeEg9SKMpwEhcBSpSApI3A%2Fv5q5KgDI3GwMencSOaJQtAOe6PQsEkJ0lP8ALvUvjoGXZ8LluQmJPUTP%2FFNspRPUqhSVpBVvz7VBqWqCjT8aTun54qCuDCbDvqBhIO3WIolVUV0GGHymCSCCd6NP0igwxcAwf3txUlJpAyhYYt3yVDb5qndWD8YTZeJ0qgHiijIW0FGbiCJGx5nk0qad2QINvzA56c9etFGe6IPUPQABsOaZaILIdiIKQR7c0MmyGYdc3lKTP97VFJ%2FRKPPOVuJg%2FFEmEoifnf6p68VGWoM%2BD24lRj3oaf2RwZ7556kn6bUy2DZ4HiVTvER8VL%2BwZKxRL4Tskaj196oiVKhZDxUQPSEzuKJSZbSY5Q8DsFA78cUzmhXxsdJcIMwDBFTkiuDHaXlEAgGY71ad9AtDxt3VvAPQH3qyDtDiZG%2B3QVCDhDgJ3k88VCDgOkiII6VCC6HI1KgCoQ%2BDpMHTHTmKhDEulSpIBHEA1CCalQSqD8g9KhAe%2B5Bgkaup7VCAq4cB2JB7GKhAI%2B%2BJKQCd6hAa9dAbKCQPniqcki1GyOXN8hIUCQOxmlubYxQXsiF3jRakIKTHvQBJJEBxvNvkJKlrJHAP%2B1Jn2PjFPTRq54i%2BKDFky6C8gkpiCrj6VMjXHbNGLFv9HMbxt8amVIvmBdtkySE6gNMda5fkTcVaNsMcaOVPiF4j3V3eXCmrgluSkeqdp3%2FnWGeZPZn%2BBWUvmvONyxll8pWUunqDG%2FetGGCas0QwpdGqGOZuvLvDG4chaXFJO%2B5%2Ba0SqPQOeEWN8p4s8i%2BauHFkydJ33BPWKVGuWzGnHpovbEMaufuYMkpUj09Cfb%2BdaeNmuGCK2gYnE7rFmWsNsGXbm9K9LbTYKlqIEmI52BP0pE8Fu29DpFZY9jC8OvgVy1cqSE8%2Fhjofesnkxh1FmrFip2BFY87dqH3srLYPqJnjvtWSPjTb0MnkSItguOrtcwsqYACXXNMzPp1RPztNC8TXYn%2B6X0br%2BB2YWrnHsTwvElOCxdt320SPQDp2%2FjQ8daHYvKT0Wl4L36VXd1gjagUB50EExvuZn6VIRsd8jeokRzTjw%2FwAOvrT7w06%2BLtSk6TJJ1Cd%2FgUxya2hE8al%2FLskDmXnMYyq3moICGW1KZccSoAkcQOu80cYt9iH430Q3FcjoOTHblhlaALpRlZEIb6JHvPWgtrpjVgjRr3n21ThN7g4%2B8FaF6Ux%2F%2BGqeBFUssn2y%2BCj0XR4OYc3fWxfuWm1sff0suMTC1ogQe%2B89Pihc1dmjFj5O2XndYNcYTnbOmTrOwQm4xDCCtoNxDKdiskEwTG0e9GnZGqGfhtYWthmSzw55lF%2FdpZ1tqG6krSrUT77A1aFRwq7K5z3n%2B8v%2FABZvGn%2FKNk%2FarQG5GlSie3Q7VG7Zc8lSqys8yPP5TxS%2FtrpsSsKbAJmUkSQI555pUf0DLIl2BMuYUt3GMo4jbW612Fy75Egb%2BYFAQT05olfsOEYtpm7SC8hrEMMs7sG6YuUNgEjUDJn3gQaZo2SpLRvp4BY1b36Mx2%2BM3aS6yli0cUlc6iokCCfxARRRyNGWTvoZZxabfyjmXL1ut68vXnCu1dS2CAEKOv5EbH3ok7TsJYrdrsgeUfDz%2FGcIyAbRlLeXbp%2B6axJzSVaHjITI6biBRQgSaaIJfOu4HgzuCoIVdtXikIB%2FEkhREe3xXQxxk1%2BRWKd6YrlnMLdr54uHFJuELnfmOY%2BZJqZbiFkinpl55VzjaN5yyctu5dTClOlJ4UNMSaQs8noz%2FDGPo2Hznd2OY23mLZVumfWlU%2FiJFSbdL9kWSnoid7ha8uYTYF58uocPMzH9KBxcdWNU32aveJAessRd8p4uAmQI4k8ismVsuEd6Ncsw5mxFBbYuXHgjhOoSeYrO2%2FZojC%2ByucS8RnsJJIuNC%2BgkbfTpVJtC55IpUiY5d%2B0A7Z%2BW0%2FdkCdYB2BMRAo077G4ssUrFMyfasvLNgMm78noklUx%2FQVUsb9M0rzoR7Na83%2Fadxa7uF6b9RckkKBG07bUp4mZcnn8uiisY8XsaxYPpXduLKp0mYBNU24LZmlNvsDZYzPeJxu3Up5airUVCdyNJmgir2VYPtMPxrNeKOWVil1Q1kIIEk71ag70Lnkikbx%2BAf2N73HMVYxXG216QUwlafrJ%2FLmtCRml4Usv6Ox3hr4H4PlS2tWmcPQXNktggek%2B35Uqbm3%2BOjqYMXBUbi5bwO0we2SGkhtwn1RG5PMGmQTrZWWb6LDtMfRZlLKCCriR02p3NiuSoOf8AerbSNOx2j%2FeijkaFyUWZozYbtPlNKCiY1Ann5pscj%2BxFIlWGXzr6mx6VNA89KNTl1YE4PtE%2BwtxJJ1SpQO%2FtTgEy1svMJltRSFcTtTsUd2DOd6LAurMO2jiQkAKTBrUnTsxN3s1N8W8s%2FwCIsvNBoqSeZEyKOcPxpCoK6Ro6rLr1njSmGmghAWUjpFedywcZNHpsU04%2Fs2NySxbsNtIhaiAN5mfig5DXNrS9mwGGoUttJKAByBToMqKVWyUthIb3IPUz0pgqTs%2BJ3MmBzMxUFuBmg8HSj4qFfGPWFE6Dpke3eoA0GrVeyU7gSCQOabj6KJJauJT5ZSJEzWjFvQnIk9EotFlUEAiaeoUKcdUSuzUDoKYJNMSEyjZIbffgkeqSDwf506KpUCoUw7ZkFxUCI326U3H2LkkHmCn0yTTl2Z2GGT6UiBE%2Fl8U8CTY%2BQBABievt81DDJtvY4SkgEbjgA02K9jodCwbkAKiaMIbKQWzCREdatOhM%2B2ewJlQCe0CmKf2Cxs4xOoAc89xVuF7A%2BNt7YOdYKVKhG8fQ0pqgXFIFPM6SStMHvVBcV6BDtuDqCo1TtAq7ZNpAq4tTskArB7mrWwHJgR%2B0B4QVDiI2q3EbB32AXrNUklIM%2FmKAsGqtEidgrpBFWEuNbGTtulHpCSes7fpQtWXcfSBL1ukhUNkc89atJEjK3voYrtVR%2BAlXv0qq%2BgvxvWihUuFJEmen9ivOt2tHds9%2B8FHCitPT5oHFsCU0YecpCd5ImaZGKQCk2%2BjIOFcgghMdOtEuwuF%2BxNyUlSUlQHXpT6FyjR8m4WIKZHeBuasBJDkOpCj6YI33oXGyzNtRJSslIESTP8qGSdaAlL6F%2FMaWoJKlADgxEe1FG%2FZE5Dhp5IcKQsFM7yOKt9BhRlRPqTqJ4O1BGarYMkgmw9%2BAbageDvFGpJ9CpxDDLyRI1QZ6daugUgvbvbAkiQdvipyosIsvlG0nmZmqX6BlBBVp0FMpWD2oZ5JXVgOLCDVwNX4iP51ItMFy9D1NyAAkwZ57mjooXTdBEIBJTx9anKtlpivnjYhR4jfvRLI%2By%2BTMFXABMKGrvNTk30TbG63zqJ1E9Z4qNSBaMvvMclQ7e9TZDH7wTxxVqTIKIeTvKjP%2B1VyIKouUqKUoUFCOI6VFKiC6LhKTuoR2FEpkHCHwR%2BMpHxRp2QeIfTsAvV2qyD1t8TKVFO3TrTMbKktDtDp1KJ4jvvTDPEeNvgqlSlflQua9sNQY9D4kyAOnNWminFjhLsjqSON%2BasoUS%2BOZmRv81CGSn0gTqKdpmOahBP72kKKdQ4kCOKhBA3YAJKgkdh1M1TaXZaTfQMurlIUTMq6%2B9WUBrm6glSlAD5qFNkSvMWSlZHmAEHvQTdBwVkXvcZQNWpyfaaXJbG8a6IhiGOJKHQl0nTvtS00tDo42%2BypMzZsTaoeUl88f5omo8iHwhro1szx4o27No%2BhV60hW%2FJE8VlyzfsZDHb0c7vFTxnZdYugbpDb6VFJ9Z9UjY1z82etNm3g6pLZy28UfEO6u7%2B6YVeLWCFT1AFYJ5w4Yahu7NSc0ZlZY16nSW1bTqMnbmlcnJFuEIrbdmK3bfH8qPoQ%2B2h5LZKN5Uk%2B461q8WckIcn6NZcQsVW7DqdZJDxCtuP8AmuhbfYDmn26JVb21u3b4RcFQSXUpUDPJ4PzWTLlyJ7IpJ9FrXy27rArUIcH3hlIKgD6ljfeKGXlzoNTJ09jdj4Q5HdwhhTL%2FAIk47bk3bsBRwaxUJDKDyl1wQpZH7p00vJnmu2C4qb36NRscv3XnbNDig67q0T1rLxtm35oR1EIWrYuEXGo%2BW2Wyk6eZ6UxKXVGbJNyKxYun0YpbNOeY0okLJn8RBgilU7KWOTVpG0OUsfRllGGYusqbS3ct%2BYtU%2BsKPH5bRWqfjyjGwVa2ix0ZotbLF8w32DXa7WxRcrdYBVykidz%2BgrM3SHYbb7ore4zOxeYphQVdlYevElDYiQgncx%2FCg%2BRGleMk7dnRR3AlYX4M5NsXrlTrV3iLqE%2BXbyrTBIPdXI3rQpLjo2wpB7x6yrg2WMIwfK%2BEoecStgOFzUFanA2CUQPc1UoaIsdu2cncZxG6xLEbxi%2FQtN0w%2BSCOih0%2FhSElYhSV0bD%2BD95ctpvLeWX7hxSsST6iEtBpJMzzzvFU0m9B%2BJ8iuzZDMGL2L2ZMRxJd8y5iZywbguA%2F%2BRS9OsSNgSRMdhVNtDZ43%2FgCZPxP%2FAATJ%2BD5ocCFYm%2Bu%2Bsm0FIB0wAFJPU7q32piyaGxw0qZpfnLEncNzFYY2Qu4Um4GsEx6J3ge29UpWzmT8ZfI9ll%2BMuGJbwTLuaEXKPU226luJKgrkA9o60zGoqX5dBZcKfYw8J8wodtG7ZvSHU6bpgAypDg5H1ihy1yfHoKCS0jZa%2FwAYuLbE8Cx0k2bjx9a9P41fvT32MUu%2FRscIuOyxcv8AiRdYYm9tsOuHGV3Kdba4JIcCpn9Jp8KrYEIwj0bBeAGems45ibtM0XeqzW8uwYKYQStZlQHuRNFhnXZf4p0bKt4QvLuTXsoYfcu2t8xidwthmQFNlLhda1DqCkR8k09RUpWi3xfo0l8a8WTg2bmri3H3Zp5Kbx4ODdK17xEdFTVZsjWkZZY16Ipn%2B8tcMuG8awi6P%2BGX9oxeMwrhSk%2BtJ99QNIk23sKEVEYZczSLu4w%2FEkPut4hbtJTKjtM0EMgcpp9G6%2BDZqtsWwXCnF3Kfv8pBKTPStTz3oXwXZLMwZwtm8vstXi29TRHXkT%2FGqll%2Bw4QcnS6Nf8%2FYkxjmM4CLRtKmn9KOdjKtiTWec2%2BjVCMoukUr455NubJbbNsEq1N6glO8e1LTdGnBBzX5GgWe03jT1q08l0OAGTJAA4E0mmnTM8sKRTtzmm9sr1NoXnQjZI3iKZ70ZZzkvxIhm7Hr13zD5ylMgSNzJ%2Bfyqm2KlFNbIA9iKX4laydImdue1L5X0KhihHQ9ZullCG0hbi54CZNHC2i55VHst%2Fwuylf47i9w6ptxLbTCzBTEkiPzo%2BL7spzU0%2BJ0y%2BzR4GWib9h69YLqgQ5uZ3rNm82MXxW2aPC8B3zls7C%2BH2WcJwa3ZaQ02NgD6RwOlJ8aTlO2dDKqX4lwly2ZumHYSlKVAjcHbfeum5I57T7Q8u8c8p19DSkrUdxtsB71HJARk%2FYwZu3LiB5rkndRA49qsuabF0feH7lCfM1IT0%2FWoLcHRYOFFu3SAv1CeDyaqkKpInuH4m00YStsK%2FhPemQbXRfNJFg4NigcWgbCNtuRWiMnYqML2Xzlm4bUG4UVR79q3Y40KcC3WUsrtCCocbzzT1H6M8kul2UB4mu21vbXKk6dUESTTJzaVdCsTSe%2BzQ3FXm3cXUG9nSo7DrvXA8ptyZ2vHeqLryRhq9KXFpJXxHEVhVuR0FD8bL6w1nQlJCVJPA%2BK2RekkLnVBYqTA3nod%2BPzq%2BT%2BhEoIbOKQkGCkxt3o0VxZ4FpO3B9xE1YLbQ8aWeQqPgcVcVsANW7kQnUoDmKOEWQkdo7IBlXUCdq0xXH2Jm03ok1m5PClTMimc72J57psldk4SkDQQO8801NegJOyR26hpEc9TPFPjL0Kal6D1uQkp2OkHiaNMBprskdqsJI5mPmtEfRmYdtyn06NjPzWgGTrbCiN1AzO9QxZJXIdtjaBPb5p8VaGw6F1NzOgAdI%2FnVlTbrQiWPSRvIMcc1BTZ6GkQorlMGNutQFv6EnGWiNiZ6yaKLouNt0NHWkjVKSD7CmWinC2DnmUqBOs%2FUUPAqMWuwW5awV7nSTVOKXsMGPMD1FMT%2BoqmgXjXpgd5kSToJPftUUilFoFvWiVTAIIiDH8aNUwwO%2FZJBVIJQeoFBwZV%2Bga5ZEiRCpMCRQhJN9Ap60B1EQD1FQoGvWekQQoDj5qENUw%2BQoyCJHA4ry8bR6AyS8owSqVGNu9FzZdnwdgKCzydxPBooyspsyCyjTwY2iOaYJeR%2BjInWSFKhROwJ2qWxE5SMiSk6hBj3pmOVlIcNORCSoRuQk96YXxs9C1LVKeRydoNQLSFx6SSohQPXtV0wXJvoWS60gn0LVCjxvA6fxNC0XUgi0%2BhekBaVEncTSGq0A4SCTbiQUAbQY3%2FeNRSaIscgi3cfh%2FCgHn2orbRVBVp4aQJMe28VayfZAizckiIAE%2FSmJkoKMvqRHqlPtQtJsugg3c6yCsTz0iaFwroBw%2Bggl8njSExA9qHm1oW4tDgPEwYR33603mikvs%2BDqoM6vpRrKvQ5NL2eeceDEniav5QtGHnGEmCO%2FtQrPsRNPs%2B82CZMfBP50yOVMkYNmHnACTJgzR80TkxTzzMAIPuDQ80U3YsHSJBAP8qJpNFCyXVahz323pLiQcofVAMBMbVHKkQeMvEFSZ2HMGjjkTIgk26QNlCOu%2FFMYbVDtt31BJg79KJSdUBXsdoe06SFTBigaIO0uqRGokjmKJOtgyVoUTdgAiR7dIpimgPjYv95HOnv1ok0%2BgXGuxNd0dwkHaOtWUC3bspUoqVpI5npULSt0CLjFi1IERzJNLk0%2BxkU10DP8AuBta9JVB6b81fNLoH42Mr7FEOtlaFAe9RTD%2BBlU4%2Fjn3fWVKCQDQzkiQxuynsw52FkolVwUtjtvP%2B1ZZyfo244%2FZXVz4o2jpWkXaVqg7cf3xSHlrRojBXRSHiD4ktKt3VMLaDqQSN%2BR1FRZl7HwhfRzd8WPGRVndPsIfKUnZIKhuT27Vlz%2BQmqRI4WnaOcni54ququVrsluIVGlwA7KP99a50ci5Wwpy9I1QxLNwxtxSHVBt8SlRmZPvUnkXoC2QfN9kpeHBxKipcEJgjmP4VnavsjZFcm4u8HG7fzBq1EKnt23p%2BLNxeyJ0SK5y4HLooX5%2F3V8kKjcJBG3671qXnR6olr2NzhjyE4FhV2lxtxkaFQf9X9KXPy7%2FAIokYf8ASidZdwxDOcX724bL2XcPYVdXYJ9K0JEpH1Xp9%2BaFeU2qYcsU6soK9xbF8y5tzFjF7cruXHlLeRJ39hv0isMpuy140uyKYleKW4l9aFFz07hOyR2ijXeynBrTWwfh2YD590G3QptSiAmfxEHr7VtxTl1AJOS6BV9cebjNm7bjU2FJ1g8oPUT2rRkxKW2PjmklRsPmm8au8g26LJCdSUpU4I3Ck7isvl5F0jHKDvsguQ82jGRi2DrkL%2B4LddUraCkgbe%2B%2B1YozTCnjlFKQ8fuMOdzNZOWbZSzbNoSQJ%2FEEzO%2Fc0EkbcU7WzsbkrMdraeA%2BSs24mhhbVm1cXIceSSmUpISgDp0k0y9GqEvZnmPPmH5hscm5xefZu8QWpX3lQSlWt4o9IKeAAng1JtvY6MG9o5PXi1jFcbsk26ncSevn3HFJVIaaKyQKTRnotXJF%2FbZVx3CFX106pq5s3bdbQgHWoERuDtwSatSrY3HkceiY3ON%2BZjLFup1BbVYhojn1atwn22iKFzQ35k9IuTGlovfDrLzTbCLdu1YUnYDzCpROtRO3QCm9gOd9miGeXE3FtcLd3Z8lXkk7aVH%2FAIoE92Jad7Lq8TPR4a%2BDmHvguou8LbUE9wQYE%2FNMky3FoqvwvexHK%2BJYe7eWZZX9%2FUylROziZEyfk80CkwG6N%2BPtNJZwTL%2FhP%2Fh7ls%2F94YU4kpBKnJUjZXuASfrTaLbbWyn14t9wvcEOHld1ZG7IQoGCY2VPwehqAqDX%2BCWeGGP3%2BF5%2Bw65w37w6BiScRZSjcICfxGPYTQ27odHj2zqpjGcP8b8VMNet7%2B2aYxq0UhRjV5brSQpB26lMin48jTpGic4taKu%2B0nkHDsTy3lS9bw9lvEjb67hxAJFw7JOkjpxxWiba2ZI%2Fk9GklnjdrmXwzyZYXDKE4lh%2BOPYeQVepxpatSQR7Vh5I0Lx99k2zLgOHZad%2FxK1Qq2s1vJIQQfwjr%2BdD%2Fg0Sw8VoJ5RzwvD7y0dTcJTbLfgJG8Cepok6Yv4m6tkm8UPEW0Xh2DpYcSW3Lgs3An8IJ%2FjxV5sgz4qdRHmHY7YqwWwxBTgectXErBG%2FpBETVehmHBK9ltX%2BM4Xm7FcMccYt3GXnUqOsg6UQNoP1oFN9DskH6NU%2FFrIeXby%2BuXrO3i8bdWShCeUD2%2FpWefkAVq%2FZzhzxlZxnHH3rZKghBnSkH0matZL2jlzlyekVhmjCLtWGKe0Cffk0Lk2BxZBbTAL11ptbjbqtXXmPam4kq7MeWEm9F5eH%2Fh4L5TTt42VFO0EbjrNBkyuK%2FHZp8b%2BnzlK5G9fhfkmywewvb1xu2SVqQ0hIgcbkn3is8szkvyOpDwkuzfLwfvRatuusKbbEET3G1Z3jh3exkZKCNsst5hKSBrgkFUTMf3tWjDxi7RnzZIpE9RjybqEKWQon1Cdk%2FFbYytmOeSTJhc6bluwvEHdbULnuDFdHiqBt%2Bxeyu22ZQEhS%2BJ6UideinY7%2FAMSLCgT6RzsZ60DZcv0O2cxJP4AkI9j1qJWKk2tWGLXHTLaVSFSIEz%2BlVVMFNeyz8vZi9SEpUZEcDpPNaML3sJySRs3kvEVvJYIUlaBEiPeuknTM2XIujYCzKlWiVcQN5Fao2lZz5wd2jXrxRbW43cI1J9Q9W34R3o8i%2FCy4Q%2FI1PwrAfMxVa0o1KUqSqP4V57LN2drHGkbEZdw0MtNwJjpEVnrex%2FOkT5pIQkNzttz0FGnTsFysyUUjaTM8HrR82TixFZPqGokneQanMp19Hgc1qjfeiixbx%2FQ5ZWREypMbjtRp7FtBa2XpA9Kp9zR%2FIyqD9u7ukxInitMp%2BjOSWzcJKDJO%2B54%2BlSEvRUtKyV2bqgUAKMe9aMYpu0Su1dOlJEGdtqbHsVOVaDVqtMSQVewpwCkSm1UCAob7TWmNaM8lRIrVQISYkkDmJrQmJzfxYYanY8p3JHWrTMir2EmxIB0deKLl9FzmmOFEJEgCeTtxTYuypSsUbbkFRSZ6T%2FKnRSoo90Kk7A9RV0hctdCK2gZBGmaHgCpMRcZ1z1A4j%2BdVwKTB62gZhMqO8daYPB7jIAUIEDbcUMo2wZX2Dn7RKwQE6filuNC%2BTBbtmZMpTPtVUVyYMXanokmdj7VGygc4xA2QY96YpIbGlsEP2kKWd0nkACglXoNP6BjtqDqPlhJmDtyKoNO3QOetFJKSBqTuZqgniNHUqUE7FRE7%2B1eXO5Jr0fFWyTMAbTNQFM%2B1gkECE7nczULqzNDgBJUCUxHPvRqLsGUdaF0rClqgzv8Al%2FcU0W4P2LggkayZ%2BakXQtRS2LelRAOw9q0IrmfBYAO0JiN%2B%2FwDKpZTV7R4pRgFWoHnei5sOK0OWVoEaydMjgcE96BBJL7HjbrUrKTA4BIg%2FSKCUWyteh6y%2BkhIBV8Hr8UtpoS5MfpfTEBRHvJ4qRey8dewlb3AAOoak9xUb3ZU1uwqzcARER%2FlJ4qAhFl9QKSQUH9DUpeyJBJl8EiFFKoo1k%2By7HzbxGkH9etVKaZVjkXTYCdwOtDxb6LeO%2BzJFyFEJCid%2BO9XwYLxUKl4HYaTBMDrV8GUooTL6QFAKUU9aixv2FR994QFGSIjaetF8ZFFGPm%2FvAgkGOtMA%2BNCoegxKjvFA4W7KeNmaXoJG4MRBNMi6FscB5IVJJI%2BtGshEOm3gepUIncc0S%2FLsKL3sdtPAJ0gGZj5pT0yn2Pm7gApTqIBEx0o4MpsfNup3kQe1MIOUPREk6egqEHSnU8lWojcTVxe9kPPvKQmSok9hUl3ohl97BSIKlDkQaik0VKNiKrtO4CjET%2FtRLIwVjVgLEMQSnWFGR3Hej%2BVfRXx7sg%2BJ4whAcQXRM7b70mT9mhJMpXHc9nCXluLd%2FZgkSTz7UHNDPiBbPizZOshYuBpWN%2FWOe9T5EMUfsrfM3idhyy%2BlT5bcg9ZANBlkkVKH0ao588T2Wk3LfnEoMidXH1pakmrHwezRjNvjorB8Ru7dvE0C4SdTagswRPFczPmuWmNUd2VRif2jm8VWtp%2B8bbuT6TqVzH1rI8t6bNOKLZo74z%2BITuIqcuGHtLaTMpO8z1pMmu7GZZqEWjSbNWdLt9oOKdW%2BnhUq6Uccal0zC5ordrMaBiQKQpJWdwFczwfmiXj26TCLFtLtWMWVyylanPLE6o5HBmlTjxdFtMiOCYVdu4xiC7VQb8pHnc%2FiAMbTQN%2FYaxSatIvews7m%2FwAMvPPbeW%2FbIDspMam%2BsxULwunUkN8babdxu1DTUXLDKQCSJPpG6u9DJm%2BOJRPX7hFv4d43dOhtq5xO%2B%2B4r4BS22kqP0JP6UWOuLTK5bo1Nub0WeMuNWp0I8v8AETsO5%2BYpcIW0hWXyK6Ipd4g4C82lQ0uNk7cAzsRNb34dNNvQptyI9gDqnr8yoBJ1TpH73%2FNKUvjeheQdXN4bHFnVKUhSHCCZJ9Jnt3pfzTYHFl55dxm0xVrEsOU44lSEaiiN1AjcxVzxzUdkkumI%2BC2F2g8RkWl5bsvN3iH7ZAcEBG0gz32rNGNO2a3JzpR6FsVAscZxC8daFrrfdaSnTwASKp7NVG7mWc03V99jLMiLl8OO4S6%2B3bgOK1KDnB5367dqO6VIfil%2FpZn4SX11mTwGaZxJp9WKW12gNqIPqQ4n8RPtpqRlqmXm6pFP5jwjDMGfwTMeHBNyjEmLpCUtwTqbVClr7bg0uc0mVhxKS2Q3NOYmr69yTiNulpL5bSw75XCVBXPNEopoe8EUrssbB7VteZbS6e8t5oqbWhtInVG%2FPzVfH%2BjNJv0bbZxTg3%2FaGdP8Pv02jT6G7q3t1oJ8uREBfT1E7doo5P6KXjyuzn9n7AncK8PWH7lCW8Ru3nXUDUSVNoVpgE8zuaA0ZYRX5PsAX2Zn8WyP4fm%2BxBT9zbMqtWhH%2FjS2siIPzUM0pt69E7s7gh7DcGeW2EgPPtuK2UVmCB89atdgv9l25vxq%2FwA35H8Kbu7edGIWqVtkkyNQOkbdJAn6Gm8kFHWyrsGxNxV%2BMPedUjzLvXbuufhRPpUPgmKVKT9AzSZbWWbzGfDTxGTev2627vCXS4pJBU082oAc8FJBI%2BtVC3LY14qVm62Ysyoy34neFWI4K%2B2nB8RYTiFuVglB1A7AdQB6YHanO0y%2FGxLi02bL5jxc5y%2BzxgmN4wlxi8RjNzbBSRGhxKlFJnkgpXEGtiaeLYEEo5LvRx%2FtrtrAs13GGqceatmcSK1u7AJVzI6SYArFGCRvhGnbZbeffEKyxzL%2BHWzV6p67YCvOQRyCZmfyqpOtrsfljGS%2FEi2UMTZcwpVzrbbdKipCFLMwBz%2BlL0ZXCl2J4hiz91hGIu3biS0t0OMqAmFDtNVJ0rM0XPokORs5lNkq1UXAyWlpeC%2FwkjgCihJvZshOSQRyV4gvM4lcvXTitNuSlkLP4dzFSW%2BjRKSpL2bY5Wy5h2NX7t1evIdceY1CRPpPJI4pHBPtbG48V9moucfDi1t8fx%2B2MhKbpSUAxskcRQylWq%2F5Mz8bGpFT5z8Jm14XY29u02t5ZOudj80v5NjMmP1FFaYvkBjAre0bLLZCxuqRRZXW4mX46kHsntoscTW2EtKQEwRq%2FCayRzN6ZuxSpbNjLK%2FFjZ2VoAXS5%2B0PsVGB%2BlNa0G5J9GymVMwpw3CLdptxv7064BpgnYddqz%2FFJvRilFmwWXMwKYtmnHnXAlROnUDJ9vb5rXjwSr8jNPDyZb%2BH4p5iEnzSoJQDM7d4roY8aQpQRYycwleWgppWos3ASsz%2BFJFbVcoaFuUVLYGsMxpdcUVqKh%2B6FGTPekU%2Fok2kObrMCGlL815IGqdzR8Jf4M7nvQBez2i2CvLWpW5g9KnFl02J22flKeCg6plJV6vVufagld7LWM2ByBjL9%2B%2FbKKpUSJ9h7U7Dh9oVlhWzfLw%2BBSzb6iSdtoit6T6MmR6sv1zEG7OyUpxRKdM6e9aVVCfkRrJ4g5hTcvOsIUoAgbDmJpPkZK7CwPkyJ5WwsKIdKQSTJVHWuTkmm%2BqOyoa0XLaIShIEaY996uCQyEWh%2BFlZHITEcTSym0fKcTvA3nZJ5qAWNFLVqV6j%2FfSabFRYbaox1QQSdx7zHzRUl0LtjllaVFITJB6zFWA42wuwsDcASN9tqplcK7DFu6AqZJMfrRxexTqiR2Tu4JJk7jitEexU6JRYvwNKlGYI%2BK0uX0LSSJVYvSdOpSj2pqexU0iTWzqARM6SaejPOFEnsnQEplR5gH%2FanQa6FTRJbR2ZBMR%2FGtMOhGRWqQcYWdtwR2mKIx8H1QYYVMGOu9Oj0NjGlseJAJ9Uq2q466LeNL0OUqBJG%2Bkc%2B9Oi7JzS0ZlKF7%2Bk0TdFNJ9Ca0AeoiR0qxEsQipKdinUDNQW8bEHGgpJ3AMxxvUGKIPeYCep25PvVpL2W0roHutwCVDado2mhaAeNMYONahyreluALi0DXWABISOtC0SMUwW42JI0rHTer4MnxsHvswD6dR6UIUFQPetwoLCh154mrSGKaS%2FYMctilJUgqUByYqMCOWmc8A5EJ1AbH%2B4ryx6lqxRLhOyoIPHq4qAcDGZCyY0fqTUBuujLzCZI5MdaNTfQDdHrSyVqkFJmRvz7UwFzTVBBpw6RqUCZ68j6VKFNDgLOkkQTsZ70yMt0JkqMyqdIDYPzyKY3RLtUehUSSEp2jmaDk30Sk%2BmeattylUj5kd6YHwR6lRTwAO1QipOhVt9YMpMgcfFDLoMKtPhyBqBVtFIDcfxsJIuIJBIk81YqUbCrVyNIIASeu9QH4n7CTb%2BokCdMSBO5qEnBJWEm3VSNxH8TFQWEEXBKIIggdOvxUIOQtCiJImeRRKTQXNmZVp9OrbtNSORspbPdauZlXMxuKcE2fBSpBJM1CnIykmd4qAnutYG8RMmoQVLiifxBRNQtIUDhKhO0DnrUFyx%2FQulyDBO3E81CoTrQ6bWqB6oolKg5JMctuGNiJ7nrTY9C5RSQ6Q6dt9J4mhdgDtFzGnUTsRsKq5FpC4uE9CNU8xU%2FIvgzwYmEqCHCnVvHY%2F0pgJi7frEgKTPPNQgIdxJxsLuGVBf%2BZNBGTbIJIxoOJK29JjlJ2ijIAcUxu3cS4C6lK%2B00MnQyMLKJznmheHIU6SkJ6EGTVL7GRxtOzUnOniS04m5aVcJO50yYg9jWbLP3ZoUbNNsx%2BNV9l%2FEH2vvLgtTKgQOPiufPypLo0w8a%2FZXuOfaItnWAl68LLyknQSvckb%2FAMKCXlya2g%2FiUdGt%2BbfH5m8DjTlw6tIEFM%2FP5g1nc5P2OWKMumaT%2BJPiGi9ui9bvqGiW5C4MESJpE%2BxscUFpmu95np9FwtaX1KJkherikW30GpRXTK9x7xHcVb3DNy7qaWfUAf3toNXUnoRlywlpo18xLMarwKSSGQpekq4AFa4%2BPKr%2FAPJicIAW7v3LZ9Kg75iEqEADoeoNFxknyhX%2FAHHRSa0X34UYihvMwwy8KXMPvGCAqICVKG1InblsqPJdFlZw%2B4ZQvncNtG7Zq%2BNmG7hSZPmTvBnttS5rdGz5ZqNvsM5FzA47esOturQPKLSwTAWkjce4q00Kn5EpQ5NDjFbVN9jWJvWiilQUE7bQkif7FHcH2Hj8hKOyJ%2BKCkYfl7Kli3craWu1XckTKVLUoj84Aq8lUlFCYSi%2BTkzUdjEhbu3JcbUrU4QNXzV4sEm%2FyFpclaY0urhD62dDTTe2kbxv%2FAHFbp421URkX6YCw5RauCW1IS6lwJUkHcb%2FPBrK8T%2F1CJKTdUYYw247iaGwk%2BolYKhz7VoilDT2PRPsovlOOYXfIUFhSS06lBEq%2BevFaZRXHkwcibWuycXVwm1xLC7iyWEXCbt1CkR6QkQdWr864%2BWKbtMmLLKJIL90YsbxzyUoabheuZCj1j2pEo7o6dWi%2B8Edvn8PYytiGHiyy7f4eX0%2BVslwpTP4ep5E1OLDUqRuQMuDA%2FBa%2FtLazYF5d4Zb3VsUQEJLaZ0qA5VBO3xRcNbAUkzUoYAvE8pi7eLNswxZOuMkGCkqB9Mck1SSLUGa%2B429b2HlYN5YDrKfMUOCTAJ%2BKFMN5ZVRcWGt3NpeZFxNtAOG3LjGtIXJWiJIP5c0XNjcfkJdm%2BPiLlDELvwhztimVsMRdiyxFt91fmpUbC1VsnUqQFAE9B1G1FOLatBZPL5T4NnK7xHx53FcPwTA7RJmxZ0uEiQFySoDtJpELrZkkvRXWFuJtGrFm6d1t6llKVH%2FNyB9f4UREbQZLw1zH7XB8dRbm6atHHLFbg3Bcj0CZ5Mc0UYu0W4M248UMg4BheT8rZxy4%2Bq5w24wlDq7VCFqdTdpGl1KlfhTBJHvTiXqjUfCXLV28yu0tCipq8S%2BW4JUu3JEkRyJEVnZFFs32Yytb52ybeY2iwWyp63fZuX1S4r0g%2BWERwdQGxp0Itpsc8sU6kVb4cZyxa5Y8OsHzRh9tds4bcP8A%2BGXTqIhCz%2BEE9AsE%2B1VG%2BxU5Jv8AHRvRcZwbvfA%2FHMsqbTa3TN2i7bZQrT%2F8pDxbXI7QUnbpTOT48Rax0%2Bzk74lY%2BxYtYfhb2GvJxF%2FE7m8u7gj0lAhKEA9SIJPzSpyo1eLKDbT9Hi8btjk9yyt2mkYi9oeK4lXlGe%2FvH5Urnav2aMbfbH%2BV3ziVzdYQH1N3Vo2C0CdlJABO3Qnf60tNp7CyQfbJ1bec9li7sV2yypq9GlwpEhs0yTpAwSQytbNwMNWloC35jigiREjv9atPRJX6IhiPm4a8q3tVrDgdAd1HqP4jelS0ZoQm3cjbjwyztdodsra4uy235CkoIVuIH%2B1VKovs68PLpdA1eKDFsVxfFLh1UBR3H7w680t4XJ6ZHki3YMLzS8WYS8nW2UnSoiY%2BlHLx5R2Px5daKo8Q%2FKeQotsp1BcIBHAnp71lzTfQMp7tkWyHk68xXGG1MhRacUEKO8hMyevSlRT9EeZNdl15hs2rfFivDkJ8tACEz%2FpEA%2B1Pc09GOTp7dkvyZia7%2FHrWxW6hTaRxMJ9%2F4U%2BGF9meTfZsP%2Fjja79FpahKktbAJ4BrVHHIKc3FW0TD%2FvpvDmFtKflYG5J69RTFGhCmWVk3NTuJ5XzalTp0jyX%2FAMXHq9t6fCdKjHl3ITYzMxZNlbiisHYyQNJii%2BRLoPjZC8U8SUOvOtNvJWgc6VnYd%2F8AageVsjg2RC5zo66oBD4WSCAD1%2Bf0oLYlNJ1ZN8pXb9%2B80VOFZKgCQZg%2F7Ve5aHNq9HQXwkwdTzlouFattx89a34INKjNnk0to6LZHwz7vaMqCZOxn%2B%2FitcYezBLN6CebMQW3bOJRGwIKiaYAsiNabppzEsUWN1JJ3JFcvK72dDBiSLQwWyTasISI0niep%2BayXuzdF7okqFEwCoDrFOcl7GV9DkOCANQSZ4FIr6EuLMVL43JMcdvei4MnBiKlkwdIUO8wYq1FoBpifmKPGx5jiKtyaLQohajpKSSo7HqRVRm7ph8NaCLbxB3IIJ3HammaSa7DVs6oARAB9%2BKgDV6JBaPTpOkEgn6VohK%2BuxU1RJra5gJPO8metaYJPTEyVslVo%2BpZSRIUCKeC5%2BiX26ztunmYpsGLmrVkjs3jqSQSZO8D9Kfj9ipqiUWixKSfSY61ph0ZiRsLkCAnV0npRic2loLMqI5j86bBiVBNWx6ok%2FhJ0xTF9Azil0P7cHSIIJJOxPFMUfYUJPoeJG4MyfpVTGCakiJIBPaelXCexMpWYKa0kgq0mP1pzmCJKTB336%2FSgINCJ1agNzAoWmBN09DF5rfUO%2FUVIplwlfYNcbAJ2KuvPFEMtDBxrUQJCZ3mqpAgl9EKACQTxvVSddBqWge%2ByvYnY9R2pSV9CufoYLaWNxvuQKtxZHFPYwdAVJKTyP7NFBFcEcz9YIChAKjHzXhoTktI9NBnyXNlphSlEcCtUF7GsWCjI0jtPtRipmUkAmFK%2BNvpUAFEKlREBW3zRY1sg4Z0j0n0jv7f3NOBcV2EgQRulU7xIqGacE3o%2BJJIUQoSe1Si%2BCMdZEySQfrVUTgjFxckklSQODUoqEaPlLHAH1BmoMeF30ZIcPKiT6vyqC54mhdt0jSdjJgipSLvYURchUJCSlR4%2FwBqsIKMvjTOogVCBW3fSsjnbbk1CBJp1KpglM8CBtUKasJNOhSQQozxxUK4Idoc0zsQRxPFUD8YoH9RSR7TFFw0XaSqhz5pWomZTJEA8Cqi66FtfoUSSYIkk%2FWaOMneyjILBPpkkdO1NIZkztG3FQh4FHgid%2BewqFO%2FQolZkc1C1fsVSqCDqG24qATXsWC0ASSAPY0PL9FJtigeVElX9au9BcU%2BxUPhMS4DQqTvojivo8F06kFwBCyB0JE01TYDnQkcXakpcKmHh0Vx%2BdEpsJNvoEXmNMaiFrSF8T2pbA4Mj7%2BaTbLU0txaQRtKtlfB%2FkaJTHQjqgTc5yZYDn7ZIHY81UnZbVETvvEKzsybhm5StoepadW6aoohONeKmDXlu%2BpN02y6gTqCxvtwfaoFGCNYM9%2BMmGuMEC8aUUqKVJKh6Z9uRQSb9Gj46RpV4i%2BIuHX7N1d4bcpavG5GkLEqFYJ%2BRZcFs5%2B%2BIXikpRvGnXfMfCSlPqnjpWCeU34sclt9GsWJ%2BJ6b5DmHOvFq4SoKSoK%2FEAd96VF0Oz4lWiscwZ1Nu45cNXXmzsAs7qqnNmXLjknsorMecnb0OgvpInoeP60KFzg49laXuMPvMB4OhA6alxNQBOyusfxZa3fQsBK9iSrjpS5djIQshrt%2BLllxpDiUrjbedJrf4rlLT2gZ44%2F9IUwpp%2B%2Btbi1eWFPBICITuozT5vGlTCjjin%2BKNpMhWDYcw5q6ZUh9CmwN9yCQDJ781y5OKla6N2OFLRaXjJgDGJqazBhY%2FwDkN%2F8Ax7lsnmBCV%2FltVT%2BysGNx0yrsFxtzD02TwQWrhLeg78xsaWXPIk6aJh%2F3KiyfxC5deDlq75QSdQ9MAyP16U66oy%2BRL8qXRGvFfE2sXXlxRHlMsWDaUhCYCpEgn%2BtaJYpxXKPsmLHCWmatYjdMIxEOMuJU3%2B8DyDPNV48Z8uTsdkxxjqIQzPZ%2F4W9aXCElLCUIcTv%2BKew610MmSL37E36I%2BxcsKuHb0t6UGAsTsDMzHbrQvxufbssIYoz9%2BvbG8D6PILa0twD6TG249qJYUuikqRFcu4ov%2FHWLdK1gJcAIEbQdzQyi0qbByZUtUXC%2Fd3CrpxKVQlKiqJ5nad%2BprmZ8aStML5JUtlkZUZvMXwu%2BTZMK81po%2BbBBCUg87dYNIRqg5e1Zv1beG18%2F4M5cznbPqedsVuAKWsn%2FAOMv%2FKNiPUB%2BdP8AXIXLLLlRaGd8zt4%2F4I3L%2BEP%2BVmPBEJcdaQkQ6gthBSQeg5pU5WqHYm1k2V54UZSevLQsYrbpVhycvpvFKCZSXiSAmTtwJ%2BaBLQ%2FJOpvic33sQXmLxJzc%2BkKce8x5wIWNwBtpj2ihv8gTY7Id9bYxh2V7q%2FcQy5hts5bKTuQFidJj%2B%2BKappLsSoST7NzMKt8SvsOx7LuJOIbsb9ablsT6XR5JKdI7SKqUrHXJM5m50CLbGW1lppHnam3UpMevcUL2MyW3yKfxZS0XWFWiknShRChvqTSZwa2mLNs%2FCfMdjb5XxzJ1wXCHgLtlxpRC0OpOxIFMjlrsfiyJaN338xv45lHCLa3tmr%2FDLnD1WJRbrCfuuIlsqCjtulWkkg7mtClqysc4qdmj2Xbu6tcx2uL3FoRf4DcIVc2a07OW5XJTI%2FdI1fnSPldnVllhWjuf9mWyy%2FcYDi2A4laN4dhOL4iLqwSRqDSHED9n3O6RHsTW3Atcfs4XnybkpI0I%2B1Rke5yh4iYNk%2FBXFowLLqEoWEgpK1uqW4sq34BUEj4FLn%2BLpoLFFcLZJb3GXbnLuR80YU%2BbRNxmBFvidu6koU4pSEyQDwlQGqe9U5V6NGPGmak%2FaJw7TnHBbG3CUsJcubgECU%2Btcwr4FZs7tjcc0t0a7v5pfuby7UhSwq3t0NwTAAQYgUHJrQyXmOrSLHypmCxS%2Fa4kVJt791KkL0rKYOnY1Tmxcs05%2Fo2m8KMVw7HLDHcOvFJ8xmwcugowNS0g%2Bnf9Pk1XJ%2FYWOSu2h7hQwKwssJaumXE4pqefeW4olIRyEgdN6O2lt2PTi%2B0VYLO1v7x7EWkXD7C3lrHmbAkngfkaXDJGW%2FZMmFx2DHcx3jF%2By1Yny0tLKDv0J5pf9w5Oisbp2y5snNJv8u3N3cPqCfOIKp3H9zVuddDHDk7QliGKtsXYEpKAdM89I27cVJ%2BTJ9jlC6RWeaHy9fWzDSjvClTWbNJt2x0scX2i1PCd5NnhuJ4iq21OgKYthMkuL2kd4FaIq4IzSxRi7RPbjDJtS5BQ4EyskSZjih6YE3aoLZAys%2FauXGJgqU8sSgwITtzP161peVv%2BJgny5cS47TAzb2bl6pxa3j7bq57U%2BPKrkwJWu0VpjFvev3SFNIWsFUr0kyNzxVyTYucdFu5EvLrDcrZ3cuEqCVWzKNRB9J1yD%2Bla8bVbMTgnt9lK5p8S3A6uwtFuCEDefzikTkv9J0MUbX%2BCEjNLjYCm3kkKPq3Mil2ykovQ%2FtMy3L10A0SkEiJMwOeKrjqwZYYNaNp%2FCBt1%2B5ZUtZJLm6SZTG8wBTYxvQUYxidevBTCApFr%2Bz7bdenJrqYHoweRM3%2BwHDwzZpSEqUqIFbYvdnOWk2yJZyZBQv8ADwRv%2FCqborHFXaKsw%2FDAl%2FUlBCiSRFcjJvo7ONaomDDQbCZIEcQPak%2FGx6VMclaB7iCOedqjjRJM%2B8xKp3AB7dqFFqaEyZJIG8Hc%2B9H8jDMVLg%2BoDfeaFzYtzZgHJ0kAJ778UDyfZXM%2B1aVEBSPM5jeqU0Bf6CDa9oIMdu%2FtT4y9AyVhO2dB0qSoz1NMFNNEhYcAUkbz%2BVHilUrYElaJDZuiUqMntHatfyISS2wdCSBq1TH0p8UgXKiZWb2gAbqPeeabDsyym0yU2TxlIMH68VpximyVWqtcbaqahBJLZWyYMEc1oQjJlrSDbBT7AUcHsRBu9hVpQBHYUfJXQ4eMqSZCRp%2FQU2MqJfoep0lOwBnYxVuSaAnG9mSgNMAlXt2obXaFHpKCODG3Tmr5MWlK7GxaBUAVH8qYsljBusaDz6au7LlCtMZOo1I2TqG4O3FQBRp2DnUp3Chwe%2FFU5boIGrSRIKdQ545qyA19sq3gx260qcfZAWsATEpV1oCmho8EqKhBBnaKsVKFbGTqQZVGlXtUCxnK1t5UJ1ETsRH8q8gsZ6ygg2NQURCJO5HaaNJgynT2LhKklR1kEgARvFErFzlZmNShJ23jnrVpAikEFJ9M8kEc%2FwC9NhH2QcpEeo%2BZHAoymvscJJJ9YJEQBNQTKvRko6fcnmP5VRcFb2fFxJAClzJ%2FKrYDG4XtE79ienxUH8Y3oQW6SrSSAqPy%2FwB6oFzdmSHexSrqfcVYf%2BGO0PHkKSAeIHFQCUNWPW3gNJB0g8TvFQWEGX%2FTuZVOwnj6VCBe3uBsSRM8TzS3PZAvbPKIGoA8%2FWiU0QKsu%2BkEnfrvREHzTkxCpM9RFQrkhyCABMTETUUtUSxfVI3UJjtxVURwsWQdMgwNuR1q7rYqUGhckmSSABxRc2CKQdIJkH5q4ydksyAmNz%2BdNIYmQY5%2FnUKlJJWKJVtHpSO4JmoTswOsBWiFp5O9Qs98xTcklenqeYqFsSLjTiSUqRHUgwajkWosjuIYs5h6lrU7LEx6uKXJJk%2BNkNx7NLTVs5cKWvQBq1pMgD3qJqJag%2FRqZnv7QWA5cuXNeYLa2ebMlKl7GTtI5TQOTfaKmt0UPm37YNjZ2bl8xjVhcWvllZAWVJVHSRx80uebgujRjxXpGqGZv%2Bo7ly0u3bK6fXh9yhfpcU6ShR7FXv0pa82NWwJwSdMpjNX%2FAFGMNuituwvLlF4JAUeFpI4I%2Fe%2FlS5eb%2FwBLLjCPo1Uxv%2FqGZosMXuLRTfnFJKYC9lpjY8bUmX9SyfbNeOK6ILmH7WmYc3tru27py3uloAUoLOojpPcVnn50n2w8nhzl2a%2Fr%2B0nmhrGV2N7euBMnfUSB9DSXmsH4JR12Q3HvFK8xC9Nwl5aySTClTI6%2FnQcbGRyz6ogGJYpc3DyrpSHUIXJCgPwn%2BlEpV0M%2BbI%2BkR7FMTW7h5OtS3CNJXEaFe9U3fYjJDJfKZRWLY5ctXK7Zx3QsHWn3PX6Glt10Wvy2wLcY0%2Byyi71emIKehB9quE90y%2BKI7it4F%2Ba2FJWFpCk7cH2NPcoJX7LjFdAnA%2FOOKW0qi0chCwQTE7UmeS%2BmD0i7hg7%2BBXSy64lBTGlQ%2FencUKj7JHIr2bOZOetcWxvKdzbnzA55SbhKgRChySexj8qjgdfHmjWiW35Ti2MZgw957QgPOhOkwSJ9MieJA%2BlC0Onli0U3idg8rBrjGrBJWzarLdynktKBIM9uhqIySa7KxxfGH8QabtrZYKFArR%2FqUBvRW7owZYx7snmc3EXFrhbDjqS67hrS0kqkJ9PHtvNdJ8pRSixeNR%2BzWzH1p12qko8pYMK0xv0%2FWgxfJF8ZBV3smWNtXeJZTYduA6UpRDSiBMDb9BTZ4N3RlcZuVIgDaUqsltW5dKnWtJjnUB1PTms6lKDuyvinfYtlR97EsKt7UrcVdW7imSmZMcj%2BlaZfktPY6nEilu%2B7hubGWnEhsF7SdQG0msMsc1tsJzb2XALhq9zHaW7jrhbcISsgRpA%2FsVnk3ewY5Y9I2B8ObtrDLtvC8QccssHxFx2ycuUESlZHoJ9pHNEkjVgyTk%2Bjph4O2F7i32fMw2z7C763wdLuDuKLnq8zzNbbpE7J309Zp6rjRMilzK6yPl%2FGMEwq%2Bv79pF7bYzfPYfcMkghCVJAEE7CD1pXFGik3%2By0mcHxrCcjY9lPCX0XOIJtkrZRcIJ1aNStCSKjSoKMPfs454qi%2BwHO2L4nZ2xbLDq1XMJIAJ5Tv0O9Z5Jdhpejcz7OWFYVne3vsKwu7trbGlr%2B8uWzwCi6wZkpntvsNxtRYcfIvJHirZbt%2Fnu0ytZWmGLacusRtLdy1SpRKFAoUSkxzGkkfSpJ09gNXs50%2BIuOPKxVxtBd0%2BfrIVwJ3n9aR82wuXoi9%2Bp56b5LZfudClJjqY70U5a0UXL4LYkxa5nU7cpRboZZS4raRB0ggzzyaVjbbplpP0bJu4ze5Us8VwRrEHU2SL4YiVjZeoAwEx3Sog1onNrSIvHk9sg2VsTwnGM3YjcWr5bYcYNvcIWYVctEyCRx6SY%2BtKtJ7NUIqqZ%2Bgf7KVg234f4fel%2BzvbawQ0%2FbvKREpQNRhJ5UkykjpFdbx5Jq0ZvLxW1XRqH9ppiyzJn7xQzNdtMN3BdYuG0Ef%2FwBXYrSkKdH%2FAO7PPNTK3L%2FJSlSaRHfEnIV%2Fh%2BL4tlVS0OWQw20xSxeb2StuAQoTsSEpcE87is%2BWDaGePkbjtbNA%2FHN9V5mBrGrRYKNLVwEaf%2FDqTBTHXoT81lyBznx%2FFGluIY1b4Xb4na3Drn3y7uVwQJhsdZPcn%2BNJlkS7Er7H2F4s%2B%2Fh1ioPOLeQgr2%2FcI4356VLN%2BCTbSaLr8Ps9u2V7LrqkF1YaWrVtojqB0mjSa2b83jKUdG0jOKtZnbtL%2B3KkBvUwtaR%2F5FKEkR9aampasyrxpJdiNq3h1hcWrLbji2bdhQKSBJXB5%2FOkT8aNWmaoN1RGrfKmIDB1484RDylrTI2Q2Cdye3O9YHCSViM2HlpEkyVjbFhlXE2H9UKUVon9CO3Wm4ptbGQxUt9g7FMSbdw%2BxUhQR%2B1g%2BkEj5rR5GSMkqGY27B%2Ba8OccSwq2M3KWwkqAnUOazfG2E8ldly5LwxzC7DC8OXqcKAlxw6Yh1W5EdwCBPtWh42orYuWRN7LdVhq1EtKUT5pJ9U%2BkUPH7ZHwfRauBZec8i1btnPSpsGeYPFa4RXaMuSLuy3WMug26ElkjQACNO453rXjdqmYM%2B2Rm6y3aIU7DIJPf934%2BKvgzLklvZHsxssYJ4e5guVrSh24u22Gx3CQVHr8UbjUbEqX56OemYMSK8WuXElwIkgbbpPx9ayKezS5UMrTFXVk2zcqHXuqrcw4Qcixsq277921pDg1HrsCOu1Vb6HTwpezfnwWsli5s0BpJlY0kSYPX%2FmneNfLoXNKjsp4KWXlW9uogJBIPv9K66nJOqOZN2bwYWgNWKQVSNPXanxkqM8SDZmCXFuKVCunzS8%2BSkM8eNPRBGwEk9I4ArivKdNNWKh1K1JTIB%2FhQrM%2FYckqMC5Ct1GfbtUeSxbPPMIRJ9Q52FVzRKR4lapI81KY9uDU5ovkYrJJAKtjB6d%2BtVyCSRgHNiUmAe%2FU0MnZTowDxBUZGocGZmqTDhHVj1Ds7lW0gDbimLIMoKWygkoUVFJMjnin%2FACCpv0g8w%2BTuVJjtPFRZDM1QftHSQlUx7zsK1QlfYiceqJdZPkHdQJBHHStmKTfYnJHeiZ4e96RqOroacKcb7JLZvQSQdgeJrRCRnaJfY3BiFkJB4M8fNaBcoUSi1WoQSSSKfHpGOeNt2iQWy%2BNMHoNuKJdi%2FjYXaOocgdNuPpTqV2M%2F3HrSktRCiJ9t6spJBBrcHcd6tA5L6XsXmAQkASQNjVC3CS7PCggDdJ9u1QoSWolJ3g8DfijgguDGTiCd9Q1e1Nokm%2FY2WnR1Me3Shk6FqdugU7uVxAHxz%2BVL5MIauLPEEDg7U30QFPnZSiU6vilOT9kBjpknSEieRFCU1YwcWQTJHaf96hXBDNxRVuVBNQtKjlEhSdlAAEdBXjVKz1%2BWFOx%2FbrUeSlKdhHc%2B1HbEvYQQperSUztA9%2FmmY7YuUPodJgFMREQdq0xVANPo9DY1albD9RRFDhIQlJMEnjY1AZdC8q1g6DB%2FpUEmCpUNEIPEnv8A71C0m3oScWdRKhB%2FQVA1j%2BxEkISlRSAensaonxDZa%2BQAB1nvQudAcXYmFkyoSBwd%2BKHmMxqhdtwQNwd99uTV%2FIMHTTyttWkHr0%2BlFyRUkmFGVqI3M9ASIpbmIcWE2HlECT779KDY2LDjD4WEwVJ32MzR8WBKSYWadBAISQCOetNXQAUZXqTHJ6HrUoHgh%2BklSZSkJVx8VQtJp9CqFDc6lJ7%2B9HTDlKh0g7HSYT8cVTTKc%2F0LpSiQnSCn5qJWA3bFukgAinRjRRlPYQaKyHkA9jt3qrLPCTIATG8bGrKMFu6N1Nr7bVCDVy7aRKpGniaBzRGn6IvimLWNsguh8I99QmfalzdvRUFJs1%2Bz341ZfwSyu7W7xJLiY0gKiZnor6dqRkzRj2zoRwtrizlB43fbqt8kKxHC0X1%2BEwQy8yUuoA6hSYkHY0p5U%2BmVDBki9I4qePf2xsw5zub5%2FCsSwu8YVyULAdEdxMx%2FOayOeR9DpJNbRrjlbxE8Q8yOuNDFbm0sHjpLgcSUcdUat%2BKpYsr7M85Uvx7N0cs%2FYG8dfFLD7LM2X8xZYx%2BzfSF%2BUsuW7424UCFJ7bg01eFF9syN5L2izcr%2FAPTbzrd3tzlLNz1zkrNwldkm8cQq3xJI3IYdTwv%2FAEqFNl4eNKrs0Ynkkq4kjxr%2FAKS%2Fie7hV1d5axNi4zMhpSjbXAIbuQOiVAbL6R1pU%2FESVoZHFkuqKCtfsZeKNpdFlrA7ll1DLjdw24khTD6QZQR9Njwawy8d%2Bzfim46loonGfs8eJC75No%2FlXEbfGEupbUhTRBKFfhInkUn%2B33QX9yl2Cs2eBedsr3ykY9l66w%2B5YbCnAUEazEyNt9qqeOUR8MiktCQyiXcEL7Q0NoTrKFD8P%2B1BcgzXHNivuF675ICm4Mjp7%2FWiTdWT47VMpfGGk3zH35gBLyJ32Kv9oq45%2FtFY0o%2BiFXy3Cm3DmpKFfj3kA075tUkZ887fQVw%2FDQsM212hLmsw0vvSbEqLfQUsMLYtn3WX2hrQo6UyQAfeglNr0Px4V7LCvL97GMNVbBtCylkJjqFCmQy2gZ%2BMq0WX4R3bysz5d8951ltOlEgRPqFOx%2Fk6M8Mcg3nu8u8r59x51L48hxbognSCCdoNBmjUqR0YZG48Srmcy4jhtzf%2BUtTmHPIP3lk7hxE7k%2B%2FvSk6I1aohAR5l4HLS4SthLhU2DEgEcGqjO2ZJ%2BMyxs14deu5Pytjj7kFtJtXCB%2FlJjb6121FcYyj2ZEuMnZR90v7%2FAIh5QaK2h6gVJ5ofilKXKx5Y7rrT2XRaBtCAhkkpnqB2rRPByVOya9lI%2FwCLJGIWDiG20MBJCxp437VzcvjpOkZJ%2BRTpHuBFVljWK3RKm7dUOtRsQZnatmCEEtBSlJroY42ld3jFtiKko8zzZVpAkzEH9KV5DlbSEqM7olTWOeRiTbqlKCvLVBB%2FAo9Z%2Blcu7tm2GOJetnji8VyAy7bWxaurZ3yluAQhwxsZ70N3Z0YLibwfZ%2F8AEd9rw7vsN1NhGI2Kre7CD%2BNxJgrIJ%2FEOJ%2BtNhIpxsuDwhxqzzJlm7w6%2FtlXeJYdizIaKACt5rb1bmCBCZqc60Wpb0XQ3f3tpn4W2N%2BYMHXfMPrUVaPKZIKFx%2FmEESKCTb6NWGW9GhXi%2FkmwuM354wHLhaukX14tq0dWn%2FwA4SdoI9qU3IqeGTdo10y9d5p8LvEnDF4dcP2WJWly2kpnSAnbUD7ETUhk47AyRl1I2fzC%2FhmZPErH8UauV4bgdxZ%2BchtRCtC%2BCmeZmT7gijyy5T5GOLajxNRvFDL9%2FhWZLizvHWX0ONpKFgSVAnb8hWeULdIcpXsjDKk2jqEW4W84xof1AEbDkR8Vd1%2BJaL4wf%2Fttu%2BtcSw25Atrq8SXEKVOhJAChPsaJKyW10Wpmq2tcLfvcPuMXYDymVHUDttxEbdeaqmOxOT6KS8PcTZy3nPBrp103CF3CUupXu2trUJk9IiiT3RoXiTa5I%2FTX4WYLg2YPClvEsvYs5hF7iVwpA0PjymUra9aWUbAJJIV32O9daH8PxOZncuaUuls05%2B1Vc3v8A9APBnxpsMIJxDD8Qu8JxoMO8lJ0LQsRuhaEmJ61cov4%2BSWzoQwKOeUX01Z74t3DGO%2BFGR%2FFHC8RGK27eAvWzgXchP3ZtCklpJSNz6SUR3pGZOjNB1JpnNXMbtxnHEvKSz93D4a0BKgpJ1CVfBFc%2BUrZUu9mkGcsDxDE%2FEK3wKy1vlvUyIEgJCjqUfgAmaKaVbLjOgVZX8OqaZd0spSpvn8Qk%2FwBKzO10aMXkJP8AIk2D3b2GOIUFBJKZ4kwf51eKLTtm2PkWjbLIONXdpbW3mPO%2BX5ZeAURGrTEmevFNhKnYmWWTegzli6x%2FHs1NsNhTiHVlKxo2bSTEn86GTbDT%2BzeDH8CwvBMvYtlx0B%2B4asUNl0JBSBpkIkdTMmluN%2Fiwq3o1muMGOF5ow%2FLl4p21LjCXFoUmFJTttHc0i2nxNMYJ7XYAzk5bNpthZqIaXdqAB22BjiZ4ociS2V8qT2TzLVzZXjN3ij6Um3tUFxZIkEgQlI7yYrZi8mKj0LedSdLZYWAXxLCLl9sNk6XD2Jnf%2BNDPNy6GuOqLryq41j1%2BlpAKgBAKRMpPO9RZV7M%2BRUbOZawgNNpaQVq2I9X6j24FNx5m3VGaU6ZbwwVCGEKKdymZPPxXSxRXsyTeyDYxgSipT4ICiIE%2Fxp%2FxiZqPbRQnjmpeHZKwGzKAXXEu3awACqCoAfoDSs0Wo0DCKWznC7ZPXWIPXTiVKSpZKjG6D%2FxWJQl7D230GMLwsm6ENhSiI3HHWpJUbsVVpUbFZIy1LjB0qLigB3ET%2FGri6Kl%2BWkdFPBjK6iuzQbZbbaVDf45jvWvHJKjL5GJxR1e8IsILDFuspgJAIEdOK3wbqznv7NrmRotSVA8HpWiEfYifZWGYrkJWpJKe0TWPyOzRhh7IMXJUAASD1J%2FnWDR0I412eB4pTulUdINKlEPhu0fB0GE%2Bkj2IFSMfsk1Z4Xkgp5M%2FTer4IDgzPz1fiAJj60XFF%2FEYqd0K%2FCII7VZHES8yCSkKTB5FJk7JBJ9mJdjbjpJoRiVdCzb2khIIgmd%2B9RFsK29xGkkq1cxzTk1VCXCkHWHgFAAwDzvWhMXJWSKzfAjcBJ26b0yLaM8op9kssXT%2FAJhzWzG2IomGHvEaRud%2BZiKfzQqfZLbZ8pKFJKZmm45GaSpkrw24UkITuffvWqLpWKmiYWrkpEQK0Y52Zck2vQft3CQJBngTTBMsrYat3Of1HFFGNgRjYR1cKjUOk05IYnWh%2BwuQkEbztvFQKx1rGwJJBMGi46suz1ShBBB6wKtQsuxFRkqMCNqYlQLdCLhG4EpO1Fetipu2D3FblO4IO9ImxEo%2BwdcSCoJCQCN9%2BapdkjKkD3VAkzO1Obov5GCH9lEyZ9%2B1JY2CsGOrkQJB9%2B9URJg11yQQPrP981CNMaqXBIAk8jeoUclWHlAwSoqG4k814aKo9dPImGWlyI1DY7ma0ITYUZcEwfSuen8TTk1oXxYQaIUNR%2FEPcU2MrZKkvY7bTqBJ9Ct9h1MU1OxE5NdCqUAxGkwIP%2FFQXyb9ma0QZJ36HpIqyU%2FQkoATqJjneoNhHX7Gy1Ea0jeB0qrBk2uhBajCQEx0PvVS6J8g2XHIWpP60l%2FspyGpUJ9KwpUTuRVWWppCwdJghRV8AUnkw219izbxJkrJSRsDRxnvZXEJNOK9JC5MTTCwm2rYHWSKtWmJ2wvZvBEA%2BkE%2FMR3o4y%2Bymg9bq4II9gKBvZA1brUQNQV7UcWyBRog7GAnp3NGwZt1SHaEAlKY2FWpMS2%2FY5bATtpCZ32qWw4Rt7HCRBkkHaN%2BlV%2FgB96FABM9afGSIZSI3V1pUk76LaPFKSABINVFVtlJiLj7bM%2BYdAPB6UV%2Fspga8xe0abUldwy2oD%2F8VImj%2BRDFBsqDG864Aw46wjMGHNXaQSW33Bv8bUieRLYzvo55eP32ncJ8P3L5o4ylepJ9Vo4lW8H8MmhjkX2OhlV7OCH2i%2Ft23F3cYgvBcZdtiFKSPvBUtLx7lIBArn5sXOf%2FAJND89p1Do5t%2FwD1Z8W%2FErMiLbD7bym7tzSh24X5VtcHgJSpff2rVi8J1dsXk86b7N1%2FDj7GmN5jxTD7jxPyH4VZQdcCQj745fL%2B8zzpuLQJLSusqkfNGsii6v8A4Oc4ZpO0v%2BTvN4F%2F9PTwkwDL1niHhYLXKuOqaSLxAdGKWV6qN0uN3CQqD%2FmlJFaf7hI0Q8WVW3s2%2FwDDPwky94W4yt21scKy0Xjovbe1QpFs6sbEoQZ0fH51hy5N2dDFh1rss3xDy1l7FrJi0xzCLXEEW6vveH3TQOqIP4VJ3CgetYckzVjhWgv4e5nwDH8GU5huIuXmJWQDdwiYcnuse%2B9Ij5PoOXjx9jPMeWMsYzjKMTThtgm5u2yh5aEgFUzvtyRRvK%2FsGWGL7KbzJ4Y5Zet7e1xfC7G6ukrDbV0WhqSOm9VHLTBWCPoqjxC8C8s5pw25tMUsrZ65bSW0PBsFS0jiT7U2UlPTDjjUdnNzxM%2By7hVphuKtYK0gLaC1LbA20%2F3NJy44robijyOJPip4W4jh2J4i80hYbaUtZSf3kjmPbak2%2BjDndT%2FE1Qurd9kX9ukguplcHomd%2FwCNLePYS8prVEeXaB8NoKvMgwoHqDuDUehkZRl2SS3WGbRuwUEeWh3WhJAlJI3353pOScqpDkl6Bzlz5OIKuXlKgSlQJ2Pv81IydbGtKgxhV8y%2FfNhpakpVzPeOvzRRm12L7LKy1fi1xSwdYe0OIukKAB43Ez%2BVOw5E58QMnT2SXxcxO5uscuBiDDbqNKhAMwFdffpWjyYcHsz%2BLK4XdmuKMSuWbp%2B2dSpNsUlCjP4R0J71lbHNyvoM5Ztw7dYi048lBLZW26VQEOASNu1Mwcb%2FACGSzXpFxM3zOM%2BGN3dqK7hLV4WH0EwGiU7K%2BSZFd3G4qP47OdllFS32UKw7cM36l60oUUcf5e0Vhhnak01otKiw02qLjA3r9CW1FTKm1oiShY%2Fe%2BN63qcX%2FAB2Ck3I1mvHFs4g5JUsnZBP7x%2FKubmxPlpAya9BK1vTc%2FdW1KQXJKJ41fnSMUeL%2FACGqbFcVJt8Vs2Hijy%2FLlKR1iujJfjasTky%2FQMur9Dlw1KySJGkGP1rDkwRUbRXPWy6%2FCPGwbrEcFuEeZbvsL0BStkKG8gcdKyKNaNeLI37L38BvEK2yzm9pq7fDmFN3QSttSQQUnY7HrE%2FlVxtGnI2lo2J8Ps5M5N8UmXbG9uF4Y5duOISEGA04qBsOYB9%2BKpyf%2BCQ632b647cJzJiGI5kViLOIO4eu2AakHSws6QfoefeqWX1Q6caf6IRjWU8Pf8WfC1h6xQ80yu9dvFHb1x6fkdPmmRVsUov43s5weO16g%2BNuc8S8s4fZC8LQbXCVIgQDApWbEnthvJKqewflnNBVirtk5caC8lLZcmQRI39hAFV8ZG77CnjLYBGI2t6btu6DTKFJCuSmOf1iqf4spIq9%2FEcOtG7TEUNpdUy2kvgDYhY3EDcxQrJGXZCF4HiSkXbwsitLP3kKBJgaZ3ooyj6ZTZJsy54ubzHHAnEHylJCAFA%2Fh4j52q5ZF0macOdRWgxkS%2BF7jGHtPuecylYPokGD%2FwA1cWbcH9RXTO8v2Z843hwrCsr3KmU4WlDa2gHj%2BydJgg%2FKZ%2FKm%2BNkabUujFkzcm%2BJsZ47Zcy1l37LHis1dpubjLbmMINwttsOeU6tEhUK3AMDccQa2xTeNivHyTnn33Xs57YzjFrgX2Y3cnLu1F3EHbdaVFQ0NNpMhSSdxPpJ71jnBex%2FkeNc79GmfhTmGzwvONmjMa27yxa80PBSdadOgp1ADkyaTCKe0xOSLXZr68E2t%2FnfNdshpH3WxfsmFkbF506ExBnVpKjRyXoUmukUNhzL1uywpKIQRp1H948E70hxa7CaD1hfJcxJCQ4qUGCI6iOtXFlpM3I8LmLC%2Bw3GbvEVIbtbS2W4fVBcXGw%2FOKZ%2BJtxtcdlqeG1lrv8KUtQtDeuJuVvDYIaSequnWs%2FwtvRqUuqNx%2FDlWHYld5pxK%2BbdxOwtXTiCW1nZbCEnTM9VECjjhrsNxt7IFZYLZZtzhfZxxRv8A%2BakKCEBQlLhGwHsKGUYt9bAkkno1szVl%2FEDmAWSXQpltap3kJ33NMWGLW0WoxLSucEew%2FK%2BG4BYqDS7gi6vlACYAOhG3sSfk1JYYqNJgQxIlTabRFg2y0%2BdQajfvWXHF3sdJ0qTNkPDa0t8Hwmyv2G1T5HqUr949%2FwA5pGR7M05Ns2ayItT5acfUgKeUZTPv%2BlbvDdvZnlFuVGyf3dtuxZBCVriK7EMXsyShK6RXGZbc%2BSWkt6rl1QbSkGYBMD%2BNPsxztaZrZ43YaziuLXlkUKRa2Vs3aJCTO6UgbHiSZ%2FOs2aW6NGCFq2aJY5Y2eGeckJJUdxP7orLK17NmOKsY4M2hx9IH7VMkjeNp4oI9jmvRt14a4E4v7ncLkKUrYT05FaIYkySSirX%2FACdNPBXLinE2qlJWUACD0%2BlPWKjDl8ly7Ol%2BQ8KLFs0tKVpA2gjrW3E20YJ9lkYjeC3tlBJiE%2FlRsW0u2Upjl%2BFPOJBPUGTzXNzy3s24EqtkeLx0kgFII6fxrFbNfNGIe1SZE%2B9SweaXRn5hVMkjf86uLouM7PfMTsAskdD0pilYXIyCyo7LUmTtvV8kROzFToHqie9BKX0XYmpauJPPU8ClkPNW5kjnvEVTdK2RI9Dq0nUrieT3ofkQXEJMXUDdeozBM70YuXQet3tkgKI%2BT0puOWxJIbJ8%2BkFQ0zFbVsTJbJhYPAQQrc%2B1asM3Qlw3SJZYvevcqIO23etMWZ5RJlaOg6pKRtsD3pkXsRkWrJJZvgFIKlA7fStcKapiiY2DylafUSJ5707HSEZIRaJNaLKiZ%2FD1pxjyY2noOsORpkgz70UWLTphhpaY9RBVO21OsfaocpUEEySSTUWwFKCFkXCJgmT8VdhfJEXDgWJB9uKbDoB5PowWoQoSO3sKPiC5saOOQQAVe%2B29BJtPQuUtaGC3dGo7JgwB3pQu2wa86lOoayD8fwoo1RXFgl98SAFDY9apsKMbBrr%2BoqP4TA370Joxvj2wVcPgAlClA8n3qF%2FIMXrgKJnYnrHFQtO9UD3HUgKcKgFdOm%2FeoXwRyUYWqDsraAd9q8LGVnr%2FAI0GLd4wASU7QD2rRFtipYPaYZYWSUkEdo7D2pnBiJRrsNNAwFEGDBPc%2FNNhH0Lc0PWyYKwFkK2IJ4p6jSM2RaseBOkkLhSd%2BmwNEKSo%2B0iCElMVTDjOhJRVIAAA6D2qxsXasbPSFHkjiQOKjLGS5iSnSAOsiKghqnQ0WkQSoaDuOKVN7KGzqAohIBg7A9aVKFlqNiAaWOFiR7%2FpSqCcGPGXEoTqlalGKlIOEH6HrLikFJBBTv15pkH6HuOgzbrSDAHqj9KalYiToLMKSJPvx0qpKiRdrZIrZRASY357VQuVJ9Bu3J9IKRIEzJ3pkJegQywTIAXKus0wg%2BbACgCJB4JqEoeoSCSk88c1QqUnYqAZAISUzVASdmUbgAGep4oov7LUWfSCSJ3FG5r0RoF3jy2ol0pQOdt%2Fzqm3LoiIzjuMWeFYa7iFwU3LQHp1K5V2%2BanEOGO3s0J8YvHvFMIscVu8KssvptG0KJRcI1HbmCKy5cjXs6ePBBujgL9qj7XiPvzzFxnJvLWIo1K0WTjqvLn%2FAEbJBIjrXMnllJ0huTx4Q30cgM8%2Fa2zpiOJOW3%2FdmI4hh5VAfeSCtHO%2Bkd5rRDHF6ldmB5n%2FAKRjlH7NHi945YnhWYMIvn7nKN2f2t82uGrZU%2Fvqgx8c11%2FH8Vf6ujPOTbO6f2V%2FsA%2BIGUMKsl22B5E8RkpSkIcx26ZujbGZ9DcSg7yNyaLNLjpOkBgxRcv%2FAHY2dl%2FDvAc%2FZSw1jAPE7wnwrFcslIabdsLVC%2Fuw7SVE6Z7QPauZKCj0bMeJXUIv%2FuXnhmSsv3YF3ky7uMpYwgDSpEoA9lo%2FCodKW8bmrb2ab%2BN8THMJ8TsOadsM22OHZhtyQpq4bbjUJ6x1Helyx5KovHmttogDGZ7hlTWA49d%2BQzJVbM%2BYCtpYP7iydgexqYcaX8hryWqoij2H4bY47f5py6%2Fd5ZzChpaLlK0jRcN9lhJhUTsRxNFPw01aDhli2lXRDsV8VcwZdxnBkYiwpTWtK0voSVNOCdoUDt8Vhy%2BPNdmx7V0TDP8AnhIw%2B5xVpDyGilKigCQFjc%2FTeq%2BN1YmE1dMptPjAi8wq6uE3Kj5SoUTvB%2FPjnaqcmldDHJI1Q8RfH3CLPGU3Cb23Sl1st3CY2BPt3rNlySfQcslL8UcqvGLNGFKzDiDOi3atnNS2SBCChXI%2BZ6UuLkuxLinto5tZvTbWmbXXmwg2Sl6QkwQkdpoJZHZdIimN2NvhjzyVQlpwJLa%2BCn59qizNFOF9EPcvX213CShClCAoneIG29SOR8ugpY1VNgi7uFXgKbdxJfEbcAmPetCn6EZPGaVpjXB8ZGE4kj76FESEqT235FMcbEY5uDqRaP35NvfsYjbOIW0dKlievO9LceLTRsjKLssPxJxJpWMLcK0u%2FeLRt5CQehSDFP8AIk5NWY%2FHdJ0a%2BYtiTaL5CkElh5vQvp6huIPes%2FxjV5K9oywvGSkg%2BYtCwCCAdnEzwaOOlQLnFu0y2vC7Fxe2%2Bc8uoc0s3LIfZTH7w5%2FjXW%2FprbbRi8tW1Iij7F09cPBhlxbjaIWpKfUkDvQeY3JtV0OS1ZIMjPOKGYsKU6S%2BoDShzjcUPjZ4Qj1sknoqzGMLtbPGlMLWpy2WtREHdtXYHpT%2FAJOW0Znjldogrtu%2Fhd3LRXp1agYkxP8AHegUl%2FrE%2FNLqR7mC7fQ%2Fh1yr1Q1sTsR706EINa6H4XGqIviN0WwFIb3O8dt%2F96V5GClaDaS2TzJOYlYff4VfoLaVNr3B7cGubLsHHkvRIMPxY4djdxdtJWAp4upIMhW8%2FwA6G92aVJroubLXiQ8jErDF13IQEEocET5cHcgfFVLYa8p2dKvAfE7XMGM4XbOXzTtvjuF3bCUh0IIUk60au5JTt70mPJO0dNZJOJtw%2Fc2WL4vhGLWvlJuWw20pTigkLnSlUfrv705OTewODapmpH2gfs9pzdmbxmzThtm%2BwzaXlusJTB8sqa5HTT703gMhFS0zmviSncqJw%2B7DpXcL1JdSofgAMQRWWUmn2DLC0XJjqLi%2Fylll27fYN7fIDSPUDqSqImg5bEvTpmu2a2H8LL7aHlwAUKSTuSO1BGD2HGKYrkFm4ulYg4UBZRblwSqQJ%2FmOaPHj%2FZMhX2PXLmG5kuFOuF21MLUSTuY6fNPUEYZ%2BS0yzvDnHzc4pbt2BSlx0BoKTICZ43HG9BJSQ7E4zdUdyfsbrucewHMV1jVxbIxvBrmxQppRgvtLXpC9X5iiwybls6j8ONrj7Or1nguE5wwbxQ8OMcwW%2BvcCW04LizS4Sp1wNkgwN%2BCDI5rtKKkqOTmlOLU06bdHDL7Rjqsr4OjKdpLeGIwhvyQURqAVpM8CREbVyc02nSN8blSmaP4PjNq2PKWC4%2BW9XpVpjfaTB7VnUvofnwwX8RfGsvXV7hmWWgp22wvFcaQ06sbNtuKQqNXwJpsXZz5NJ0UJmJty2vlWzbemwtXVWbRPEIPP15oMl%2By1KzLL2Cqdt7jF5CW1PhsIUqJPJPvtU4asaofZsjkDXf5dxxu30hxkqSpITvp0jc9xJ%2FSlkeN%2BkXzk%2B0xbGmsFw7DB94vQGkQ0fUhrdI24Emdjv1ocvJ%2FwY%2FB4uS7ZtLkrHbhkZjwtpKGCppFoqIjuCo9RzHvQrI3pnQcGlpkquGsNwLDMKDKlLeTqdcIX15iehNN4atCl2VdbZeVit4rEb1plKFuqvLh7VAQzMpQPkiPrSVkf%2BBkoUNXPPZs7u4vXUl9alhKAIIjgD%2BFC5t9jccLY3ZurCxw%2B0e83%2FAOYv1PaxsjsBTcUWwpYPyNoMoYoq6ssObabUlpyHQkiAlA6Ee%2B9BHA%2BX5Ijjw9FyeHmKXN3mpi1tpVbNI1Ob7bq2FascYJ1Ey5Mke2jch19tryEaIWR%2B6PwzxtXUi2onPlOndAa1ZbexFzEnglxu3BdlQ4Kep%2BtXDJN9GSbT2aY%2BKuJPKfubdBLt26tSySByVT%2BgpOWV%2FwCTTgnFo0dzfh167cuAA%2BUDuNOxPzWXJy%2F0m%2FFiTJt4a5XcWtFxehJKVDaTv7D3rLGLcrYUsSWjoH4UZQubh%2B1cW16ZEf2d67GGOjm%2BRkV8UdQfCnK7dmwwoICpCRsNuK28bSObnbjo3NwVn7vbI0xtt2pqlSoQ5MBZjxINNuIVsNyaRkyUhsUm9lN3V15jxUFTO5%2BK5WRW7s6ahoaLeJUSYI7zFJdIpwPg%2FII30zyOlBz2ClZ6LnZe4jjiaMJxa6FvPkRIMREUa6Df0xbzT6oAA9tyR80BIxowU6lQBIAncyeKgRitzkbd%2BahBLzVEbkb8Hk1CnYoh7c7K3PJE%2FlV0XKDSsdtvACZAEztvVEDVq%2BFKGpPNHGVbFSi7tEotHj6EqTtwTNbYT9i54%2FZMLJ3UEyRIE7bVpxSdJGdS9EtsnJIkyo771phZmfRL7F0gCdyKaJkrVEntXCkk7gTwk0%2BLESjTJZYXGrSVao%2BeDNaUzPLsllo9wvbf%2BNOhKxcrokFu6DpJ3I7mjMKC7TkgDUZ54mmKV6GKWqHyVBcBRSk9TRxVE%2BNmUyNQkn4q7AdLQqlxQ2KZPIg0cci6IfOPASCCU%2B9X8n0U0MXblStgdMe9A3ZSiMlvhR%2FaKnerjJLsugPcPKKiOkmKpsvsFuOFuSrf2qg0kv5Ae4udlAKJTwDNQqbtgd99IJCyAI6HmrCWMHuPkpP4USfz%2BaoKMaGi7jUmJCiAINQI5QsvCADO26fb%2B5rw1HsAsy7Cl%2FuokJ%2F4puKTTFT7Dds6OUwT2J%2FlT1NmQOsKCgCFAgdANqfFiGqDDZJKUxyeTTgJ9McTJ2kDkiOd6gkzhPCQFGdyDUIJFMhIKiSeOkVC7Y2Xqkk6lbSBFQZFP2M3STqCgACY2I%2BlVJWE0hmtMSAkkfO09ZpbixCGjgIgRA6%2BwoGh6QkPUd1ahyd%2BtLnFUWKdjBImCO9LSsu2PEbEEphPWriyWwrbqAKQoyogVoj2C2vYZZWdwCqPpvTXFMQnXRILValJ2I%2Bdj7VXBFtsP23CBwatRooN2%2B52OnbvvRECrRUEpAEnnaoRj9I68CetRGbtGcge%2FehdlUeH0pM7frROVvQVgu9uQwsOBQSOKpIONVsG4jf267J1bywCidgfUe0Crb9BOaXRpn4058Xb2dwhONWOXAykuhb6zB7EpMA0rO%2BKsZhmz8%2Fn2w%2FtGYU7h2J4Vi2YScdKCLW%2BsUBaHkiepV6fgzWHI24crNcJL%2FS9n51fFjPuYsw4jdMt3bWMIcMAvJSCk9wqs%2FitKQGSM5P7Hngz4W4vnjFk2uMW9vdWD58sP29xp8lR29WgEx8CuzhnUlZhzco6Wmd%2FPsp%2FZB8TvCdzB77IviDhOC5WuIfvbN5oXLT4Unl9l9wKWCAYKQI3ineR5GH%2FAHBwePmm9%2F8Ag7aZFGHYBaj%2FALfuMqYhigSNVv5BZa1RuAPUa4UvJtNI60cHFU0XRlzxDzim2Xa3GEZMsrv8KW7e41oj3CtwaXzfVj5xivQTdzZjSHWrXEraxw9bnqF1bqQ6wT2U2TKfmtGKUloXHjeyR2mcL42rmE46wLe3A%2FZ3LS9bSk9%2B6f4U9t1YMkk7RQvipl6zx%2FDnQy60LpJUW1kASPkR%2BdJyQ5dBwyL2jVrD8f8AEXC03OWcVYvsx4SkKNtiGtvz7Af%2FAIbgBClCNgog%2FNRxklVhvNFbWihcy32dcm2GJ32EYrimPZdUFufdrlqTbOblWkzwd%2Fj2ms2SLrsmPNJ9jJv7TDZy9bYJj63k%2FeGgu3U5%2BJBA3SsHoRwaBz1TDcH2ls1qzj4rX%2BX3b8YDiDL2HXKm7kAr%2FB%2Fp3%2BtByb6HY7%2F1Gh3iR4oOM5nl51btotZXCv3TO4niKTK%2FRom9aZr%2FAOJma%2FMuLdDdyt62XCkrVMhKhxVSiZ%2Bkap4vev3eNG0SFvap3BPqj561lyY%2FZcZp%2BhxjNw%2FeYG4y6Q1dtp277UWNxr8gJ3WiB4VeW9829Y3zvl3GkhDnOrrFPSiZpOUXs9scLu7t11y2dcWhmA4AR6ROyjROkSEZSdNkdx9a7J1KnIK9W0HkfFMxuxXkY2nsOYHjqFNssOlTjSvQocaex%2FWhd3TJGRamcHvvOH5TxIhTmq18lUwd0mI%2FSm5Mf4phRddFF319ovLppYCm1HYkboV22oYw0JlNjWzeJcCtakqBlJMwauS0SC2WP4eX%2FwBzzRa3A1NtrWGlwSI1bGad4uTjIrLG4tGwdrhjuW88uKdRZ3eF3tq6yCo%2BnWU7KPwYrfl8rj6uxcZNwr2RDLloxdJucSQppF%2BwV27mkDUYMiT80GOUJehmRukkVHmFi7usWubhtYaW6dk9UOe1OeGLFfJLp6Ipiy3TYuOPIDd2hX7Ub%2Bk96COG%2B3ZSwSfQJxhXnWGHXSIcSWiCR%2FCi%2Ft4V0A8W%2BiGPvl2zSUtrW6DJnqOkVlSSe%2BgowbH2Wrws3AU5qUjXukcCelBlhjatBLHRLnLxpd0kBS2kEEGIMRWTiuhnJj2yWgNJSi5%2FY%2BpWjoTS5X0aMUIPbZvLkzNK7LK%2BQscwV1bFxaXAQ4pCoITvt%2BVAsLvZt%2FvIr8fR0m8PMQuM4YI1jrKnrS0s2k6k6tSlKnqY239qck0MWe1%2BKNzcQwXA38l4zmLEnGFs4nZKCkwAAkCJV3Ox5rQ2lExOORyo4P8A2qcn4Vl7D8s4hYrQV3LjpXoRpHQj8hWLJFejfwa7IHgYcdy3lzFXVKesWFp0oUd0wOf1pShJqn0A5b0R7xAwR29uvOgJZSnU4B%2BEK%2FuKiTimki1JoCYTh68Ow%2FEX0vFt8pDSBqHrETRY4NJtguTZSWa7ly8S4hT5deaJSSDtHIA79qdjddmHyFvRYXgHjdvhmbsNbv7Q3jBUQU6ZMx2ocv6D8SW6Z2c%2BxZnSxez%2FAIzYYhb37djeWyGLhSladBSTBBPckbUeGaTtnajPjDTO3uR27nLucV5ncfu2LR2wcaum9Y0PEJlMzvIAO%2B1dPHNN30c7JPn%2BLrs4L%2FbozRh2N41ijmEIcs2kvuoaYWg%2FtElWoKHYSTXL8iNO0zROLpJrZz2w60efesWEXLVqpwBCugSo96z8m10VGT7L%2BcubvHfDTLOWLC5Z%2FwC5bfMQJgAhCEtEeYevU70xTpIG1JvlorXOOXWL7w8yNi9rbfdWrzDLnEnCpI9bpuFN%2FiHOzcjimzdozxjUn9FOhasNsbHDg4pwSp9adXJVG%2Fttt%2FSs7yPpIc5M2j8GLFJwrHrpxUC5tHm20k7ayjYzzyKuEXdmnBkZsN9n%2FFDlrKniBnu6ZDTNth3lWylNlfmOwUAz03UQPrVStP8AE6fOUlSFvCfH8VxdxTz7Ljl048ytTQHpWobAr9h%2BVOi6RfOLLsxLLmMYi9ZYFZMXCry78y5eu%2FMhu2aH4lHpAAO9A8zZOUSaYbga8Wsza4Wv%2FwDL2R57roSYDCEwgwdzJ3B4Mis8o3sdBw%2FyBbrCLC3sXccxIFVszOlDm2kHgn3MTSOa6HZIQfSKnvFN3gcumrVSLdTggkbRwAP40zaEOjZLKl2o5cSLaVXcpTtyBHHxHWh8iUuP4%2BwfybNgfCL7vh915l0qVOE8fup7UXhyjFXLs5fkxlFmwuFYq%2Fit0tYcWi230KCt9NdXFk5dGfJO0WBfNNWWWXVKDvmXYJQOD5YHPvv%2BldGKSVGaUORpNnDB3ri8u7p4AeYCBxxWWcF3ZphjjFUa85nwQoegMJYEyRP97Uik%2B9m7G6%2FiW94WZYF24y48xrSIUUx%2Bk1WPFFbkgLk9M6KeGOAsspYQEjUIGo8Ca34Wn%2FEw5ZKL2dCMhYSi2trXYekcnp8VthLVM52Sdu2XE46Le3CpKYT0pjSFuaKdzJia3VKAcKRyQTwa5nmT9GvBFPaIN5qVqgKIJ965Uspuj0J%2BZ60%2BpX9KttD1Cuz4OqSoHeACNutUpRKcE9nvmwBJJ6QTU5oHjXbFkuwEpMETG9SVvoVKH0OA8N%2FVEHoakU%2FbB4yPC6AdRiRttwaCWZJ0x8Y2eFxKiU7p3k7fzqnOxigY%2BbuAFafeeD71akqpgOLs9DxQB%2BIk%2Fp9akuNaYUE%2FYu06CRudjEHrRYnoqcdtroN2zxIAJKQPpRr9gNEotFlSUSVEgflWvHJVSM8r6ZMbF9XpSSSO%2FfatGNuzPJK9ErsXdICZPPet8MlmaSpbJhZPzoQNt%2FrThDRK7V5MBBCSobjfmrTAbXsklm6pRgkRPeI%2BK2QeqEUSyydAJBABnf3p0JUKnFklYeJKYme1MTvo50oqIXZeCSJkJ2o09gw7TCTa0KAEk9KZzRpUr0hcPFJEE6Ttx1q6TM8qT0YruVCBqke3Wq4oqxqt5Sjv%2BLeKKi1vobrcSSStUiig9luNdg555ACwgqUffpUl3oXFOwa65MxG%2B8zQj4RfsG3LwjaVxvvUDaI9cvIbiComeJqAySW%2FYIceUSZ1GN%2FioL5Ng514SsBShtFU3SL4vu%2F%2FAJGbryZlWsiOSaH5P0CpXpHLFKgkkKCQQZ2rxHNHuApbueqVbf5Z4q4v2gZvQbtXvUCoHSOBWtv8UZskfaJFbOBRSJTPcHinIySv2G0K9SCSDO%2B%2FSnRlYEnphBBUQIiOZBifmiECpAVG0QeoqEE1k87%2FAJVCf5GbpA7atuKgx5V9DNwE6k%2FiERxUC5X%2FABGikFUAk7dulKk3YMYDRadCAIgjfjY0uhggsEmNt9u9WU0YpQtLgOoKTv14NInVg8P2EWTwDpieFHirgrYYTZ3PKTP0pyKtBe30%2BkQEnrvR8m%2BhVokNkRp%2FCmDv2NXyfsnH6JDbCICePjmmAhy3B2UZjiKhAo1O0L2jtUZTCCZhMwNhtHFUZ7Pjr3kkAnaBRxinsa4qro%2BUFFJACSYjfaat4mhVEMx1%2FwC6By4UhxVqBDgAkt%2B9BVdjodFRZkx%2B4w%2B2Xc2jq1taSpl9r1EDsR2qhiVpnNv7Qf2xsj%2BHuH3OHeJmCvX2GupWE3VsyhwAj90gmWydvas2XIzV4%2BKHHk3R%2BbP7YXit4ReJDF%2Fjnh9fN4FZypSmbttDS3FRyjSfVM9BWVzlJ8UtAccXL8X%2FAMHDXN%2BOXjl%2B8kuAgqJkHYjv%2BlacWHguhGbI06TNxfskeIWe8h5wwK%2FwLF32LYrSrQ4o%2BU9vJQ4gynSe%2FSryz4xtBwwvI1yP1yeAnjoMcwmyfuMtXVk6pA83ym27hFseoGv1aT0UCRXGy%2F1FXTWzs4%2FBSW2bcWXi%2FkQpeTiGHMKujI8w2AlJHQ6YM%2FFYn5kU7pj14rW7IZmXxew9di9dYPhFhiLiJHklfkkp%2FwAwJkn4HFA%2FKT7RfxP%2FACU1efaBsXAU2WKPZdxActP%2FALRBA5TPUUzF5jsGS9NBLBvtJXTblum7dsL63HpWpt0ehP8AqSCDB710cXmSeuzJOMV2HcQ%2B0O5bNXF7guFYdmKzKCVsC83TsZBQQT9fpWiOeT2kLxvH%2FqNVs6fanwZ28Q%2FaYFe4DfaPLUFSfKP%2BUHqOtKlmk%2BzRHFDurNX1%2Falx3CcfxZDtz52DXaFtusOrGkL%2FAMyZOxIpTm2MXBaRrh4o%2BJWG%2BIAt77A742mJWmoKbCglQj26ikO2yc6RqVivi1jSmzZ3Fy4422Skwfwj2o1j%2FZz5%2BTJlKZ7zdfYwlCEvEOI2n27%2FABVNUDjzNsZWt1iOOYM3aPtl68ZQShUGVDmqUW0aP7mKdFfXFy27e2V2y06i6ZWNe2ySNiD%2BVK%2BMesiYDzvfXNkXPKX%2BzUdaVRHPQircBWTNx6Kgw3FfPv0ICSh1KpnmPem8EkZ5eW5viyWt4xiuCYutdupTaXG9K0gwHUk8EdaBxv8ARMedxdJWfZhWh8uKebbcbW2Fp0%2Fun5osUaL8mbdEVw5x1i8bGpKrQp21GBP9aZKJk51IvbDbuzxzJV4yHSt%2B0WVgDlKT7fNMjjco0A%2FIfLZQGKOOW2JaVHWjWNRO1LV9MYpJ7JPgDjdxcICFNizUqFo%2Feb9xQzfodDok9jh7lriFxd2D6nSlWqE%2FvQeSPpQXQTp6Nn8Zv28w5ZwbErYhq9ZZBcAV%2B9tMD5Fa82TlFGdyqRQ2VsUewzH8WU6pJS8oKUCP3p3NIjNxemOlBPsa5vTZKxdxFncLT5qdQP8ArP8ACtEfLkn9lPFH9FXY1iJUsKdbZbui2GngNkqI4VvxT15kuqLWSlSMFWr1vhlrfPLt12LqS2EB0ajB3OnkDfmtc8mvydMzSybIq%2ByW3lOIVDKhKN%2FasTtutMF5H6GbIXahN0HJkzIVz8inPFEdypbHRxFVw5r9CCeCrr7EVmliV2nZSkn0G8JxRu1uW03UKZEyCdwehpORN9hp0zZHwszBfPMvYC1eMtsrWtbaXD%2B%2Fzt2kUjfQ9T4o6i%2FZE8XMPeznZ%2BGuL3K2bC8wxxp3zI9NykykJ9zBq7p0a4eR%2BFJG0mI57FnkrNmW7lakqsXDbKYekLhZMqn%2BVKxylTkx7nFtS6Zop9o%2FBXM45eyhhpShKmVFUtpghMBSuPaB3onGxk58kacKx1i0w1zCW22ihT6W20KEqQjt%2BlJcdWLpLsI5lxll7ALm4tWyhaiAogfiUkAgTQyk%2FwDSGsiRWOE3Tn%2BHuG%2B0v%2BoAJKtxqHSmQhJ%2FyMuTMvRHsTwN6yuB5KUutqCioKGw2mJpjVIyK5SEPC93ErTOWH3thoS8l9EQJmTH4apyvo1eP43B3Jnab7EOFJzn4su4Y6wy35TJuXQ0qNQSTJ9jJBiqx4m2dPPOKhZ1jd8Y7DL%2BbMPytjd%2BbOxuUoYdWuChle6YUTsBxt0rU8nF8TPCCceSWzgd9ofHXMRxHPLS3heN2OIKZt1I29KlEz8QKz5Jt7o1OMslNI1QRixYw5LrS4WggkK%2FEvfgf1rF8jMvwTT2i6cuLxBuwvbmxYZaubi2Q6yXFemQd47nf9K0QVq2HlSS2F04fi2bcr5KyhZOOsps3H2UpZb1fsG2xBJ7FRcVWhxtaM0mkkaxYmFM47iaFFbyUOKaaITBIH8BWfjTKfWjZLw5xpTeAsKHl25Q%2FKtKhqI7RVz0Pw2tvRZF1mfELfLJytYuuCzWwElCl6UpQCVGAOsnmlylKtG7FKPsm3g1jmK3Fva4DZtpaecuGjdPoH%2Fjt0yoif5dZ96HHOa72aHLHdI26usyXGMi4t7tKsNy4pstOqnSpTSOQuOZ4A7miSb2gnGPXsK4H4hu2mX824Vh7Vth1rcFtpTiT%2B0daSR%2BzCuQNht2FLll5LiyljV3ZVd3m1rHH7q1v3FKsdZdU0kyVIG3Pv8AwrDHBK9M6WOMX7FrNxvMb1la%2BT93sUQ4LdkDSlMwB87fNbJR4oOUYw26Lnwa9whF0nBMNKFXKzs3rngRPseaxLJNPRj5O2yzG7a7wW9Q3aOeZcrAQlZJAAO0RTYzcWC%2Fy2zbHwmwZ%2B7U3Z3rikyAp1YB%2FZtjk77Diu%2F4cNWcryuP%2BkNeIuZVC78q3ARbHS0ylX%2F22wYFPyZnF0YXir2VPe4eH7Vx14oUhIIJJ5V7UuU4tUiJPooTHsJcvb7yg3oAnp%2BEe1IlJro6Pj4pFx%2BH%2BEPlVhaWjQSoJAJHQT261cW32zS0lFs6C%2BF%2BFarllKUrLSIjauh48FHo895km9m8OV7dNswlbxStcTv%2FAErUYHtD7HsXS0y5tKQOJjepOXstQKKxjEC%2FcLjSJIrkZ5typnZ8XCqBqXwlJWDqMgxMfWuca1FNiK3fMMqISY78Ut2xqSQslyECVkHbrzU4tIJ09o9TcHfaNpkb1Iv7BnH6Fkr6qVE7xz%2BVMWVJUBwZki5lRhRG8CZqfJ%2Byvi%2FQt5pSSSkJMEHbf86uUr7AUaZh5kQQoRt1onkbVBpNnhuCCTpClRAJrNPuglBmJcVPUzz1mhIoMcMvAFIHHudqJTaBnH0GLN4H1zqJ6RWrHJtbFSjolNm%2BUkCQU8kfwp0TPMltk8dEiUrB5rfikjPkW7JVY3JlIE7dT1rTCddGbJBvol1i%2FATBgVqhJsVJaJdY3BIQNQ3%2BlPjGzLOLbtEstXCVJkgJ3iDzWiHYrdkksXzEkp22kzNMYE5eiT276ikbgk70UZtIU1YaZemBsZMGnoy5YpMJodKVGSQknaoKHaHwSSQAZ6GmKfoYp%2FZlrAGxBPXfmi5ovnEZOulGtSRpT7daImRaGDrklYKoA33qlLV0KGK3wkD46HmqUrYeN9gZ%2B5cSDKyY43iioaCn7id9cKHHtULpgS5fCwdxPT%2FaqckC5LpgW4dCVEBZIIAAHNC5%2FQpyS%2FiD3LnaSpCt%2BIqvkJzfsHqeM7HYdT0qcy3PVUcyCSkggaT0EiBXgpRVntRyy5uFELknfamwkukQO2ytyQkgkb1phOtATSa2SG2XvoUoDfanwj7MLjxJAypUg6j9TT42%2FYD2FUHZPJHO5phllFr0L%2BkekgpMb7%2Fzqy4Trs8O0kmTIO%2FeoXKaapDZSZUr0pA9j71QWN6Ga0gBSgBomQaprRIJpUxmdH4jqPXbnmlOLLbrY0WAYSAImSaoS8l9GBEKJCjq6xUDjMwQngeoI6dKhU1ex6gAj0mekRVoOLCDBIgaQk0zT2Vk6CzRAUmCSPfrvVJpCiR2gIR6hKuYHWqbtkDtuogpQCTHIAppA8wDKVESJNQgYYnYdJJPtVMqX8aCACY24%2FjUQlLdMy1QqIBIqpBSx0rZgpKQNQAH14pyyKqBsieOPANuJTCHCklKuhPY0n%2FBFOjSTxcxXFsFssRxbL7T9w02Su6sQqEqjnSP3TtxQZG%2B0aoQTV2fn0%2B23nHKWdcJv8RYuE2lxul9h1JSW3OqVDp89YrnLIublIOWaLTSPzV%2BK9y61jV1runn7YEhEGUJH%2Bk9q2wnCXTFvLFRpGuxZcxO6NsEKD5PpKdxPvWhPRkOqP2S8h4w5ltIxTAVXzjSyppZj9qNtgeRXF8%2FJ6R0%2FEhcjs34KZxtcGXYiyw7GMuvMJDYWw%2BpBST%2B6tG6VJ%2BOlcWDt9bPTwSSLT8SvFHMFoXG7rLLKwAP%2Fn26ygrB6mNppU%2FFyN2tBQzQ9mj2dPGbHsPvXHg5iKrYr2Sl1REf6jNaPG8NV%2BS2c3yvO4vSKYxTxuxhCvMtccfdt9UqadXqIG%2FXpWqHjq9IxZf6pP8AwB0faALbjq04lc2F5B9aVmSD0Nao%2BPP0jLk%2FqEn2TPJ%2F2jcfssRReWeN6LhQCCojZ2O4O00%2F4pxVtEhmctrstbMviVl7OliRdr%2B64i8CVeQqElfcDiKWknK5F3J9mrGdr9nDXVs%2FeFqH4ku7z2%2FKtEfHg1YDka749jt1Y3KMStbhxLm%2BspMa%2B8is39vJ9oZHNKqRA7nM6F4qxdEnQ9%2BzWlUwO5q147b7I4DDGcPuU3Ljra9SEq8xI%2F0nt7UGTxZoikl6Lcy6gN4a1cqtm3HWAHNWwK2zuYFA40hi%2BOTuS2U%2FnK2FnmB%2FEbQLaw%2B4JWlsGQlR9qxuL5GqajxoiedGmLrCMNuAErZUgoUUxIWDyevFOpLozyzclRQbbTmH4ml3TLUGCjpT%2FwDJhVlwurssx5cUtJFvmK0GoLH%2FAPcs8fEiluKTs3xy1H8eysHr9xpYsnirzEjhXVJ9qOJk%2FwAmLb4bYdASXW51xxp%2BB9aOOPkQnHh3i9raZpt7a9LicMuk%2BS7vsZ4J771r8dVLihWVa0Cc4YCjD8wX1m8ryihSikdYnbeq8jx6dKIeLoCYQ27ZYiUtjU0oyRxEVgktDIdlu4b5ZaRiDGhKgChW%2B6x2NKHJFl5fxk2mXr1wL1MNP6yiJ0g8n86OKbToVPbK3zrptsUbxCyCUNOhJB1fiBG5Md6KEfTJ8nFWQzE3XCLe6fWrzEEdZMd624fFjdsiyx7T2Q%2FMa%2Fvi%2FvJWNagElQ4Vt27iteOPEVPLfRipQLaLRpM6mvTJ4NGldp9ib0RZi8cTdi2egtE8H9w1ijKUVx9lYpq9hJq0c8l9DhU56yQRvA61JpzWjVkwKQMWUNlCvLUmNiY7dzSfhkJh4zT7E%2FvLaHwotqPae%2FP5UyGNxXZocV9ljZRzAMNvbJ5DhlK0qMk7b8UrJ47X5PYUWbFZcz1fZdzjbZpwu9uLV5pxDpcCxvvMA1nbvQ7G6Z05xbMjufsk2eeFIS05cpbRcOheourn8Rk9o%2FhVZOgo5XyBORWVZixrFE3KDfllJtLdpZPqUoRPsrjfsIpfxt7CyZeL0c2%2FEfDbzAvFXE8AYbFq23f6C2J2M7ikuk6NSdxtomOYcq39vgdw%2B84tdqQVJCV7IUOQafxS2hEHbpohTNubTLeG4k6hBC7vSZB3Cd%2F5VLKnjh7GmZsdtsWxYs24aaa%2FGUJ2HA7%2FADS5JsODiumRLAA3hePuXVuS26ka0g7gEHaD3oXFf7jnlVHW77AOMXuB%2BLN7i1y%2B4yteEXakEkwomCJI%2Bp3pscVex2OEZQ%2FI3b%2B0%2Fc6vD1zMeHNusC6xNzYQoBRAMj6incZUNx8YxuzjXm%2FMTr6cdwzECU3rqm31qkySmY6e9Z3F%2BmD%2FAHjj0iprxpLyIkpKkjrt%2FfFLeGvQqWeT7ZtJ4U4ejMmHYLgrNu4cQdU4w05q%2FFA1ekdNgabBUqKi70bZeE2WLLDMk%2BOniItxTNng%2BEu2%2BHFaAB5y21ICUA7zKpn5in412TNhemzlZmRD7%2BZbZbTKwlSPMdK06RsPxRwJPHes9pugceStoszAH%2F8ADsqXmIuBtbpukIRtuTpnYUUsXsd%2FcS9loIsXn8QwbDjcMoxBduHnWmzqLKVAnSqf3oEmlzS%2BhTnfZfHgbmXCLDFMSvlMsu2zDbnp0Al90iASOdKQCfcxROpaGYpJfpF%2F4nhjt54V45mG5eDF5dlK2GUc2rCVhKEmf31qkn2FP%2BOo6NuLUrvRUGI4t92trDDbh97DnVto85pIJdWs7hCUxPG9YMkm48ZdmqMk%2BhC%2BtXMNtHMQumH2bVUt23q0lyDBVq6wZHaaH45fQy3H2WxltpeGYA5dhSm7h46mWQndaQOp%2Bpquclo1Qk5KmW59mDw5usfxnFcz42t5sLdIYaO8pG53PERzQrJxdoRnlGPRsQrDGXs4hppZf8pyBG%2B42ge%2FWrnn5aSM3z0q9m5GH27OW8vqZUsM4m%2BhLl0U8tJ6Nk9%2BprZCcYoy%2FEr5FI3Tb%2BYsabuC36ApQR2G9HDyeWmDPGkjLHGE4c0i2KkvBIMiJG9PklZnhBvaK4cwsuLSEoUp9ayEpHUTx%2FKluLNcYOuy7sqYejAmGUPIKr58BKDwUJ6kfwp2PWjPlxS7s3V8Okowy2ZS96H9iqTz7fSujHIoI5%2BXGbFYfmNhtglDhJ3HMyO3vTFlVWZXNxAOMYu7ea1alJbHTgj9aDLkVBRtsgD6xrlQGqNyTvXFzvR2cMXxGq7hMKVJmsTyIfGLs%2BFykEQCvfmdxtVTzEjFrsbt3atR1KUEzx2%2BlKeRPYwcpeV%2BIJkQPzok2%2Bim6F0XYgahpJ3I6Uel2Eoi6XwQ4TJBHfn6UJRkl5O25JPUzTVJEMw8I3Ch3mrtEo%2BDoKiSEk9hSpPZDLzNUrjbfpFCQzbdE7J3nvVpgyVhS2dSpSVSQPbn%2FinRkmzPk1oktncJToICk7c1pM8pIltncHXAI1cc1sxvQlrRK7J4pKVdJ3jinwXYmSolljcgkEiSTPxvW7HIzTluyXWLyVpIJI6cRTkzO3eyWWT4IlZ3P6U7muzMiT2lxsPUSOfitMFSKZJLe4BCUypKZ2ohAdZe0HbUr%2BdOh0Imr%2F3CaLjaZOnj5ojMO0vpEAFSelQhkX0lRBKie8xUINnngneZqEBj9yElUFc%2B3NMhYcW%2FQGduzqVCvjfimNotTfsE3F2dwCdPzSZdluaA1xdCTIk8fFVYoB3F0JUCVDgbdaogKeup4MdyahaapoHruRIgHtFQoYqfAMSQqeOahDnJcgohOkJEbGZAE14qUV2e4MWFKKipX4QR02%2BhoYVZVB61cBUoJnY7wZ2p6lQE4tLYftnCoiVAk8gDmnRmjNkZIrV0lIkpnj%2FmtMJPsTwfoNsq0pI9AMSRE1oQDu6Y9TBTpKvge9RMyt32eLCQNR1H37VZBBcBSikwqIiZioWptDNaSCmSqNgN6hoaGixMJUPeSetBPoobrEqmeO%2B%2F8KUDxRgUkweIMbVAZRVGIQCFwqBP5VAYRvsdMsq2haTxNUnoYoNBVrUV7GFTtFMjBVZU%2BrCrZTqGsgwdu5NG0qorHFNWG7UpGkJPTrzVcELTD1v6lJ1ERPAPNGQNM86kqMzINQgVZWnV%2BfHSrXRAoghSZkD3NB7E%2FwCsUISU6gUhXJq2NatUxu%2BSWyjeD71BEHsqzNrr1g2pb51W%2B8Kncf0qDJNt0af%2BI7wum3b60ugi4QkpJ1fjA6H%2B%2BlLcwnidHCP7bXhZhPiHZYniWXE2GH5jYK1XAYJSXknf1gdf0rnOcL%2FM2Q8d%2FHbPy%2B%2BMWAYrgWO3dhdNupSFkGRt2pq8eL3BmHJicSo8s2GIox2xetW%2FNUlwEpj8QnoKyZJSg3bFU7P0HfZhyvb3OGYde4TiDWF%2BYylSm3knSo6d0ieNxXM8rM0qXZ3fAiuLkb0pwy0wi3Wu%2Bw82dypO621EB7pqB69KwRlN6R1I3J6KT8Ss4OXeHPWTONvupa9OkuwfqOvxXQwxlW2L8hxWjQLN2O3LK3kJuLh1hRUPWZSJ7b%2FNdnB497kzj5GUJj16sqWq3dWCDsev1Fb%2BKrRgyJX2Vre3xSsldylLm0ydzSsmTiuy20loEW%2BP31k62ti7eCUnUQDv%2BU1kxZMrdrZI5JLomzfiLeeSl1i%2BWyoSrUFH0n4%2FKmynkbqVr%2FsMjmkwrceKDuKstsYsoG5CY8wb6xHboaTKE2XHI29kUvMdbxBstNrCYgiTFKlHJW2aIpJ7IPfMPJfUUqSQYUmN9Se9XjzuMaVBylT0bK5CsrbOeXbJNqEKxS09C0r3UpMb7daz5cspPbNWGUZdIWv1KwZxTAT5fknRpPCkHn%2BHEUHNfZeTFydplZ5sZDtst1gtvNhRcQYnSk96GeRAR8X22VncNsXWH3No%2B2pTY%2Fao8swQobR8VP8AAuSSdMhGMYK4LJrErZBW2nZZTuAD39qZGQiUUuiNWOJu2VwlgQSBqaJ%2FUUUlYKk%2BkA8eWu4vTeABpf4lQNvrVooCuXSkqKSQFQSPeRvWjAmS62wtgeJS8G3AZCtTaoHpV0%2BlaVjqV2Gmn0X9mW3%2FAO48tWOavJZTdM%2F%2FABLxCE%2BpKh%2BFf171o8iLybsGGNKbXorjDm5WQ%2BkAj8LsR%2FzXL8jBx6djVBImuB4ihlvEsMelWpIca2mFD4rJwk1oNTaCeA4sgXzuH3KkpYeBaXPzyBRLkgJvVnuN29onDncOvEJ0gS0ojkdCDRrLJF5EqVsra1vnUG5t3S282JSAuOP5VuwZHLS7Mzwp9AvF8LDuGqeZdCttSSlXII4PxWyK%2Bxk%2FFa%2FjsZ2Vo%2Fc2%2FClONtyQEyQO9FJGdwmu0RDEkgrYuAoFWrSqRyQetZs07qkA2kWNg%2BFf4phqrq1TqcQuVgGQRzEUUWvejapxrsHXmCXD7S2A35KtMyqBO20UrJmxPVhckQG5ZcQ2tl1YQ8gxBmFGjxRi1tAynFdmGH3C7fStwKUkKEz80byRknFMWs6ekWlYYt94LTZfBZ2mTvt0rlZcTj2HGe6bN%2F8Awaz6zeeHmJYNc3qX2bN1KUNyY0n1BX5iKTKLkbuXFW9mzngjdXNzi7OYsPvULsW3hcL3EeYlXBNTHBrroHJmgnTRq540WlrceJWZ85B23eS6tV0kj1EK1EwPrWXOqlaNEXor6xzU1iWC4lh7ri2rggmFqGw%2BD80qc7RbHuYbayRlPCLRLYUpCgtawB6SJ3%2F3rTGT6FZlao1wxO8Q2yMRDpced1gjVuNwN%2FbimoxuNdHtq8%2FbWn33UVqIBAPUE9BVUrs24FS2dQPsZ4ri1kM14qhDtw6uybYbcMq8pG8pjpI2o1Jth5ZPhcS8vE%2FxEzE7lLC7a%2FI%2Fwti%2FuH3WlggvMgQEzHfg1cptOhmOP%2FUcvcw3lzimZcRvUJLVs6VKCnFzoT0Enk0EnZE43Q6aYGJ4vZ2tmXrlbyAdA3UIHIFInkd0W4rimuzdH7PuVcwXOP4bjliwbTDMESXH1LQdTjrvoAQN9wk8niKdjhbLyY3E288brZvA%2FAFeT8mOXTovLtDt3DZJfhSiCZ30pGkD3o530FguTpnMvx4y0rBbnw%2FsbW7YKHsPRcPutp0h1zUAQSeQnj5NIap0ieVCLehxhlsLXKFmXVo0G8cdSoiTqCRvT%2BTqjPFUNrbG0%2Fd3XLBdwLhxZQ9cKMqcJEGOwj680pxss2R8Bv8ADr7FLmxslFy4baHnakDQFlQjc8gAEn3irjCS6G44rtmz%2BPZ%2BwzDMGwvAX2ra9fdvyWEpVq1%2BX6Q4pI6aidIPOkmlTlKqZ0cUV2uigEYw63myxvrts3uJ4hcOftHAXFpQZEgf5okewpDyuP8AIfCcf9JPcTt8RzG0ysMvItg%2Bli1ZcQQGWhwAPeST80fyDOXItzKmH2zVy0i8U7iF2gaNBATqUeg9gKRmlW0aFjaVs2Xy%2FjqspYG%2FdI0W10%2FCG0pgBtPYD560iU21ZleFt6J74apVZXS8zYkUfenVebZNcqE7F9fsOE7bnfitHiwT%2FKRkztRdMtjEcwXF60thL%2BpazwDvvyT3n3p2aSfTDxNrbD%2BT7QOPKcKdJQiTGwPtNF4sajZWT7GmccL%2FAAuBSi84oCJg1qUfoVKbS0JZewK2wlm9x3EmvNRbgNpSSZcVEwPfinwjW2Ic2w3lh1y8v3cfxUhKtcMII2kcQOwHX2FMxptjVyLownNyA4hlLySOwVvMcx%2FfNOg9icsElsvrK905fsoX5iyrknoP96fNqPZzNSbJw%2B15VtKzCANR9%2FpWXLLVmqCSdIgN%2Fc%2FtVISomd%2FYn%2BtcnNkidPGtWDy8Skgfi6idqxzTfQ2j4XKBAS5oTMjY1fNDG4fZmbhGlSdaSTtsdzUlkTVE4J9MUUsELKVcjvsKDnWkU8f0eodVG2kkbccULk%2FsrixRNwuCCtJgbR196nJgCn3v8QUJgkpM87VfyMhmbsaZUgAfPNT5GWeN3hGyiV77SRtzVW%2BymKpuCqdRUqImRNXzY6UVQ5bdDhKUKGkbb8j6zTIO%2BxQStlAkL8xA9u1PgtCsjvRIbO4UTKlykcmtSerMsocf9yV2lyE%2BoKkyAZ71oxydASeiV2dxKIBSkbGK0Qk6M2QllpcAwlSt471shNUJklRL7G4UIGojaBPStUXoyyXsl1i%2BTABBgET3p0doQsaJNavwTunYcVoxSSFSRJrV%2FiCNPTemiJJBti4UBuf47imQfoz5nSVBVD2tOoEUxt%2FQjGkxdD3EwD7mKvX2XKCSszW%2BoSdUGKoWNHbrkbexqEBlxdyVGVEcyOlWmNgtAN%2B4jao2xVtgZ663jUe81RAK7eDUtJUT3HeoQEP3IJUdQAjbfihc0EoNqwQ%2FciSdQ%2Bap5F6L%2BMHLuh6vWmTNT5EX8YzXdSVHV6uwqPIifGaIXwPrkkp67V4%2FJK%2Bz2SkmDUApOkxIjVPX2pKf6L36QSYWQegHA9vrTVLW0BJP2iRWqkpAUFJBkEyQI25%2BKbHMuhbi6JNbDcBe87gg8CtEJezO1ug2wtZRq0AjmOs%2FNaYzFtWwghXmQABHIBo%2FkAqhSDGxn2O1RSsqzBSQRpB%2FrRUBKF9DZxBKSSZJ6nkGrJGP3%2FwM1JJG5A368ULlQbG34yExEbE8VnbotxowM8JG%2B20frQtt6ooXSiAkoSo7SY3psVZBwhuTpMHfgcxTOKWym62EWwmdkhPzU5oQPmx6o9IgnoSanMPgw5bAhPXcSOkD2q1JABxlRSQkJ535quaIGLdR%2Femf4iiTsgVbmdkHVEVKIwm0oEe%2FUbbVGZ2qMlADoBPNFCVdkUmYLeRBB3%2FnQpBY0RbH7e3xKzet3E%2FjTpA6f81TVodJUtdnK77SeF4%2Fki3u8Wwp25%2B7oVqISTCOfxAdPesubofin7as%2FPV9qbxTvr66vcXw%2FEncHxwIIcWhZCHDP4SO1cqTSdGnJKGSNwfRw38V87YlmPFLz%2FFEJfuCd1p6%2FFdDx25Ls5k27oK%2BA%2BAJxvHWFrs1XCmlBK0%2FvAHqKX5mNJJsuOO2jvL4OZVZwfLts7KzZEACESGzHB6g1w88m2j0Hj4XCOi8cXxDCrSxTZ3Yeu2OULLkLbPSO%2F8AtRQbbobNtKzUPxOv8JKHHVLcUUAp23UPnvxNb8EW3pHI8qb%2FAMmmeacfYDjqksFbQURCtyfy%2FOutLHNrjdHOlkb0UJmDFVKWtYCEJM6RINMkkSEfZT2M4rKlK1nzDtPvQ2xpB3cYdbUSXFAdQTud%2B1WRs8Zxp1KylDhSsgjmaoKEqdhX%2FuB7QG3wlRIgK4NKyxT7NbyJ7R7h2YNN3%2B0cCkT3kDpxWHPL1Er5N0yxMPu%2F27cAOtH1yBz8e3tWOnWw5dF8ZKfvsoY5aYg2lTVq%2BlLgISYWk9fpxV8dF4JbLI8RUMOBjF2LbWzcJBKkiAknv9azSxujp9O2ULdvIa8y0fktKQShXM%2B1LjjV7AlKnZVzOMrsHMQQyllaXE%2BWtJG%2BknlJPWtsWkqMUsjbtj3Ld5brev8AAnyF2t%2BghCjESJMfNCtBfImvyRUuYsJcsX1pCQh1pWkHqROx%2FrTYv7Mc4K7QNcSbu3QXygOTEkzt2NNtXooj2JYQ626l1mNIG6e%2B3I9q0xyw7dgShbs9ZsrhtoXraIVPbp3%2BaOXlKvxJK16NmvB7E2k3DuG3zRvMGxFnyLpuJ0H91YHcVm%2Fu8l0%2FY3JDkrRlm7LNxlzF3rZ%2B2CLJThCY3BHRQMdqwz5RlT6OjialH9kbetnGrtDIaUQlIU04BwD3iteLyqWkZJ4l1IUvbNKQ3ehKWrhEKURtqPt3puPIptr2Lhjr2fZsfXZWKmLy2Utm4aC2XUiQOxH61rjiktNgZpS7KJ%2B83XnB5pagogpJ%2FwAx96Qs3CXRnx%2BRKL2g7a4oltuLhI8uAle8jjmP5035m48kbIZtBi0uU2OI2lw3Ltsto7f5k1fySX8gZWkNrzKjOIN3uJYc4FWgVqU3HqbPURWLJntmDI23sNeGl07guK3DLg822cBQ6CAdjwaVlyN9s04Y%2BzZfBPDs5pwXGsVZsW%2FNs0qjT0SBMH3jelKLZraqr9le%2BJ3g7bWGWsFzDhw1OXTAe2iSeoP8abCbjor4ds1HubJ60uSy6kp3Mn%2Bla4Qg3yTMS8dqRjaXa2XR5Li0lQ3HWjlJOXFjJ5GnTNl%2FDXFLiwsnXELUF3aPJWiTAjj%2Bf51gyyV6Q6E2%2FwDBvr9lLMxtct55wfEwoar9KGI3JBBkg9N42%2BaFRaVI0qKk7eiNZ%2By68%2Fi%2BazbFKbU%2F%2FFt%2FMVpKlgSYT9eaBwSNai0jTaxW%2Bxme4sm4uX1BbKgBJ2O5IpfxtmfL5kVpEvvcdf8A8GxHCXtaXisEb%2FhHAkUVV0hTzNlSXDyLu7sMIgh4OaNKU8gmjcZJWg1OD%2Fk6LRwzD2Bb3ljert2nkJlKB6jEwN%2BnM%2FSlKO7Zp5p9HV%2F7AeVLO7zBnPAbp4otH8HbdDCdytwKMbnjYmnQe6Hzi5YqX2efaTxV%2FDbDE8DtLLDk2zKC2lflyoqKiee%2B0VJy3RMmDjFN9nLLO67q2etrXz%2FMeSn1RAgnc8c1myq9AY0n2Wv9n1CcQz9gCbyzXceWkgJBCdZiAJPG5oYp%2B0bMEINVFncP7H3ho1Z29hjOOMHDrXGsZukttKAWXg2jS2kbwY9SyPcVswwtWlQPkw4LfoJeIHhXj5zPnvD78PrYsjcJUlzSlsoL6lBWxiQlO%2B%2B8UTi2JxyVKRyx8b8HuM1IwpwpQw1bYg5h1o0SnV5SQkhRjaFbmluAOZ27KrxvGLTBsjYRhVu4q6xFxx5a3lphKUpUUkN99xuaJx1Rj%2BRqVPogWT3XXbLGsRuV%2BdbsMq8tClCPMX7frSrNEKkbWeBTt1k%2FJOZbxhQexPFEqDR5LbSRBVPI3Jo1JJUyOKT0SbBUXrmLZdtbNi5ucSuFC2aIRq1rWY1k9kpJ4oU%2Fs0Ysrbouc2uGZdzxd4owDcqab%2B6YYXADpTuhb0TEk6oJ71OEXujpY4xfZJl3l0lvGLtCwxhFspFuLh0gec7pBVI6BPG3NJza6R0Mc4LfssDw2uWMw4wlWFtOt2PlKcVcOn8LaRKlj56Vlc1XVifI8u9Fh3mJaMHfzFfxdYSwtwWlrEf4i50Tz%2F4wfxHrECk5Zt9mSHkSuqJblLM97iI%2B%2BXdw4t9xCdcJCUgAbJAHQcClQyux2XFF%2Fk0XNgN4l%2B5gJDj0Tzskf1rZgyJO2Kk1VI2Cy7aLbtGXAlQSoTPQxWqE1RnmOkYO5jWIa3Ey2k9eEj%2FMZooZFJ0BK0rB2ZXbAA2KVqt8JtU%2FtFgA6lHsOqj26VpX0SEK%2FL2Vfi%2BZFJCiy2i2YSkNttoOzSeg%2BZ5PzSMuWaa4orNK2kix%2FCrBcTx25RdPNvJZWrYRE%2FP5Vq8aLk7kYcmbnJxZ0Ay%2Fg7eF2TSC2EJA2kASa6soJrZin%2BL%2FABGWPYsnT5bejadif4VyPKyxqkdHxsdbK2fvz5hVIEjt3rjZMyR1IOhJF2NfrIUUngnkUn5hnyGKlk6ikEzyRvFRAvGxZH7IgmFHj2qMkYX2PUvJ5GiI2ioOpUKJe1A6dyYgg1GUfecTuHFfyqgeP7MwsJIJXPVXFWHZkXAlPpBSqdx0NQjZ8h0ABQPHU9qopmWoqIJKt%2BCR%2BlQtOmOGXNMklYETH9aLk%2Fszyi0FbW4CvRBG2%2FenYW7BeyQMPKBSoEAkSQP6VtUkuhDRIrZ4GEkKPU%2Bw96fCZimrdUSyxfMRqVETv%2FWtEZVoW8aRLrJ2NMiSDMTz1rTjM2WH0S6yuFwn1gJI2nkVph0Z3FMl9lcAQrfVPWtMVoROH0Sezuj6VgagriYp8OhFkktbtK1JkDX7dafj6FTWw8zcBREAz8yKNMW%2FoJIuVAwSQI6U%2BMr2LlijXQ6TcogjeTuJo7MmvR4u4A1cT1PaqINHHwZM8nYd6hAVcP7qHqEdQeKhWgPcXJBMkcflVN12ElfRHrq55KTAB3INC8iDWJsAv3kAgEKJ70HNjVhoDPXkglJ1H8qW8mw4xV0C3bsERISnvQ%2FIU4fQOVdeqEqBPzU52VwfsRXcKkbkH2NUor2W4R9moGIMrMp9RQepHXrXmpRPVQqgAswtUEhUT7n%2FAHpLxtewqHNs4JHVZG57VGqCtkgtF6dCkqVztA3NWgJ%2FxdEntQFBCgsJkRsYFaIZDC2GmSEqRMJBiYmtUMqein0E21BQmVFXSR%2BtNoQOUpA1ABPyBx%2FOmRoh4rTHVMdhzR2QSXtp1TM9DxVkGikyAFageTJ2%2FKlT7KfQ2UkaiqDAPHIFL9mhNHqUbApUkgHmN6Yor7FyfoVTBOqCU9hTFFIAeBHqCiSUz1qCnyHaOQATNRKiuLH7GwJClTxMbVVoZFS9hm2WFATpKYEb0plNILMlKkkjb2q1EDv9BVidInYHvTUCwq0szp1SkbGrIEmlgJCiSQP0qAygmZLWFhRBUBEfWqaKWOgc6CrjcgAAdasMEPk6VlWmQeomoTlRQPi9k%2BzzRl%2B%2BYcDZdU0pEKTssR%2BE9aBxXZE03dn5NPt0%2BCr2Tb7MK7axWi2U4pXlq32J%2FED2rnZ8N9aDtpWujgJm1llnGXbFSShRUYCgY5iPap48MiWmhcZvujZb7O%2BWmsSzDYOYaXMJxxCkpBI9Dqfc8Uny3OvyNGB3L6O%2B3hplnFXsKaUbY2OLJTDqEIKkrAHO22%2B81zl4zb5HX%2BdJbGueMLe%2B43CW8PDd6mVbJKY6detaYQon9xF%2BzQ3OF1jLLt5Z3eHJWZMLKfVx%2B9Xa8eCStHAyZ050jU3ObIDjrvlpaISUynaK6PxKhMe9ms2Z79bK3go%2BYBsY78Vgmtjor6Kbv7pbq1at%2BenJmqV%2BiNoBLKz6wTvI9R4NJzSimk2U2n0Jh0JGrWQroCOvzVRbT0io8l0D3sQKVqSVFQ4BB4qeRNKth5U4q2LYa8S%2F56inywYUkb0uWOMqaRcJrkrNncFwVp7C7PEcPLb8on%2F1Mf2I70qcYdSb%2FwCxsco9WXrl3FbbEsCsLZ9oN3KP2Tg3llccj%2FSazJK9AcqdodYhiNwvC7rCrwKU0iQhQJ2V0oci%2BjVDO%2F8AUzX%2FABjECpz7ut4JU0SCJ6zWPKpXpD%2Fkg1tlf4uyErccbdDrajxFXGUrVkhjg32N7C5W0pK1OqQ6FhbagPwkdac%2BjGk1JpnmNupvXvv7xAf38xKOTPWDRQZJR%2ByPXVsG0rFusONKAWjfeeoIq1MXkgo9OyP3Tqi2hlLiisSUbzAHI%2BKYmAF8Pcbu7QsABD%2BrcAfi%2FwB6jZLJplK6uMI0qbddbeQvWk%2BwrLPJWzo%2BPjibUOZiwnxKykhi6swM12SAUFIkXTPx%2FmFbccFkjy9mfKpY5fi9GuVwm%2Bt75btq5cly29BSsbgD90jtWVwa0ySk3%2BTCDeYLDMlsu1WWLa9J0OIG2k77p9qZjm4lJqh49a%2F4rkV%2Bwu1%2BdcYc6UocCpKmzwP411cOZSjYrKrVGtV%2BgMEotlkgGIiPkRUUoydNGeT9HmHuF4G3UlS1HfffpwKOTlxr0EoxfRNcLtFXDreHrUUp8vS2s9DHBFZpybVJi8qaVpgS2zBimUMaeWVNu2jhLb7Svwuo44NBHEquQMcftsvvwvy5Y5hu8SesVsO3TyUlhJ2JPaKyyab6o2rJGKVI3v8ADC0u8tZ%2BxHLuK27TOEYlhqVuiJGuNMpHeCd6pUhuWakqQv46%2BHl%2Fh2Qrhlq0WFWrQurI6ZBbmCCfcAGgyS%2ByYHPl2cr73C05gxW3Za%2FY3BJSUiDvvt7Ghx6G%2BS4t1ZWuK2Aw%2B%2Fft1AhaZBnuDFbce9HLlxTou7weeF5jFph1w6GrTSp09vSDA%2BtDmxRjtFqDXTOmP2VMEtsy5icwvEPJtbRxLjrboEBWidvmaUOxSk19G0Hjx4UYRl3JFl4qNYci4tRev2xt1Ew4UAAkkRMqJ%2FKpwvZazzTqTOVuG3tux4iqTcYOxgFi48UqUkag2CeSTvG9KlKi3gcpbFrrKtniGL5vLN8yS06pTKmxKXI4pMsjZtXiJLsoNVmtOZLVttbSLsSVqKpOo8RR8rQmXjtPVEuaabbKzdvOtvhSvNXGykgdPeaCU6Hww%2Fs6W%2FYq8QLfJeY7rPgul3OGtWybTyCrYrUhQJKesU6DvY%2BcmlSY5%2B2Fj2D2Vzhd7hybhNjcWybm4KVEeYsydifbpRTVPZccspLbOeGGWVxmnFQ3aNvPuvpU603BUqOYHesqlci6OkvhH9ny9y%2FmnKVyrD7hx93BjiLY9SVMvKEoBHMiPenxbcgsOSt0dw8i4Ra4ZkfI%2BYs0s2juIZdtXb26ZXKAnW36VBIjhSUpnrvXUjGoqzNkyuc3wIZ4tM39vkvx78RMaxnDli6wi2w3DrbQWUtvvHeJJlRKgmY%2FzbUrIlxNC1SOJd9mDBv%2B484Wou8PQ3h1vcXDYcMolDIQpYPVW23uaxRmF5E43dmnud8x2AwnK6g4lsrsIZbUqdJUskqJ6gj86c8brkcrKuUhv4fJfu%2FOwtlbdwlaDeXLjqtKUtpTuT8bfnRf2s6totZfjdI2syhmOyuMjYnfMB5bz74w%2B2Sg6T5SYICfnvWd9HQx%2BSi78FeZwWzsb20v7mzv1pS2q70kLaHVDKZkCDEnfk9aQ4Kr6NmPJGStDrHA1b4ja4jhf3zEMRulNM2LdwNkgCJ8sb6idwD80UYtdDKoeZ1vcXVgmBZWw8ffMTWsouNSQhttxR3gAdIkzTG37GKZunkrw1tsr5Vwm0cxYC1u2f24Kgly4aj8KE9EkzKqX8Uewo4%2BTLIdyrheKWjd%2FiF8z90tmks29u0kENpSOAB2rn57l%2FsMjCKdFaYw8rDw6LFzy2h6gTyAOB71zuRonh5FxeCtvcYqtq6fClpUZO8ACnwmpKmIjid0bzYXbsvMoS0r9in0yByewrbjXpFTikYXHl2DF6429otUnQ46RuVTslI6kf8ANPhraM0o8nSKCzQ5dPrDywtDYJ8psKmDHJPVR3k%2B%2FtWXJmbZrh4mtjTJuUr%2FADPijDS0TZzumJ%2FPv81t8NuRg8jjDUXTOi%2Fh3k2zwK1aVpZbUPxFRn%2BxXo8eOuzh5Uou%2FZJsw5gYaS40ypJQNhB3O1K8iXFaNGCKtFHYnmJKVukuAkk8njtXn8%2BTTO5jw60iNHG21lZC9ZA0jfrXLbs1Qw%2FYQtbtayVk%2Bmdp6f7UHECcEvYdZuQQkkzt0qKypKv4jgvaQSpRSdqnNk%2BR1TMvMAglShtsKtSYzDLYol2QkhST3ipzY1zVdmXnpkKKYUknYfn%2FADqubF6%2Bz4XHqWEnQRA%2BPmi5ouCX2e%2BYoJJBnbrRKSY7ijwXBKU6tMJOwnikZG2gvjTHabiSpc%2FSePpTYMD4fodi5QrSNRIJ5Bo6AlH2P2Hg2vkkR0pkJ0ZZKmHrR0K3BC52SZrTCaYqUPokFs%2BUkGdY5k1pg70Z8sdMldncE%2BUSso%2FlWlPRkcWS3D3lKAVBUY2%2Ba3YWvZnlFkss3xEAySNjzWiEvQia2S6xuiCgHnoOlaIy9GWXZKbR5OgDV1kE01SfoRJV0HrZ31BYOgDsZp0JUhdP7JBb3koTvpM96dFqgJoLN3IgHUT3INNjKhX6HIuBHIBq%2FkYDwxPPPG3qnvvNWpv6FSwP7Gzr4UfxA%2FFX8gLj%2BwTcvBMSs9uapyfoJIBXFwTICikcfNA5N9jIxvRHbu6JUUAq5mDUQ5aI5c3IOwUpHUmhAlL6Ab9ysz6tuB1NIAV3Yycul8EiT3FRbHDNbwIjWZ%2BeatopowDnpPr2HSaTKb9A8F6NacTQDqASVSOQdj8dvrXEyNp2elwdEVeahQUoEAJiO9ZZyfY9L0ZsIc9I3SoyOm9SLCcA3bKUoJKjAB3j4o12LkSG2KzpAUNPJ22%2BlaYNezPLHbDVq5snSuVRwDua2RlH0KlFp7DKDuAQCZ2kzRGeTTY7CtgRHaOZqAmc6gFH09DPaijKiHypHrATqiN%2BlGpkGy0SonrxH86MliCh6SBBNDxSLSs87BSTq7mrpFuLQukbAgEkHpVi5SodpSTJAHPA%2FlQylRXyC6ExCSABO%2B9Lc29BRdofspghWgGTzFVVbZYVZRGlYgmOvFF%2FsIl2FGlGYIB55q%2FkKCLBiEwAI69KHmyBVkkwSSTOkU1Ig9SRChAPxwKsgstRCTISQe3WoQYrdGlZEc9t6hCO37wSFhO6htA5NQCUG9ld5iu%2FMtHQ40skSPcVVAxTs40fbl8ObHNGW8TfKFB0NqhWmSCDMVg8jTNsIXBn4%2FfH7w%2FvcBzBflloBaFk7jgg9KZiVR%2FRgTaDH2dvEM2WLWmEY62%2Bw%2B25DbqUkkjsRWPyZJ9GjDNWfpJ8D8xrvct2Dtli6HlaAQgH1I2G3z81kjM9D42JOOzPxKzZdsICMSw5t%2B0IKvvLaSlYE9R1NV8hm8nG6qjSXPDuEvpfuxeC4QZjSIMe%2Ffeur4uV%2BzzkvHqVs0L8UFtJeecslhUgwT%2FOu3BOthGlWZ7l03TyOxJV7Vz8r%2FLRcce%2BVkANwgrKUpTMcEbz3%2BKRLGpdjmNXkpUpRAa08gA70HxcZJt2Sl7ANw6lKnE7EGBEbihksrf49Fwi07iC3BqcKf2iUnrzS8qy%2B0Lycm7kH8Mwp9xRSlCUPcpg%2Fj%2BKPJ5CqkB60XtkDFn8JtFWV5rXaKUdaDyiTz7CufKTb2aMLvsv%2FLluyu7aOsNurGlccrT0V81Zrx43Loyxl9%2BxuFIuk%2FsQqNX%2BccT%2FAAqmTJicXTKHzW8pF%2FqCQmTJVPE9RSpdhR6I7dtKuGEust6ZRoWmZHyBQ2E0BmrcllCSUK0zAKtz32q3O9ArA2rbF7UoxMJtwhpF4JCUERrHajSSVsUlugbe4e82gtPFVrctGEq5Ch2NO%2BSLXQfAjl%2FZqD6Ua1IvUpCkaNgr69eauMk9JAyVGOGPlxxSkhTNylW53E%2B4FGvHbKSs2Dy8m0ftbW2xbDGQsp1qeZJC%2FwAuFCufkjs6OLLSDCn7jK%2BKWuJZexS3UttetEphLqRvoWnnejwvg7iL8mTmqktk6u8usZ5tWc7ZbdYsMU8wi%2Fs0j0oJ%2FERPIO%2B1bckVkXKOmYMXGD4y6Nfs0ZewzC766xVlL%2BGOIWVDSn0KUDvt71jjOV0zbLx4pck%2Bxnl7Fze4gm2S8lDV60ptadXo19NuhrpYpOqj2Yctva6Kkzdh6MNxB8p1NI1GROxM7zWvI5qOlsyzsF4ReBtKUjSh07pUTvHakNzfodgyL2WBZYomwvrB1aRMgxzA96ZxfGkOlT0gziGXrTO7l43hrgZzCApy3bUYF0kCSB01dqCV8aYpWmGPC9%2FEMOxLDUsOP2uINXTRARspJSqYPzXJb2aoV2zsRgWEYdmy6ssTsXG1XaEqEqG%2BjT6jPsZoG2bHGEUmTxTzGY%2FCbF8Mxa4Tc4xhqXWWlcJcbIJQhR5o8bTWzLlfGVR9nLNrwrbVmFN7hrEMl3z9J2KVBXqSferS2LbptNFEeK%2BUWUZnxK6s21NsiXI23333%2FOjWRp0inFVaBWRHWssvjE3WvNuAdKWieUkRPtQzk2XGFnQv7MWf7bDH8vXNw00hLVw8HAPxICp2PcGiT1SCjJI29zH49W%2BO%2BGjGVceTbXWCpvLlZcVBKVFUyOw2A2oozpC505Wc4c0sIxRb2LWLIKH3FuIVsTAVAA7UjJjvo14%2FJhVUVi47i%2BHPYgLVxbKVx6U8QdiTSfia7GZPIUv4grL%2BWMSxbH0FNi484QXi6BCQB3PA%2BppkV9GWWR3sK45lm%2Fw3DcxYhehNs2UqUyFHlOrkA0xwJDI7L08GrjE7jK9vh%2BGJKUvPIS0tGynlbn86XZswybTLo%2B1QXBkLLjqmLi3uLu7LaA6ZICUQUg%2FNHmyclpB4cNWQv7Jnh%2FimZvFTIVrh9o4q5bdIWQJ0oB3Onqd4ik4sLTtDoY5OPJn6asA8F73MubvCO5w%2FLZRhrrtym5dKNAFupqT6kfh9aeDvvXWeN6lH2Jy5YpN2Fc%2F%2BHeYXMV8R%2FwDEDd4Y69hlu6y2hMtaUPltSBB0lIQkH5O80Ofx3ysyeNnShGPtmof25PFHy%2FAbMN7hmHMYZhTuNstWTK0hKr9TbZCFISncEuE7q4Anbas01qjo4o%2FG3KTs%2FNvmPMmM2GDYphaEITiWJsFi4UlRUUAkagCep4qR8d1o52XLybZCfE565tsSsUrSGra1t2LZppPKtDYHHaZ37108cYxjsqFE5wvEsZwTIToVbsYa%2FjDaGlPOqAcVbpVOhsHc6iZPxWTyM79MXJXtG5WXmsMyz4aeG7N0VWq7lly%2Bu3UAFaGyohGgHrCSfmsc%2BTVI1eI4p2tkqy%2FjrmM4lbOM2V3%2FAIO2vy2ELOtRPQqG0nqR3pHBrs3xzSiqOlmQsm5Xbw7EsyOtWreKWdsbO1u7ghZ%2B8LSAtZEQhKAQJAkkGO9dDFji1sVOTbuzWzFjl%2FL1ycw40qMDdW4vBbFXouL8IVBfcjdDalSRPqI2pbjFLZphKVUixvBTFsez3jeK5oxtSbizW0m1w9tfpQ2lKuAnoEis7cfRqxY5Vdm12I2TjGFtWeEplzSolxP4Y3kg1VOmXCMnKzWnGmbtK7lh9algqCfUPf8AieK52VqOmjSszT6Np%2FDu%2FTg2AW9tbNab1wDV3SkDr9KwPNukM5z7NqsrYy5b4PbP3qVWnmJK2kzC1D%2FPHKRHU10%2FHtL8kZp5E2AncfczHiLbDLSLbDWCS02lRA91K9zzNVLJb1objqC12E38HZxAtpKSsj1DYx%2BfFVwtAZPIZZeQsMt8HuEptmkbndRHArq%2BLCMTkeRFt2XViGaWrS38ht1KZACQOp%2FlXVeZVQpxT21spLNfiBbWZcYD6HHuvUJH99q53l54pdjsGO3so%2B9zuq8ulJbKVKKo0zBNeZz5m7o9FgxquJMMIvVENlYC3DBA2gVkWR1TGyx09FhWTmoiCFCBA2malsz5Ir2HmrgphAG%2Fv%2B99K0qYhzrtDsXBUkiZTtFCLk7dmQuIghJg7jV%2BXNWmXCVGCrnSEyU6uNuhFUCervUpJmSZHX9KhDI3evSN%2FjirbC5sU%2B8FRBSoAAj8qoilJLQsh8wgA%2BqYKahayPuQsh4SUKIVPfvRJ0NjJPodNvFPK%2BBPzRKZUs97ofJu4gAfn%2Fe1MFudqgraXRSSFnUn8WkdTRRdMWSy0fkJBTtxt13ro42JkvTJNYPODVJBT0Na49GTLGiX2N1GmQQOSQa0QVbM8uiXWb5MGJV1NakxElaok1ncwUwAOlPTMc40S2zuCEpAI7yK0R6ETfokLD6iBIE%2FNMh2LC1u8pOk7JHzTY09exUpegs3dJCZCjPBNMhd0wB0LjgyP60wh9961CSvSR9aNTpFWhs5cpEK6n33%2BaAsG3NzqJBTBGwE1dvoCULAlw6ZJCtz%2BlIt2XGNEfuriZkerrvV%2FkERu5VJUASTMcVUpWVSAj7hBMg78xQljFbpJ3OkcHtSXplDZTqhKdQ5jfiKtSZFZ55u0J4PHYb1HFt2XsojEEpQtQToKjuN4riZJ30eiw6RFrhIAMeozAjfrWVq0bIRXsZICgoxPUneTSt9Daj9hq3IJT%2BJI23BHP8AcU5sTNe0G7VagEmNQ3PwaOMqFB%2BzcTA1oAJ4Vvv8U2ORrYjMpN6CyHARAO3zWqE2zLOH2Pmlz6iQOoM7GnipJIcatzCioc8cCoCfEGSrUQONxHSpFekQRCVhRVM9KJJliTiYABEkmT81WyqPUJABk%2Bode%2FtTeaBk6djhICAZHYbVOSFSY4BgcFJ395qm0ULIjSCSAeI71UF7G417HrXBlRT0G1FJ0N5JIItqSnSEExIk9hUasy5H7Q%2BbX%2B6AI5HcGlzRAq0v8JlQ%2BaEPjrYTZWAJ3KTPStAF%2Bh22rgCR8GoQVcXsSVGeBJqEBFy4E6ikkdiO1USHWyNX7yEgnWoiSfcVSki4p1tlcY0%2B35biVuggg8n%2BNVKf0HCCfZpX41YLbYrh982ttpxhaSACZAnj4rFlXJ7NUIunxPzI%2FbZ8DBY4i9jNpYoGokrQNyOZIijhDVehU8TUbo5Z5csLjCMyWj1wjWULBK9JBG%2FWs%2BWGNddmPjTs7x%2FZjvHMcy9aqtbpLjgSNK0GCRtsRWB41ujt%2BF5fJcfaNg83feW2nmMUbUtrZKSSSD7%2B1Jlht9mvLm1%2BSNP87YBYJau12La0pPqUkEADvFdfxMjri0cPPwk9Gi3idYMBpwNocSoyOwBrt48aa2YZJrs0NzgTbXb7WkaZ%2Fd6isuaFMKEa2VYblAdUVOaTEkKP6VkzSaSoub9oRuLpP%2F4m%2FI%2Fv9KyZHP8AlYMuS7Aanm3FylRJMTt%2FGtODMpaY3Fkp7JCxa2z6WkIJQdiJH4ac5pGxZOWy7coZaaxrDnXmFNpxJlIOk7FaR%2B8nvwKxZ4XL8UZOClKkSteDFtpnFGkEPj9nctjaD3jrsaT5UXGtUPi1DRO8PdftPIebcK0FALZWeRwQaTEJTXdDzM9%2B3jNi4zrDdwEkoIOw27Gglo2SyQl0UjiLbtwyLVYWq6QJSTuSntQX9gSVOgHaBSWHrckpXBGmNz%2FcVEDb9AbDHUvXL4eMBCgdhEVOTDxYsa3JjTFGi1dJubJxYcmQeoPxTIJ%2BwMritxJwhQx3DAsrb%2FxAAeY2r%2F7o7g96BlIguYLRLDYaWFtuNdQNgKOPQvIBLJYaebfLhft1dCd0%2FBozMoyvsuTKmKs2Z8lbbV5YK2JURrb%2BP6UiTSOh48n0T3G8O%2B%2FYM5c2TbToQrV5SgdWnvq7ieKFJdjM0t17BmScdfy5iTdy05cLsyQm5ZUdJKevtPvTsOXjtdGTycTkqfZN%2FErD2LnBTmPD2GLvCrk6w6oEb9jvAV7VqzeJUVNMTgyJXBs1TesX8OdbxDDVJuLYKC40iW1e9KwzXYUmlqQ2zm23iDVri60aWbhv1gcNuiJmK6y6tGZpeyoWlqs7hJWgqt52gfrRvJfQEWiwH7hs22HPtgLbUAd%2BUwRQXJ6ehvJdoyxW9vMNvGLqxulMXLKhcsrSfwn2%2FPiglFJe2C56Ni%2FC5TOYsXylmmzUFuPPFnEGNH%2FicHUDneJrm5JR6o0RkmrN%2FcnZm%2FwHM%2BAXrTarWzYeLegyUrVJ1JV8idjSXSHxm5aosm3xeMVzPc27ahlHEG1OFsGSw5wB7QaUsqT0blhTSvtEj8KfBI5synnLFrRgPXlg4la1KBGpBI499%2F0p8NqzB5UkpKJz2x3JIzZnHPLqGlN2No4tgrKSdBCiIHzFVy2MUHFUzTzMVym0zX92s3FIt0KLQI422J%2FMVemJbdmw%2FhpmRjCcNUguul5LinBB2JI7UEWk6YUo%2FQWzBm7F3sOtWLcqTahtyAgATqO5Pfmqm3eg8Sgn%2BQMy9j6mTb2pCy0RpIIJTxz80pSkuzbFwekPbgW1%2FmJ1H3q4WVJAQ2kfhA5kCiUraE5MSSbHuCYhjWWcewTEjck4OXlgtASlUnclPWJ61odIROMWtEU8RkYgcRxZal3N7h6yu3aUsbb7iB%2FLpQSlXQMa6LE8GswLwrL2XG23AzilveOKTvsog7SPrQyr0a%2FHL%2F8AtD5%2FtM4ZP8NMORYvm%2FtcWW7duJSNOnSkaU9SfxH8qFyVB4OcW3I6Kf8ATLyNlvFsUxvPLVq8zi1rj3%2BGNshuVNMPslSXB7hSQPgmt%2FiJBeTGXxpH6SvBSxcwnKl1blb2KX%2BFvK0JG4TrglIPTedq6uONL9HNzqMXooL7TSseybmnC02dq%2FiOH4tboaftLdBUtKSvzNIPI6gj3pPk3drY%2FwAeUMip%2Bjh%2F9vlSGMo%2BEeAXrxbxe5xW5vsSYZBi1UtUhv2KG4APSTXL8ierR1MOByTb6%2F8Ak4UY5eWuKeJN0lpTC7Fm%2BcJUFSlphvcpB6gAfi70zxJyl22kcfypcW0iuXL53OOMX%2BYcRaX9yaWXAFE6dOo6U%2B5PFbviTMXN%2FZKMo27ucMyWKsSfJ815LLLPmEqKeyOiUpG%2F0rLm8a9xCx5JVSN1M9D%2FALszHg1hhqGcFyzhllb2TZM%2BWyhCYneJJJKo5M1mlgn9Gzxbjpm6X2ffDfBcexHCn7lm7OEtLCbNsIPmXChy6frJHx7VWHA5PTNefJSs37xTDk2eFWNndMtYXhweW3h1khWp95sfvuCSVqMqUVqre%2FHpXaMmKXF3Rzjz5gWI%2BJviviFwxchGFtqNuwsE%2BW00nkj9d%2BSa5fkLlI62LPSqjdXwV8PrRd3huE4Rdrcatky%2BUiABPHyo%2FpUj41ytGmfmOKo3wxrKOE4JgSnQ02krbCCkRCB1AnqZp7jSMcfLlKdmmVzlW6xTM7riGNdixpWCEw22R%2B8tR2SB061xM%2BNynySOz8z0XNlXA7ayeauGlpv7t1QS1A9Lh7hPJAn6mlY8Tb6ClmktyLMxvEALM4VZPuOXa4Fy%2FwA6lg%2FhmeAfpttTssa%2FirM0WmFMt2VtYWaT5aluGSrV%2FmPv%2BdBBKtDFsnGGrUAXtBQJJI3I4%2FhToSaFZYvocPZmOGqUWHEhSdjB2HtWuGdexHx%2FbKszl4qpw0uIdvgm4UYSJGo7dKd8vsbj8dPpGuGI%2BID%2BI3jiWX1LeXKRqGwBrneZvaNuHAl6JxlNiXUOPLUu4MEkq2iuXFK9HTw4q2X9grhPlpaC1K%2FDqSevvNIyUpbKyy5dFiW7iC2n8RVxPY%2FzqWITaCaLry5KgFnqSYqC3D7Hib1ISZWZidjP50Sm1oW8Ks9Tdo0yCopJiP8AiiUmyfAhNV0gEBWrr9KtN%2FZPiPE3OpK9yZ4kf3FTg32yvhMA%2BlsncKSZIif79qt45L2HHBy%2FQqi5lI5UY%2BNvarhP7YxeP%2BxZF4klOkogkTO081alYxY0EG7hRPnSFJ9yDFWhOdpdIdNP8GdHA4AFFyX0ZHJfSCjbqdQCi4NttvajT0EnGgyy42sJCAkRtvzH9aJfYfFB6zd4AnSDEkzT8U2tmecaWyW2DsFJCiARuTz%2BVbsWXRhzfolllcECFlR945rbjkY5SVEpsLpMhOoyOhNaoSFEqtrhKimNQ3Mz%2FCtUejLkX0SazuAAmFEHvNNgxDSfZJLW4lQEpKR0p0VsD4%2F2GEXUJIUpaSBMjei3HYmSSHrdwpJgLMdppsMtgSqtDlN1q3UpUdO1MU70KkhUP8wfY9hRKBSx2IG4HqJO9R%2Fj2ElQyefGkE%2FFCslg07AzrskkmD81Gq2GB7qFHcwR9KGEt7IAbiSDJJPf3pnFEArywkHeATuDWOTdsgNdWqHPURI%2FEBS27Ik30DHFKC4BIRMTHNaIxXY5xQp5mw3J6H3ogHAqPEBCtMTBkA9TXDnR2sKZD3wQVJ2EKPq61kyXejow6B6tQUhStRTBms9FsKWypITq9IgmTvNE5i5WH7dQIMqCjPXk0cXaADNs5MARpG239K0wp6Bn0F2lzHqAH8K244pLRkydj1tw6gfSQP0%2BKtJ3YlwHKlOEDY%2FU0YpipOoEyYPXirTohmQZkAL55FF8gEpNCDiSpcRJ5ijcbDTtHwSkBEEBXvzQShWyOOhwkK2MIVv8RUjG0DwQsjUCZAM7DsKnAvihUqAJECd%2BlHFFpDtCgSkqTv0NVPolD5slREgwRsSImgUmDKKYQaOk8zvANU3YtSroINnUE7pSJiaJQC5Jqgi0uVQYAInmmgSSvQ6Q6QoEaY7A71ChRbhUF7GCN5PNVv0QHXTZMwQQBtvQzdaIRPFbdxSDpSkjt1oVAYm6pFH5wS%2FatOug6kgEaRvFRwIpSXZo94p5qXhzNwpRecZSkqWB%2B571hyY99jZTdWcUftIY9Z48q%2FaRiWpEKGkgyk77b%2FQfWlPyHH8UMjmUoUcyG8pW2IY4fuptk32sENqI9f51ITi3UvZjWC3dnWf7LWVbK0tWNaF2t0WwDoUdKlQDxx0pOWC5V6Oh4WNQlZv9juWW7jB1pUmxuFaAZUnp3BjY1fCCVnTlK9P2aAeJuF4bhTt8Xm3Q0pRBTIKUz2%2FWixzd%2FiYMuBJ3I0H8SkWlwl8sFJaKVb9QB%2FYrpePkmn%2BRx80k2c8vEi0Ql9%2BCogCAY7CteaUZddhY4t6RrjfhSVLQoCDwY3rKmBlVOiOKvXQ6QZMAg7xIprjYtsWKFupBQVEGBzSuKjLohIcNeuGnW9QDikkKjuKTkzpM0QmorZfWV3cYZbsb6yXMkaVNqGx7VOd7RcU7tFyXKn3Wy68yi3efEO7bT0I7VJZuK32aIre2DvvzjWFrw7ywq5bUXG1iCSByK5mXNyYz42%2BiHO3776tYMlW0Tx3%2BlJbCSXodWqVFdqt0JUtCzyfxpnj8qougPmvDGsMxJF%2FYmbdYko6x3H60T%2FRHF%2FZAkMITfrcbcT5a52B296EGgTdOpbu4WsNwYjkUyN1oG03TDlteKYQm4QQhQJgo3ifag4sLmkGEqsszoasb9LVjdKBbS%2BDAXPE9qbinTpojkiu8WwDFsrX5w69aUWiRoUAdJHRQ9qbKDbtdCX%2BiT5Yuik3DbixoSSVASdXxWXJBm3xJxXZdOWsUu21MseZa3lmdygqk6eu1Li2jRNRntEldyzhjry3GloQ04CdBB0%2FFKyNbVdjFB6%2FRJcJxfDctYVe5dxC3TmHKt6PLuWXJC2HP8yOxHeun43kOEeL6Ob5njpy5ezXnPmT15Nccv8Cu3LvB3yAkrMJIO8BXcDpAroxSkvxM%2FFyVMhwYOO4Vc4clUpIKmZV%2F419j7GmLSExhFSpooK%2Fcesbpdm8nSpsxB4UZo20IytN2g6h9LuDMPNShaFqSRP8APtQpX0C8ikE8SvG7nCMIvXQnz0AtKXPMHr70jLKa%2Fihjm6oO5Bz3iWQ8fw%2B5s1rftRcJfW3yFA81hlc3Q%2FFnd0ztHlV6wxvKtnm2yw5i6wq9bN4lPJaeSIMq7g9KzvG7fujo85QklJUn0Sr7PLrWbsO8Rcv4ghgfietHFnZKgZjfeKTilZty46aSRvt9k%2FAbxOVfEDBcyIYt0u%2F%2FABg8zyonYCevINb%2FABfyuLOX%2FUVxkml0aPZ28C7zBMg59zQ3aXGFtnMSsP1lf%2FlUFqOo%2Fp%2BdBPHpv6GYPJWTJGNfZxQ8T8u3OAYklb%2BvzH3lKSQnYkHmi8aPN0TJBctDrKl6%2BlAKFKQ62ZBI5BHen5PHV%2FQiWZJ0zYbDMNubuzbuXVsNMJspSpQmTxFZc2NKVIm7A1th7Llq2hoLTcpUZid9%2BZrOl9jUpCmDWyznXFLi0U6bdpshIUQD%2BHfn3qWrGSjOSLWzFl55GUbPHXLZy2bt29UJklYO8%2FUiilIOGN1UkRl7HMFzlkVpTKGUY1a3rQWkpIUpsjSCTwapTvRU8LUqQUxTIlxlKxXfuNpRZpcUvWIGlRAIq5R1aKwyafFkt8NMPez1mGywbElJsLNTTtylxSStKShGokD3AgnpSI429mtukfoq%2FwCm54XW2C4TdZpQ4wyMfsFOqK0ylL9s4pIW3HXTJmur4mPjuRk8rK3o7ZeEOCqw1nMyrqHWLy2aeaWHdXmKUIWdPt%2Be9dSD0c7JOT02VlnHArTHvGPDry4au3FW%2BHXCWWwiWkjZCVJJ2KiU8cgTQTW6NHjfjBv2flV%2B30jMiUZowJ9OIf8AcOHYgr7uypRXcXarh1ZW6SNyTKQEjgACuNlxx5fkbH5EvjVs43MOYfZ4bcN21hdW92tH3Zbq1yp9ZVLij0Aj0gV1McEujn5Mm%2Bhk0i7xFIwezZUza6wpwAwHCOJ7x0qsmSvQHyfpf9jYLwgytb4ZiP8Aj16y8vEH1Gww9JTq0piXXgOyUwn3Kvam4re2hsMjZs3lzJ2JZkxezvsYZucTF1dpbssNZ2dvlBQAQkD8DYEanFbDpvRSrZJ5ZelZ0ryrj5yFdHI%2BEHDMczqtCEXirBBUjDdtrW3X0Cd9S%2Bu4rmxXF8Uw1yaqRs9nPLmOf9rvYfh91Y4FeXFqF4nizhCl2zAG7aJ2bSJMkSVEkdK25cUeP5MuDZqGzheVrfF7HBsqWbt6ytRWu6gl7EI4Uofutg%2FE9a5c6uoo34832zdHwRwz%2FDrppnDGn3rdRAcXMlx795SlcAJ4iix2mHNuTLu8SMTtlltv7ygYe0ny1gqhDrg5kjcn4pjkk7ZeLBJbRrjjRxLF1WydHlYaXIatGU6Q6U8EpT%2B7vEmSroaz5J8uujq4ZuKJ3g1nieXmvKUpFzmJ9ISpxKPTZIP7qBxPxsPzrnytS6BTcpfl0WFhWF2%2BGWrTl8tpTgTq9XPP8aPHDWySl9Dy0eXil1ptEhFu2RJPWD%2BtIlDdoLG2nslOLYpY4PYoQmFOGBsYpU50qGuW7KEzRncMN3CGH0h3USNREAxRwjasNQb9GnuZcy3T2JuuJeU9J5KpCPf5pspNIfhwtS%2FQjgOLOG4ClpUNR2Xtt8CsWVs2zaT0jZXJOIh5xpkhQEAFSjO9YG1fRFJy%2FRs5gLSVMoWop2AOx5%2FrSnjUnaKyKibsLKYUQQB3M0yOFozmarvQJJIVx7f80HOIUYNmTV2VJCoWTPMzvxVPIgnjaHIuCROkBPueDRWqFiC7ohJGobHaB%2BdVyRDEXSZBJgE7T1NTmiJWeffCDGwAncmfpU5IONIzRdApBSrURO8mrVehtDhm6JIkI9iTV0C5UPmrghMJcQNjImKqxUpJhhhchtwLAkcHkVDNN06CTN0kJAUrUR1j8VaI7SFTi29Bi2fEApSlRJ5EVpjGTXQSn9kjs3txqnfmDsN9qdBemBlaqyT2b60DaSK0JUYckqJVZvkaSXBHMdK1YXezNkiiT2NxsmCNjMmdx3rXGbszSVEotblUj1aR3O89a3wnoyzv0SazuCAiJBgSKdCaFcXZI7a6KoAIB702Mn2VJUGG7ggJlQ3HJ6UTbuxE%2BV0hZLy%2BpgdT2ooy2A79jhL6gQITp9iZptlDlF4VQFARztRKTQuUaPF3JGpSYBG3sfrRx31oAbOvFYIkxRU0QHOuxMAiPaku%2FZaQJuXSAVSmZ%2BtFJUWogd9ST%2BBQII61alJggl9Kkk8AkxsOaRkjtskX7GDmuQnZYneT%2FClMasgNdSoFRKiAd5HWnQdotSsRUlACiABvAMUYRWGJagJ0kpI0yOAZrzs%2BjvQivRDXwA4SSpQ2iem9Ic%2FRoWtDKQFpbIBM7RwKVKaY1yTQ9aUkqABKljk7zP8AOhEzVhS3IJSAQTPSmw6FtBu3VpAUACewPJo4yaKr7Dls8lwgcQOvQ06Mr2Y8kKex%2BkhIGx%2FKteOT6ZmnK9Cw0gLmZmfam8kLbMwsg6hynrMT80aZdjmQqCSIPfk0aminFWYRAHEgd%2BBVSlaBcF6Mm%2FLKtQiZnftS2Th%2BxwghSdlKPXfaPirJw%2FYpIInb33qBIzQpKiCAY3%2BDVey6Yu3IBMieN6ZBF0PtadIkbbkUxpFPoet6jAEjg0gzx30PWlGCCspPseaKLotqh%2BhyBEyZkyeKL5C%2BDHaFzGobE7EmaimU4sX1JIIUd9tzRc0UJOnYQrbfntSW7Ik30RvEiAlWj8UREUcGw5VZTWbikWz86T6TsRS80qabCjKznT45t3q7e8RbsFCVhSQQBt%2FWlZv42HGa6Zw1%2B0XgmLtu3bqLUwoEa0n8REnc1zW7ewvJpRSgjmPimNYjheNNvJ8xl9BmRO3x%2Bta8WKC3JgYuT2dVPsheMLt25huGYg2hCiNKnQYIiOlZMjbdro2Ys1aOtdzibeI4GhdpoYdKIlP9aXz0bI36NIfGDCGLpu5N1bpLiyoBQP8Av%2FGrhJgZsfJbOZ%2FidhIti%2BLckNyZCdx71vj5iS2jj5cST0aHZ8sVqfdDjczwkyelD%2FeaqhsMMTWfGcMf8xbjSFynr3HxRx8iEtSYvLiXVkMctFMuFWkgnnUODRzjJK10ZsmJx3YUsbUukAqJRHA%2FhQxgq5NFxx2rZNW8Chpu5ZQCsbkBX4xFZnOMn%2BTGPCia5YxF7CnErgLsyf2jRJ2P%2B1XHPGO0Nx4mvejYPD8WbvcGDhbTdrE6dgSUdz70nJllN36NUJxj62R%2FEXGrxti8aSUlHKeJHx1iszVvRrck1aVEaQ41b3jlu4ylTSt%2BIIP%2BYdI3pU81OkAsUZbbHimUtPNtrUshQ%2FdiFDkGl86ey346e0xnjITf27Vk84lm8TKWHBweTCv4VquzM40yp1Mu218hCytCwTqT%2Bm3em0mtCGq0B7gLVfqaKylzTttGr4qRX2Rx9ju2EW6ilKlLTII42oyjKxbYWksOO%2BjfSYI0kfFDJ%2By4vZdeXsbwTGcMtMHzclV2hKPLbuEq1LbTOx3322NasPlKuM%2Binh3cXQNzFkY4TdWWL4RdAsK3SpBlDgHSfyqvIxX%2BUQ4t%2FwCoiDWK3FjiCX3VuWxSSCpsT9PisT7GNlh4Vn9nC7y3axRIvMLWvdxM%2BkHqQTUvewafaZb2M5KwHHsLbxTAMzot31KC20un0mffoPmjcFWuyuUl2R21s1Ybh7mGZtbcxfCViHmmQlaVJ3laZiFRMU7DlcP5PQmUb6NdM7ZMsMDW7mjw7xu%2FucESsq8h1spfth%2FlWJMj3rpYckZLRnyST0uyncyNNZgZYxa3t0tXChofSNoX1I9jTca0KklVEXw8uNWt%2Fh7iVlxA1wesc1JaEPDuxRu7Fxhb9hIBSrzUp7QN6pOhypaowwjFfuhbQ635uidJPP8ASs%2BRU6QyOto3o%2Bzb4%2Fqywze5UxC5RdYPcpU6yy6okM3EQdI6Ag8e1cvPhknaOn4vk8tSNx%2FD%2B6xXA8KxPErd0tNOXBfMbEJI2HsKyJ72dd5nR0U8BcwYq7b3l%2Bl554v3DSG2wTCtKElStup3rTjl9GTLLmrZe%2FilgmHZ%2B8DkYbgaHUXV1j67h8oUdTKkJIXI9yP4d62JN49GWDcMij9nEb7YngcnJ7fho44hbd3crUl5KYlDilEwR7AfrS1JxKyyV2uzRHEbS7sry%2Ft29aliV9tt4oJZr6M88MZO0bk%2BGuV8RxHK2GPX4KG3GwW9Te5jn6CluVq32bMXjxcewZj2GqtXybRpptK3TtHJG00Kr2alGlVDfD8MVeYlgybJhSF3OpLy9IglJkifjvUfETymvX%2FJ0p8PfDHKOcvBfMq3m31XtpZOMPlQJAdCCUFJOwH8aDmgk5p00cs8q5NvMoZkwrFcZw4py3e3BtlNOgAEhUHk88UMGrNLha2bd55w7DsU8L884Rb2zKb%2FAPxe1WytHqLbKknmNhPP0rQ2mjPHx08q4vRPPDPKLWCWnh%2Ffvhi2cebxJoFLUuLT5JTqO28kRQYk12dHJ4j5Uno%2FRP8AY2y%2FfYSjw%2BwtdqLrDsPbRbLeSAApC0pUoaenX866OFOzj54RjFp9nU7G8CtsGQ6zY2wYUpotMqQY8tKlSmQeu8V15OPpHIx5Cqc6WarNq1zf9xuVpYtEI8sz6jJ5Ij8JVJ996zeQ1GNo0RaacH7ej8gX28sMz8x4sZpxjELu9syF3lqq5ZXoDzMzKCNwIKUzM871zcMIzk7Op5WOLaUTlJf5VxZu1w24umf8Ps3En7s0o6XFJmCvQdwnsoxNbliSVGDL4ntsn2T8pPXryLa2QyyzAl10QGx1V8CCT8UMscYq1Yl4F9myeRsPQn71mRGnC8JbQcHwRTiBqWkbuvhPVZk7%2FwCv2pnj5OSGY8SXRa2HvXhNmMIxm3wRCdLIdLig%2FcKKogESokmNhsKmXCpKmy8mRRao6r%2BCvhrgXgTkhGeMw4ViedPEa7HkYZhbDf7a9ulgFXpVMJQCBJ2TKid9qPHhUFpbJl8m5bWiF5hw3NecG38K8UcfvmFXTpfxK3sXA3Y4a0PwslyYIGwjclU7Vhzzt0WoqS3oGYBmDIHh1aXV7a2lziulBYD5Soh7aEoSTBV7%2FhApaaSNnj%2BPGK0Hct%2BO2Y3sYtMJy9hTbThEItLdAKlk9AkbADqfzJpDy%2BjXFR6bL9y9ljG7%2B%2BscezrfLxjFCSGLNpWq3sFEfug%2Fjc33VwOlUkn3s0KTRPM0WltkO3TjF6FP3LkJG4UqI4R%2FWhnFJaQ%2FDmi9Mg%2BVszf4hcOP3LRtGymAgHUopJ3PzWXJJGqctVEuG7Q1fWtubcvvSAEpAnT8d6ufGuzNRLsEwBeF2UONBp1RlSTuPr3pDb9F0U54iXK2W9LSw5cEaQB%2B7QYoxb2PXF9s1lzBb4m%2Bw5qacjc6iZ%2FOtXxqK%2FFGyEkuijMaS%2FbKU2lJAIIKxzO3WsmTs3Y5aItaYx93ugQtxegxpOw%2FU1mzp1%2BJeTHyNpvDvMtuQwoqVoBGkpPB9q5zg%2BVsrGktPs29ytjIuLdBI0JH4YNFNJK0FPET3%2FEQQnSlQAPJVEUrJn0Z%2FjPlXjZSEpQAQN5n0%2FSaVz%2FYTT%2BzxF2g7wtKpgdZkR9KrkibHKLtA9JSUL5AI%2Fn9aJ3RTgn2YKuwkJWkgoJmOYPeqLnCL6ETfla9SkLAAJAO%2FwClVyRcMaMRcawFKESJE1OSNCxJKxZN4oFJWJ5npQPI09A5I62PGLtKhI1QRJ35pilaszLGwm07qBIUDtEj%2BMU9dFPEx%2Bw%2Bfw6oI2g1Yma0HGLhAA%2FKmRyUKaCtvcpSvSlYg8f6a24cgmck%2BiTWtyUpCNUSIA7%2FANKfYDZJLO5OlCiue3WiU2JnTJXYXPpAWSeRvW%2FHJejLkS9EptXQkxE8CJ2p60zHOPslNncglJEaeh6frWrHvYtokTNwAUgLVE%2FH5VtxdCp%2FokLFzCUCVlPvRqVCp9Bdq4GoCSaYnZklJp%2Foetvk7oUSP51bQua5djpFyAnSSpQ9hVrWylBLZk3cIiCrUeOP50zk%2FQMkxT7ymBAKhwOYFMBUGJOXAAMHcDrvUrVkcRq64kpgfBBPNNi10CDFrElKkq9jExS5uyA11QBIE78bUKyaqguLBDxc1KISSDxBigU%2FsYor6GTiVaSDCjE8c0Da9C5NehqWwYCgkgDeBvVIpOjHyUdNfzRfIwvkKmxIjSoFUzvI2rj%2BSq0j0PjOyF3iwFn1DWBMVzskfo6nwoZhSSrUk7jgH%2FesOSMl2ThQ6adkp1SVbiO9acT9ESQUYUNIEkbzxx8U5SaKm%2FYZtnFEJUYJ%2FmaajDLsJMOlIhKyFTPPWrTFzSoKtvJ4VsepIp0ZoxyVOhwFKGkAiPnmtEJIBxTM%2FM33AO%2FeK0Rdg%2FGKpcE7Qkdf6%2FFEU4MzKgSFAExsYO9QFquxVKtgDuOo6VChZCk7KnUD7bVCDhOoCD5ahUF3I9UoghRUO3xVpoOPWxUSgg7E%2FwC9H8iLHbTwMaiSoHmOKpzIO23JJSdz3n2oAXGx82sbDeBUKeND5LojWkiY55%2FKrVFylQsi4IgFatz33%2FKrUWA52OU3APqCjEcRzRRlWmUuIm7cDSkKg9qk2DCasAYhdAoWRG8yeZoYuhqUXsqTMjgdadStSTpkEHaqnsOCSZpt4rYfZvW76lLfUmNhGxrL5CfRqjG%2Bkcj%2FAB3y%2Fgl0zeJN%2BUpEwlTR9%2Bn86wSXofxaVNHJfxF8O7B%2B4ubi0Whad1EyARJPSrk%2FRn47dUv9yd%2BBmD3ODYjZOMXHlqkKS4PxAjn8tqTknxVs0ePhd1p2de8oZnxM4Bat3rg8wJgKmR9TWJeZHs6EvHaZWWfcUeuGH27pAWgH0rnp89eaZDy4%2BiSxNnP7xFZt3XbtOsajOlIgpOw3p8suznPAkqNJs74a0p15QX6kjoAOepNMUjNLC47RrhiWHqLiivSpA796KckukU6q0QHFcIJJWhJSvkAde8Vox52tPoyRy7ImhLlg8V%2BpQGy0ngimyzObpGeWTei18AdtsUZaasXQzeHcNrVt%2BtZckHF7NEcM5LTCT2G3Fq8tSkKAJhYjilylF9IbHHJew%2FgeMvYOspDo%2B7qOnc8pPQ0nZoXRIQ6v7wFlaFWjoJAQdhPSlXxN6To%2BxSzKW1Bi4ClI3CSmSR2%2BKvn%2BjPDBqrAN5jDYtWw6AhbW0cc9PigyttWgoYadchK4m7w%2B3vbd7UoKhY%2FyjmfpUhlVUwH47vWwC807elD6W3FvoEPKTvqH%2BYfzp8Z%2FTFSwSu2iJYgytl9DoBUgGQo7GnJ6szuDUtg03aUXJ0DRqkwUxq%2BDVopjVq7fZdcV5RS2ATP%2B1WVRKsHvmxoK1BG8HVHpnrNKyL2hkWSvC804nhFy5ZFKcUwtZKlW7h2PSUnoa1YM7j29FTmTZzArTMtg%2Fd4C42m5AKl2y0%2BtBHt2rXk8eOT8osCMp3T3%2ByrSu9WTY3tgxcBOyhEED271jz4YxV3sfsnWXsRfwFlIt1vLtCQFsPEp0dZSdxS8cJS2gZJstO8xJu7wG1v2HnUNiUqUUpX16%2F7GtMfGd%2Fl0UouyqscaTepbfwS4w62xCCDrBAufbkgyPitEZY1pMp4YvZROMMJtb26SUosLjUQu0O6V%2FwDqR19v1pqmvsw5IcWQW9KWsVQ%2BjZh30H3BG80XK9iZuuiPXDb1jiStJOkKM7ciii6GQi32MLklD%2Btsp08jbkVWVpIYlSJ7khdy7e27zJ0OIUHAdX4RO%2F1rnvIpRd%2Bi8bXI7S%2BC2ZbfE8FvsJzIi0CrnDSltYSJSoAgEex25rlvJXZ3cMlVG0f2d%2FE5rKuC5IwzErR1N6ceNs88UbFncfXpTMU%2Fs0TjCuzoJb4NcZeyZ4lY3hBTdtu%2BZd4dalfqVcncI52nat%2BOSo52VNz6Of8A9vHL2Xzlzwlx3EHlXGZm1D7yxbnUhh5xsLBUep5FB5ElQrFhTdnI%2B8y25jeYLi0TZut6UuOOOz%2B70kdqzxbZaxOEOTOl2B5HVhOR8p4tbISbBu0Q24FjYJKQZ%2BtKnj3ZuxLS4o1xzXgl7ilniuZsHs7dtiwuy26EK1TO%2BqPilq1%2BzdGM0tomn2f8t2uYsKx7HXVvOtWVybRTZI0%2BY4nkfSmQVq2Ys7nF%2FkjZLIGPvZMZ8Y8nXWJPKsbjCrZ62QBKW1wRwOeQKHgjd8KdSRSHiP4OYtifgVlXNV4881iacXWGUuAJQpYUZCT1kQaHLFRhyGwx3lcPVAHITl5iltmGzumWxbXKbVHlJEgLRqSPyk0rDlVWKl41U07s63%2BBngfhGO4tZ3Nxb26jbZZ81hh8yS7wr2BIgbd624cUpOrKy5ZQjaZ1i8G8EfwNWBtOXLNrc32GWoSgHdu5bSBG3Jgb12MOLj2zheTlnzqrN8MVxG6zEVLsF%2BY%2B2ywogEmQFiRJ5JE10OaOaoDfxduXcP8ADfGl2lizeXbVsssMuL0IdWR6QY6atorP5K5LQ7A1yXJ9H57ftr5Dyxgl3lQYvbWjl9ieD4ipVy8hBDNxpH%2FjTEaUmTv7Vgvi1R1smWLXJPaPzv4ple8%2F7lzCjElTdW37MOK9SnFE9zvxFbHTWxbmpRQat8HvWDb5bwq3adxfEkaHiN%2FJtUwSCegMAqPWIFEnoZDAqsv2wtLUu4SzaWLJbtbbyWFTJbaPKwngEnfvFRuuhPwtezoh9mHwSyTc5my9m3NOF4ldXFkoXNqi7UhDfnAAghuPUdp9o4p8YJq2Z8rhFU%2BzpDmPBcJTfHFPPFtilyhSEXBBdVbskT5baeEg7kwJJO81c2oqzKoOXRqBnfIuPZszNaYDYYlieHYC3%2B0YtWEJ%2B94gdtSlzshMkAJA2rj5pSm9HU8bAkrkOcU8Pw3aow%2FMeDN4XgeHgrdtELD11cuATLjg9KIEzHApUm12h34%2FZYPgzkvCEYa7i2D4DZYa9drUpDhZl1xE7DUfUoDvsOwooQsvkl0bjWeQrDLODozViLrDtxoClhYhS44B6Aewp7hW2U4SlqzXPxOzD%2F3Yh1zB8OVcoT6FXDrUIR%2F%2B7HXtWLNt2jT42Jxa5MpGwtMbw9i4xJ5hy2swTBUN179Pas%2FBnQ4P0X14U5hF9pbIN06FSdpjfpSpPHF0Ly3F17Nl2cFvMTYL7o%2B72vJ9qZJpqiSUiucZyexcXRlZUoSCBEmrWOo6Fxyb2Vhm%2FLmFWNi595tmHP8ASEjeqat6NmJttGiefrZ0uvLZtkMW%2BowOB8%2B%2B%2FSlTx3LRpl5E4vTNcnbK9uL1wJLiUgmBHFXNpKmaceScpbZsR4eYRfWamQs%2BrYmZM715vzvJfL9G%2BGKUnZublBD7DDaXHTr%2FAMomJ23rmS8q9IZki12We06tsJA0iBCvV%2BZpbyMW1fYoLuVAKcARuNQHHvRfIRYUOE3CCDpO3KiD096B5KZc8CRn99SZIUFJgRA6maNZ1LViZQ%2Bjz72nSBBCYNFzRSg7EF3SxJ1gnjmDVfIhkcdbEhdKBBBJPXrO1V8gzi%2FQu1eaoB1FROxnn%2FaijKxUsLCLN2pCZKkkDY9ht%2Fe9NTpC0nHQSbulnSANiCOeJolkJyf2FLe90qCSQTG%2B3IimxzWA4X0F7e40kaT0gT0%2BtNi0%2Bhc8b6YZYuVqKRICjxJ5%2FOtcEzM8Kew%2FbXS06RqUqdgeYpsZSXsTPG0SqxuFFOgiFCODNPi7QBLrK51ggKnsZ4Fa8TM%2BWKXZK7S7BSlaSEn2j8q3RMOSmSi1uVQkKUNP8K24ujKSO2eUAka9JPQmZrTjYDguw%2Fa3KilKBoBO0j3ozPk6DLVwIkqPA2IolIzyjY8Q8VJBJB7yOtNFcWOUXHQqAEz9asumKB0wPWEp3mOtHB7ooVDpHqBMkwN6tZPshgDJkklU%2FwB70TkgWmJKdVsVBJB7H%2BNEsn0CsYydXqJKk6B7K5ooq1ZHCvY0cMiPxidhNC19lc2MHGnNUFYI54pcuJfPQho1atZBnf6dqULG7jJJEFW3BHSrGRj7MUocJPqBTzvyavQdIpjEwUpAIIj34rh5pHoseyE3qm9tRERM%2B9ZW76OrEYo%2FEQptXHXasGVNMtyoeNL5KypYAESNxVKf2Z5TV9BJpQmUwZTB3mtsVoGTtaCdsuAkDywmTxtvTILZlnBphFDhKgooAPSBz8U3QDQ%2BbdKSglClDoQatxjVsVLDF9jxu4lMHUU9jQqT6Ms4VpDhKwqdUwDyOBWvm%2FsXGNCweQIEST0jp2pkW7oMcJWFnVAmOB1Ht2p6v2IlGjPUmSJSDx2oihQcpKTpPQTUIOErIUDJnmTUIKeYkEDUAfj%2BlQhml1KjJHU9ef73qEFkKiDEjkGdpqEHbbifSdwY3npUIPW3RAAIBGw2mfaoQeh2QAQUpHUdagLjYslxOgSDIiKhXBCpdSSQmVGoLnjQg6pWjUDBNXy%2FRfBkdxFaVJIEJVvO%2FO3Sqe%2Bwox3sqfMji0oWUFIVzEc0M9dGvh%2BOmap%2BItxdO2r5ZaS8TuUq3%2BaQ83ob4yadWcoPHzD7t1d663ZrBUD6dRUE771z8ybZozSt16OTHiRZ3bVw%2FwCWn7tcJVtCuQDv81DnZklKkRXJea8cwS%2FYcC%2FOb1BKpPSenahlFPsLFmnGS4nTHwv8Q045hiG%2FvIZeEQ24dvzmRvXL8rGo7o9BHK5R%2FYXzpiFwbV9VyBISSSkkjfpWbxpoZjm12aHeIr7TXnqUShUkxq4NdKe3oy50r0ae5jxAOLdb8xCuSArj%2BNLrdiZJdMpbFXQVuhLaQpMkjpT4SbM%2BXHHuJB3btonyVAD5G0%2Fyp8YtOzBPY2QjDLsFi6YStIEhQifaDRbu12FCK%2BhmMLRZXDdzZuqQ2OI2INOnNtbQucXekWfh%2BMl62S3fJQ4sjSFn97brWPV6HroQcw9q5Z128pSOQTx8d6hH0SLLVk%2B25%2Fh16Atlz8Ci5uk%2B1C5UOxxn6JVc5eu2nmWFrWu6bnTJguDt71klNp0aMeNrbItjeU04sxdqaQbe4CPwExJ%2FvpRY87iwcsL2ytMtP3%2BGYm5hdw%2B2bVUo0rO2rsZrRPDy2hcPKp8WGbxTmAXynmWfKvWioKbSqA6k8pHSOtLjiknsdkzx497HNw1g2MWQvbFNwtJA%2FZuGC2rqkjnbetEXXRz5ZIvtlcYpai3uHg2hTZA3T296ZBihexbbXbOJU1949MmTCgI6Grct0FWrBn3RTSlOMu6mY2Qd1JM8GiYNmdnirZdSEJcYdQSUjVsDUTBc6JWcfuWUW141cIt75k%2Bh5lelU9j3q1mkpaCc%2BXZLsIzbguan2GsaTb5exgJAbvEohp5f%2BsD8J966OLKpqpbBTkn%2BjbvIGRsLzRb2mF4hhjKb3SS1csaVB769Z3rQoekqJHK5JjzMHgBh1unEXcsjHMIu9Gl%2B3RK231DkiAYJ4ir4fZKyJGuOJ%2BHf%2FbF9YYo4MwsBKlF1p1ALal9gdorFkhwfKCFSzTRrLnLDH3by6KXFMsE6glagCmTxT4Ri9tCpLVlSXHnNulu4d848av51oT%2FQukOsSQLq0tr5tCojy3N90qA5%2FLrVTego0iPKBWhJk8dKW1ehikmTXIzl4xjLLbCS%2Byr0KQVcg81zs%2BBxVorHNKVnUTJDF7ceGt%2Fc2NqWsaw1lbzSgTrW0DuD3A2rBOX6O1hxXuzdH7PGB4pmrwjazDidm%2B3f2t%2BrELdYIEkJAUkTuY5j3qoP3RonjdqjorhOL%2F8AcXh3l5wYku2etsTZceSkbOpAAUD3G%2B9bIq0KaalbKD%2B1BgDeO%2BM1plnEGB%2Fh91htveWYIhCgkbucDbpR5qbTJhjWNtms2b%2FA62wjIb3iSFNMfeb5rDiwEEqLaVELWf04rK9dA%2BM%2FkyfGuy9so4ZZ4jlHOmTcxuuMIt7FpTDqfRoaKCQoA7xSJpt3Z01BY%2BOt2a%2FeBWUteIeL%2BTGrXEr61XZB8OBGpMAEbn8qXDK%2FezoebT4ykia%2BCvhXfZVypjFrg9hd3t5il5b60kylC9ZQkkc9fpFE8qSpIy%2BW4yW30SrNeR38oZ5VaYxYKtcVvbJdhcAmEendCp42gfnFIllkH4yU4%2Fj0bHZhysjOn2XG8Fesb1Iw3GkXiHUo%2FGtQCSCY4Goj4rWnzxbRhUOGb8WUn4a%2BEzdhmlOAiyXZr%2B8htyET%2BL8LgB7K2k1MMFSjFUb80JJOTOyX2bfDW8whGXsbxGxctMVtEO4bieggoWnzI1ISdhJPNdjx%2FHrs4HkeZy%2FFl8N49hmHZ0t7O2Shp3D8XQ0WkqBKUqbJAJ6STvT%2Be6RI401rZtd4ZY%2Fbu3rN49ceU62A0%2BxP7mpRB53MmKfilRiztOCil0GM7Fu6cyv92Ulth%2B5VrS5JS4kqIClAyTpO8DcyKZ5C1QvAttnIv7aXhijO2arBzHcCxHCMLy5hl7i1080r9iHV%2Blu3C5JUVKCCQBtxWSOJcqkrHzjKS%2FE4IeLWEYmnAsKzdfWbdjfOuKauEIYSl1yDDcJSISkgHc7mK2y8d1aY7x4KLILh1irDk%2Ffrpavvt5pQpRiUoifKSBwO9IljaHz8mNUkbP8Agh4a5mz9jYvMJWy3aJdHn3N4tLbDQAkkd4gQBx1qRV6M39x%2Bds7n%2BEn2fxgFhZY%2FmBqzzI6bYJYKkkeW3zqAMEBRjeN%2FjnT8S%2BzDkwy5WWNi%2Fhu%2F5xXeNHAMOdGlu1t1AX10D1QBKkDfkmT0ApU22qsNScVtEetfC7BclP3Nnk2z%2B8Z2u2S06XF%2BarCLXkJUofgUo7kTJrOsaj0jXDJSBNl4Q25wpeH4iEXyrh0uPqcWAvEHp%2FADOyEnpxtvQyin2DKTbtE28OsmW1revOvXFs9dtqKHfIbKm2UA7IQeIqliSCZcVzky5zFb3Axa2W5aoJ8poiNufw%2FlRShYDyKPTplF%2BJeUjh2DEjC02wCvQlsR0596yZMDTs14PJycjUt3LGaMzXKrINFmyKtI1EiBOx2pLwN9I6SzSaNmPD3wk%2FwVi0UhpbLUeqRueJj8qz5PDvbRWTLvRdWLh9iyTZ2TaUqAjiQNquOPdFvMpLZDGcKQwErunNb6yVED%2BdOliaQGio864Sm%2BSovOJSgbRE6hPA7UPxsPHkUU0jUvO2VWFOOQ24AdgNPIoHiokfIa12Vvh3hy199DgaBTMq2k%2FkK5vkrhbR3PCek06L2ytk4WwZUloFAgQem1efzdNP2dWL4%2F7ltW1sLRktBpPmD2gn865TjT0DKR996SklJOkew46cVRRim5WlKVp1kGSocz2oTQpculR8m52UsQWxzvz%2Fc0RTi1piibqFy5C5Ej2qNL2HHEvoRVf6YgDTynsetVb9FtREDeEhRUsgH90n%2B9qpugbj9GIvStKpM7bwYA%2FKre0M%2BNfQ7bvguBrU5qJ52PttQqCROMV2EWbyEDWQAZTOrjb9KdGXoU4IJtXRQpIJB29pIq2osVOKHzF1CtKTGpMgjtT45F6QuL9xQctbsqWhJKhyffuf0p8JtvQvIHra4C1aQVkAAjfgU%2BM60ZGiSWb6wE6iCAOu0Vri2IaolNm8Vn90kGOf51qw92LyPRK7O4USkBagNxJ%2BOlaYqjPkiqsl1lcgBKSNQ4G%2BxrbBmDLFJkns3yVJQFE9AfamxWzLKKq0Sa2uFekEKIJ6mtuKToyPsPMP6VJVJmd%2FitKdlUn2GWLjVA9SVc8irFTSXSCCHwNyFT7mfyrQU3Y4S%2BmCZn%2BP8AfFQytbM1XBSEqCQo9SN6KMU%2ByHyLgmdSl78bcVbx%2FRBU3YSnSkFRHJPWhUN0yCZdTpOoz1IrQlStAyf0YKcTvuQfmrcmwNjdakJKeVSZPf8AKgktUT42YLUFAwSRHUVnfdEUVdCKkAxUDUaMNAHqTMz%2BdWEfAoBSAlcjcTtVpWQonFJJUAqVjcTwa8%2FN2enwZSCXYUFq%2FCpPWKQ4nQTsZoSoJnVK5n8qyZmn0VKNjlorKpKlJHWOtZ2Kni1Y%2FQoEgBcmYFbMb%2FGrFxx%2FYQacAJIUQo78x%2BfvT4RJHSYQQ7CtKFT3JPvTU7Mb3schZRpiYEk96JSYEopqmPWn9SEyR0I34%2F3pyFf26FkvJCdPmajEDg%2Fp70cFsueFeh02smSlQidx1NaPlSRmcWh60oBIOs6iO1B80r0UOG3FegqUSnoe1aQZLQsPVwem88VBJnrVudhtG1QhkFSqVKIJ352qEPgtQUDqUkdd%2BKhBVKzHp1RtO%2FA9hUIPWXNcyCFT1NVZBw04pJkGBxvtVkH6HiU8Eg7c%2FwBioQcpdJTqkGd%2Fmjil7IOEqSpKgHI1R7b0L70VKjAoXsnUCSORuB0qJoSpNgS9aUrUNUjcTRNqqRVuysMzWQ8l1WrV09PIpKju2bIS9Go3iI0WGnj5imgZTxJ%2Bf1rNmjG7RpxutnN7xaxG2bNw1cq1pkjc8dCNuaxt72MjmSls5X%2BMrWHXH3tdq4hZEnVP4fmlRnZWfjJNpGpFji%2F3HEUM%2Bcl5lJ3BIIB%2FjTNHPjkcXZuN4W5os7pq3SXjbvgiYBJTO%2F8AKsflU00zueF5MZbNpL%2B8ZucJUoPLdIb%2FABK447VwZSSZujn2aP8AilZsXLlw4XAwFSAlJ610MXkRT%2FHYvPi%2BRWaM5yw562de8twqQokjc7V0lmT7OSvHldWU%2FeOvNIU24pTiokH%2FADD5o00xWTHKJD7oB1KlNKXrPIHM1ohBt6ZlhGwgxhK02rTqrhCREhHWo%2FIknxsOmhy040kpEhpQMmPj%2FakznKXbstToMMOJAUpGuCPUI5oFXQSJdhDzbyUeU6lDpnk7KHes%2Ba10bMK%2FEmTrFniOGrYuGPJukiUOtg7H%2BVZ3JjU6McOxfErdbVrfOO3SwP2TpJ3HT%2BFKtSHQzcVUQ27i9jiStKU%2FdsRSmFaiR5o56daK%2FTFyduyt864AG7FnFjapetXVEJdRuAqN0qj%2BdNhma0mB8Sk7aI6q5au8NtBcBtV4j0rKROtHc%2B4rTFti88IrVEYRfXGFYyWmw0LVYC0kkhKgP502jn9MmuKYDh2Z8HGJ4YQ3eITDzZ3KQOSBzFMVIKMEyBs29xa%2BWlG6dJ2TsRU0yTxtaBi0XLVysqSFNq5ChGoT8UVoyzhJkevwhq6cU0VNqVzHeq5Fxi16Brrj6gvzVqWQr0jvXQw5ItVWw%2Ba6SFbBL4uG4UooUfSmeP6RToWnTGpV2zbjws8SsxZUbtkPB7ErBogptnIIHPEeoH4NL%2FvIp0xUscJdOmbwYBmzDc%2B2X%2BJ%2BH2L2OU88ts6vuV4lTIc0n9xZBSSSdh7Vqx5oz6EcJR%2Fl0Ux4jJ8ZHV3Ded8mvlxKCLh4W0lbZ4cSsEpV3pjd6GvHjrTNUs2YFhd5alTOHX13cAR5zqVJSBPUJ4I4rNK1pFfBKjXvF8vusuOF1KEoOwCZIA96em%2FQD8d9kew25Zw15%2Byv0edhzydK%2BpQeih7irT3sVKFAe5s22rlJCz5RPpVGyqjJicfbClrYPi6aeYKm3kq1gpMGR%2FxS%2BcZKrHY8EX7OmXgxmjFrDIF2HGk3t0tlxLKlmSQR6kkdoivO%2BXJxm6O348Y8ds6v%2FZWxLC8Y8NcG%2B7MxZthbzySZ0LIhwCOmwpmJfiBmytPRaztpdYZa4Vg%2BE4g81h12263CiAUyTpVP8auVpUgsedSVSQW8QcDvPEnDso5oDzQzhgNocLcWDpLzZTsB%2BRrQpco8ROPJGMqqkQHKGIN578JM%2B5Wfw9ansMxBtpDizPlrVIISeh2pbkrNs%2FFePK5Jk5zdlGzw%2FBM454wtbNwwrBLOwftwICXW52n6kE1my4005Jl4JPkoyLJ%2BxrljDr%2B38QsyuYSy06t63aKFNpALJnVBPI3O9V4EVTZp%2Fq03pJkuxLALfLeYTh1s8%2Bmyt7tbrKmoMIS4FCY6bnY0zI6YcMPLDbeyW%2BO2R8KzhjeUcQw3DmnkaxcLX5clEiR9D2pMscZoy%2BDPi2ma143n1eS%2FA3xBt7%2B4KcDYuzd2yEIICSVaFJnk%2BoVIz4waRp%2BCOTKtki8OsyNZ3e8Jc5WbCU3mII%2B63jSQB5itQj1d%2BOaZjm21JBZ4ONxT0dmPDS%2Fw%2FELRnCXyLa9UbnD3krGzhU3LZEckKQZI%2FnXo8GaLW0eX8qEou7%2F4NbssWGYV3WasavkWxw%2F%2FABltl24WdK2AlRQAOu5G9Z4qXK6NsskVD8ezdzIqVYfnbMmHruWXWLqxt3mT%2BFLZAM79yTzWqOnowZP%2FANd%2Byd4qh9zK2GY9c2gVe2t86EFBnSeY9uPqaKW3bBgmn%2BjWf7R3hUvxA8LFYthq7HBTjdq5imP3Fy8UtqU03paZXplQTJn0jv8ANU427Zo8XIoNxZ%2Bdfxs8MsRw%2FDM432GOHGRaXNum4c8xsMWhCICjKpQIJCUn1R0FHkcK0zoqSUkmas4JaXGFquP%2B5GrK2IQgNqvEkABXVLZgiZkEjf61n%2BVImaEZKjrz9k%2Fwny%2Fiycp3%2BIYMvMeJtoFxa4e83ot7c76XHUCErABSqFGPY80MZps5%2BTx4rdnWzD7z%2FArVFh51nj2OOqUrzlgt6B0CUwAUpj8XGwimObXQqwyhzGHLd68t3bPBloGm4xm60hS%2BpDSeSYmDvT8fFq32Lk3dELRjOVMuizVhTOI3D124pDbIE3OJuHlXMn%2F2Ow%2FSo4vpBpWtsMYP4c3OZMQZxO8YctPKGny06ha4ej%2FKCI8xZnc96r%2B3K5xXbNjMr5Ft2W7ZiydRb2TI1OLLenzVdYB4HuaKOD0R5U1ZO14VbWLbj7ToaWsaVL8vUpf%2FAKyPan%2FHXRTp9mnvjVa3Vy8pV5eMWrCNiFK9UdoH0rJmi6bNeG30VLkSywdalvOOt3KwZE%2F0rmTzcTp41Ktl%2Fpu2k2SAwhKGyISqORNLcrWwXbBF0x5jC1NqKnCd9o%2FWlOl0CymsXbxRN8tDYcbtSYJ1bke%2FWtcYtrQpTZDMwlbTS9LRXA1Sf4gU6EPsnJsoPEMPN68p24Uor1cmQEj3q8mJAY8cuQlheFIafBQAkKKjMbn5rg%2Bekej8Vy0TuxbSw0mNaex0xqrznkTUUd7HtfkeXL0yCCptQ2n56%2B9cOTt2xv8Abt9Ax18JQCCEEHfaOtBJv0DjxvlTE%2FPU4iQ4qZP4T096nyI2Kl0IG6GpSPNUkmN%2Bm%2FtVfIi2t3Qkq%2BSFpBWrSD7QN6JTRaE1XZOn9olSSIkb%2FSgcxclH2N3LwqAIcAEmdxH0oXL7ATX0ZM3WsIBWkAnYcig5Fqfqh0zeKlKlFCj%2BISIo4yAm72E2Lsq2LoKdwB%2FtRqZn2Pm7hCdJLqREgidyPjtRhLGx81e%2BsDUAmfcxRQexc4hy2vCl0K1gA8CZB94G9asc6egJQSRKLJxBTq1SoHT7n%2Fat2JJ7M%2BQlVq%2BmUhSlAdBPJituGr2JklVkmtbkqLcrBIVPcCtlxekZsnRLLG4UVzrA6npNaU4dGeT0SyyeJIKQFDiTTov6M2WKaJZauqhJS6NW5g09OujE46okdq%2BSkFRMjknvWrHIzTxbD9q8IAIhXua0QyaEz12Gbd%2BCTqUE9KdFoXN2go24NWyhHxRy30Kkn6HCXQJVq3O%2Fx9KigxfBiwcVIIWeO9FTFylXZiF7aVfmDTeTLRnrAAAUAT9aptshmFiADGx2MVVshj5iSVCZHcn%2B4q7IYLV6SQog9PaopuyNnwUrb8KY26wTTOC7BSV2YwoFKTpWORB5oJqiSlRnIKttIPzQsFzZ55SEqlIVqn8XUntTJS1oH5CisTbJLmyjyY7bV5yetnpsSIVctalmRq34O1YM02m0joRuKoHKbElJSdIO5BnasjbC5s9B0nUdJPQ7%2FnzRcW0TkxdLkCUpMdTI3qkq6BHSH0qCV6U%2B8CnYpu6YE7eqHzT5HqIUodJG%2FP8AtW6CFNPocpe9YKSSmeT%2FAAp0WvYhqhRD4BBUAd4jvROX0UPW3hqEEEE7UyE0DJ6HLNwE8oTHEEEUxv6RknJ9BFDraghI6kcGSBVxbfYA6bc0kAGP3faKfGT6IO1KJEq0g7Abb%2FlTCCinEg%2BoKiI2oU7FcGZeYDGkFR9qInxswDoSIJCiZme%2FaoHx1Rkl3TIAQDxIqFfGh0l4q0mVROxJ%2FSqUUuhUo%2Bh4m4SSkQAekb1ZUVQ6CyCCANtpFVe6LHjalmSQsAGQYmrorY6Q5rUQUgfB5NQGUbCLSuClGw5McVBcXQncaTv5QA7RyKgXyEOx3B7W4aWnSUiJ5iqcbGmoPinlUqtboou9IAkSnf8AjSZ4l2NjK0cevtGOrwpvEEFprSkEKPUCDv8ANYcm9D8aVWzin4q5tuGH7s22yfUAmSRzH86yvFJN1sP5FX4mpi84%2BVifnOL%2B7qJAOncU6GGXowSyR9m3vhBmhFwGQxcpcUqCAYkbf71nz437Rt8WcX0b34TdfesMaK3isgbxBBgVz1FXtHdhik46Nb%2FEzC3lLWtsrQVSoz25pWFKLoXnjJdmmuZ7C7Q642oqW0OnSulKvZhRQeYbR1DqxpKEhUHSOlHjS7MmfPJaRBFeh8qUkKV0J2FaUn0ujA210H2btC20NrKZOwH9KGWCXZoi77PXWbYqStQSlxJkkjnbigUvTLjGK7SYTs763bUbe5QpCiPxgzHyO1BHHbsN5oPSiS7BLFh5wG2QybkEFIPDn9TVThvQ3HlS1RPbRxJS20htbTx9LzDuxTHVPce1YJ2maQFe39uy89hj6tJErb6aSOoNQtRsXtrZnH7dyzgW2MoAU0tKwCs%2B0czRwcfZbjQlg99d%2BXi2W8UW39yeHrJGnQ4Npjod%2BlUqbpEUmU5ij7WAYtdYfdKUpltWzradlJnmO1b4R0c3Lk3cj7GG2MVw9F1Zus3TaTqSoEhSfYijTa1QuTvobZdxO7wa6QuSG5BUk8qHUUTimgU2TxrCWsYuFXWEuMBxYKvKWQNXUxvSmqH7bHt1l5D9r5dxbLs7kek6hP1J6%2FNUDKL6KkxvL93h9wpi5KXkT6XG9xH9KYpmPJJp0NmMv3ryWlIaYWhX4fUN%2FwDemxSq%2FZMeS2T%2ByyHiIsVYg9hq3rZEBakp9ST7jmPehU6dpmpNPRZ2WbnBFIYRd3LVjiCYQkvwgLHT1xE%2FNao%2BSk7SsFxUejdPwlzN%2Fgqba0v8BuMVZWnSzcFxjU1vwYSSR2igj5ElLkhM8bk9HSrBR4aoy%2Fg9xmjGsQW%2FpKGGHkG5Y0EcLUga2%2BsTG%2FSuxjypK%2FZneCS7Ro741%2BFHhBjGJ3GLYXdqwWxIV5zuHtlflqAJHmMKMj5H5Uc58g4zmuzmP4leE13ai5xfA8Ww%2FMOEBYAurReoKSeNSPxIV7EVjzRyV%2BIU%2BfZq9jeDv2qVpUltRHJAk1nwZXy%2FLszdkFcCwpBEkcAf3xW7JJKrKLAyfcW1tfWjV8G%2FJcUEFZE6ZrB5K%2F6RmJXLZvdk%2B9dw3BrN3DbkBlm5FutlyJRqEzHY1zpwT%2Fkjr4270zrX9n7Kl9hOCiwy8qzuXWvLvyhBlAYc%2FESrpzR16RpyZYxjckWdmbD8SxNy7l13Dr%2FD8NdeaXpIDqishMdztAqL9hqbpOtEPwLNeI4FgVni9%2FcLadu221uhK59aDukVdFZI3KiG5CxrErXMfiY3asNHCsWJvUJB0pbUkyCfcTWecJPodk8qPHi%2ByyvBjxcxXPP%2FANRPD6xGHWtldXCWP%2FCFFO37RQmSSNMz70mHO3AKcoyqRdXgJn21yth%2BecNvcVxDEFOLuEs%2FsoS0hs7cd4o8DcPxY7KnJJssZGaWMbzphmG2160iyx0i4CNpQYBKSegVxHvS82RSkkmaoxgoN%2By1cxYhjeXcwowhu3YYZcs0ONo5CFtkgJHtFZs3yR6FY%2FFjP8vZrrmfwLxvxt8J814XhGJIstXmvoYaSdJcC9RQr2J4rR4MZy2wnmhhknIQ%2Bw%2Fk9Vv4aWFhjaLiwv8AC8duLW7DiJLTyFQDJ4JkHaur48E30Y%2FPyxck4vs6dYNi2XMCu7XEMSexCzctlJuWlFPpSASFEn3HWuhGKTpHNyxlJVRZeE4Xhbl3naxasm8QwK4Q1fh1KjpR5pJkn%2FNMEVrilRjyyrT0Ect3uLKznYONtLYSmxdS46r1EobRIg8AH9aXBDuUeJsDhOY2H8hFl%2F8Aas37hcQ23KiVBfXoPn3p0ukZJY3aaIfnC1%2B4eC2JYZhL6rhy3eFoyq61OFLilqUogcKgKMT6QBvUUfbGyVyTZwS%2B1d4aeJ99fZcyrkPI9zg%2Fhelxy9vbzzWbdzFb1wgqu7h19aIGrgmREADYVi8uDluOjfLJjXvZpt4S%2BDWKZjz%2FAGacaxDRiTOJOJRe3DYubUOpI9Y1z5igeCZCjwK5mKFumOT1o7t%2BCWWn%2FDPAhiGJ2r%2BL318sNqxfE3yu%2BviCTpaSYQ20NvSgEflFdnHia9GPysqekbFreds7D%2FFi9ZWKnhoXdukLWkdBqUR%2F%2FDx3rZDHfo5%2BTW2D28rY94hXSzbN4jf2aAW1P3VxpbCSN9IT6UjuEyY5rV8aWxabl%2FElljhuQvDBZxl7Db3EcbcCWl4jcMKDWgHZtorglA7JEH3o1C1oKEoPrb%2FwMmPGbO2ZcxosMoZBF1gyFR99vGygL76ETwO%2B1Z3CSdIGc69G4OWsOzZcmzu8fftwsJ9NnZW2wPdaz0pkMM7toU81%2FwAgbm%2FFL3DlXFwza3d3dJSQFFJ0I9gOAKb8T9lLLukc6vGPEcVxRy7ublL7zxUYQURpO%2FFczzHTOrgtfkVHkS2xf783cKddShMHSVQJ7fNcuWNPs6OHL9m1FtmZCMPFqlZU8kQYjb61bivQ2WWjz%2FuUEpYSorXO4iQBUx4k0BKaqxULtLlzzXWNSuRt3rVDGktCHONWQzMmHW77SwlASIiZA2okmmLWX6Nb8w2Qty8lEpAPEemJoMz9GvxZ3LZHbRSmwZSTM7BQkV53z4Omei8ZKyQ27ydBbSolfYngV5ny8bZ1%2Bhq%2BUEKUnSVTPMx81x8iaGRzSQHccK0KS4ohAMQOCf7FLUi4SraGSnizulZAJ%2FCY4mhcWN4%2FlTGnmHc6p3Mb9P50tx3Zp5taG7twEmC4kAHb8vb5onJLsGLSG5ugUrCgl1uOAoc%2FE7Ch5oBw5PQkq40y43pSdthvtUlFvoOGNXUjFu9SSlYUFqmIjcfNKtrYM4q6CDNz6y1pc0AmTHTrVxzNumgVjQ%2FauQ3ATKY3nkn60290LeP2Pm71UJAlST%2B6d495o02DLFSseM3WopSpKdI6dN6LmxMo0SOyfB%2FZpSlJPGlXPeii32C0iUWd04NKUI1Hv1FdHHN%2BhE4LomNo4QEGBECfVJro4pezm5W7pEotFkK1cK5M8n%2Bta45HQl45NExtHgogo0%2FUSK04ku2KlCiWWSyVIMKEDfkRW5diJS9Ets1qISSBMyR%2FtWiKsxy7JNbrgc6uwHanJCpv0GWHF7bQr5p%2BPejLNr0GmHFQAonmBJ24rSkZ5MINvaVbAKBPM1abLirX%2BB0l5alAwI6jsacmwpRQ5C%2BFAACdp60QhwTPSuCSZCOdzsKgkTFyAUiFTMcRNWlZLFBcEbJ352mpxZLPPvASoJ9JBEd9%2FepTIZoUJAJK0iD9anN%2BkDJWhVtYVJTCeYFWpP7KjGjNKhuDHsAN5psUw3%2BhdsgjWpEGYiOD3oZRb0Km%2FQulO5On0zAJP8qZCK9gFN4iyApZIUfpwK81PG6PT4Mv0Qy8tlSVJBO3fcVinBejocl2CHGCFEghQI36VjljknosYOMkQJ0z25P0pvOaWyCKmyhMJkxAkmJpcpOXohkFkQIJAo8eNrsDmh404BI2ASen8q1pWRyTQt5wUkqV6fg7UcY0IcUK%2BZHVOroDyOwoxT7HKXhvuIjr0%2BtXHsXPoeN3IMCQBp%2BK0RuzPKdaCTTkqEncDiRTxXK2P218bqBjtEVcXRB82oJO8dh701Sfog4CpISTB6bg1Iwa2U2l2fDXukqAAP0oixPUdJUFDfYDqaputkMUqPAIMHvz3oPkIxZt%2FSP3hvHH8akcgqUGO0uwRCwCe%2FWmXYCix8h0ahDio9%2BhqqIP0OHSPUQI7c1ZLY7QohXpWsKMGRUBldaH7DixuRqnfeoJscqKjunQpUfp7VAopN7I5ibT5QtTX4uSO351TdIcau%2BKDN65a3aQHEiIkjihgm9MKckujjJ9qDArm6t7xxll14JkrkdIrBnx8ZUaceWGTTOCPjVZXVpiF8lLbqRvoEEAUKxyi7ehHktQdJml%2BKKC7jSoJbWDH%2Bo1ohBN6MLSezYvwUdbTcsvpdU3BBjVBP8AcUjycXHdGzxINPZ0pyjiq2bMJ%2B8PKXt6SBBB3n3rhSk3KqPV%2BPOCjsDZ3YdvUGQFAggkKkgc88Vbwzi7aKzZouOzT3OuFXDDr7rZLiATqSTwK0SnrrZzdVo12x5poOrU4hSVkRp6zRY8l6MWWG7K9xJu0bS55rLaZAAIHWtWLPKPTOXNTi7QDbW0hSQN0T%2BLoa0tSyex2PJfYQecbdZCpkRtHWs7g4PY3I6E2WNTR8pYUoSIkGinO9lQjZKcHv8AyFtx5ls6kzESAO%2FzSJtdjYR5PijYGysrLMOEm5VibKrxKE6HWhKmSO42n6Uibh7Zo%2BOa1ZUWdMMuWIeeWly6SuA4gehcdz0olKMuiPJkiCsCuV3YbYNyG7xB8xBEgpP%2BnqaqWPdoZHPa%2FJk0xO0cu7c3TykPXITKi2Qok95G9LjF3thLNFLsra8w5OYmbhgLCb9obRGpSfrz8Vpi30YckVJ2iJWmHX%2BBvuONKavGVJIW04NSVDrsDsfenxyWqYiUNDhCnEqS45ZNC3J4H7ncc7UebGkvxYS4pWxw3aF95AtnXmzq9KCSIPSDSG9bB%2BRN6LUwleM2IT59svErUJhxl0QpI7g8n6UKr2MyL6BePYXa4nDrL79olQJSFetI9p7fwrXjljXaM08ko6omWUPD0PsW16GRiLQUQtAglCeqkjvWuVzX4gx8hey9mMq32VnsPssRfTiFncIT91v0NfibPLTqQIEd6y%2F2012aILn0Dcy5BwTAsX8jEcLQWVoLzTwRDboIG4A2PNLyYuNWGk06bosjLw8LrdVgi%2Fzg3kh0NhKC1hxWhknhepPqI9qBY13Zpg8npE4vsrOYPcNY3gHiljN046AResIU4lfUeahCiUSPYRVql7Fz8l9SRPbPPVzfkpzpieG5mQyyUKcvWfuz%2BiNtDwA1ewc1Vqj5s46eznZcCk%2BUdGnPibgGFuP4vdZXON4bbuAqLS2U%2BUD1CXRsT9TPSifmN9lSyyWmzSfM2FGHyXVSifMSpMfUDvvVvLJb4gfI%2B0im8TwtxSQ%2B0lZQd9uPzrRhzOf8hTb7MsOSW4K3VIQdoPQUeSEX2RM3l8A8OdzAh3Drm7cumFOMhYQqCElJBJnsIrmeRBRlo34VKUXSO8vgFbYPl7CIQFIZuEN4a4ouai222Nt%2BIgCg4pM1LJKUami%2BczYHhWKWeL4vaXARdu2QsUNgiSDqCSO0Eia0PHHjYPzyX%2BDmvgS8fwTJ9zlu6R595YXTiWkFWrQrUQuf75rJtPZrXkxe32E8Ex9WK5ft3X2bjDMWZulNqZ4LiDAA54kVbbaJkmk9si32PsbeR9onOGEPeXaWiVXlwHFE%2BgaNMg996VGKbv2PjNPaN0fCe3dwXLXi5dXF5aqbDT7jOv1qcISoKUPed6F42m%2BI2SlOUYmfhTle9fyP4ZeKFzixVi9nibTbqXFEJSyDAO2w6H8658%2FHmnyTN84TtwZu74n4HiuJ5RyjmOyK3Xm7gJeVM%2BcjUU%2Bkjpvx7VtyRm6%2F8AYZqD7I39mjMGI5bz1mnImJoX5wtVKYLiDDh1avUPcHmn%2BFKp%2FoH%2BrLniU0ybM2j%2BXvFC6ust2CGMExpFzfutg6dV0nTJCeAdhtWuUZqeujCkniqX8kbRZQRhuc8p5fxHEnUP3Dwcwy7bJlSEEkSI%2F9ga3Y%2BLWzHlm4y0Xhl7B7vB8Hxa0Swi2YabRZI1p1KuEJSpKVnsZA2rbCDrRy801J72Z5AwXGMXwnH2nnrVvFbaxCWi60ZKnZTJSP8oA%2FOhxY%2FwAd9lzaUvxEspt5iytlTD8rYvdN4piDdyqSgkBLa1n1CN4kd9ppkY62NdN2WJirD%2Bfci4hk9Tr%2BEYqi4S4l1J8s6QfUABKgYn1UTh6YEsijs5Ofar%2BztlC8xOyzNm3PWO2iW1ItbC0tMOTe3D5CgtR8x11IbSAUyVerfYVly8I3ytnR8bJlyKoUkHfAHwjyngmJWGM22Duv3qHFqbZxlpC3X1qIIfcSiG2Gh%2B6grUpUb1mhi4vlH%2FkrO5r8Zf8ABug8zb4k5%2FiWZL7CcSvWj5aXEOpT5iRsEI0zoSQANKBJ71qhK%2BznOD7ssqxxHCEpsb3E7m2wMCG2WEsJ8tsAdFKBIPzW7GlQM8jWrEsfvcXxO3fYs843tng6jqL1gVKceP8AlLhjQNugp%2FCNGWU5PVkPyzk%2ByRiyH1i%2Fx66cUIXcLXdTHUlZO%2FwIpqwvsNyk1tm0uUMDvmr5D5wtlhSTCFotC2ltPwdj8xTPjfYr55P1%2FwAGymDOXeFNKurm5eujEwppI29hUbkKeV3xuymfE%2FxhYw2yu0YhhZZsET620AhUd%2BKB6Vhxlb2c1vETO2DZvuPvGFt21yhKiVKMoSBHQfzri%2BS3Jtnb8eUUvsheEYxYPWz7LCWkXUkFCdyD2JrDRq%2BTHfTC1oxi6nC64HUoUqRKoBHxTFiSBnlRPsItC482t4qKwNxPFMgqA53EsC0ZYWUhYEwIjp7VqxoW5UBMw2TarZ0IUniTvsB9KZwRUZqzWnNzbf7ZuVJKekEA1l8iCRt8dtSpIry0QXH0axG8dCdv5VwvMV6Z38M9hdR0pQgEad5g8kfHWvOZezrYMlrYPcWohRMqdk8GCR%2FZrn5%2FHTjoeB7pUbBRQrmDwD%2FWuLng4u1sdHoDPulITqJQQBBVvv7UmUjTWxou41oCUwCDKTPNByYfJjF%2B5EqJlQkCZ999uKqUvsEHruEqHCVBHQGNM%2B1Uw1FpmP3tZ9XoUkxBjgVazS6Gcd2YIf3WlSyZ5CVcHpvQJu7ZTimPW79WnSFrJIlSgZg%2B9E5pbYt4b7H6L5PlBSi5v6eCPzqlljVoJY4ofM32lZGtSUlIA3gfpWmGRexWWQRYvEiEoUZjpxz%2FAFrXHHB%2BzNOBJLG8IOpQISZ1AzzWjH48G%2BxTJbaXJ1QAkHXAHYfzrTDHTtCsi9kzsbnWlKQkoJOwnmPb861Qbe%2BjnZMSu2TCzWSpAlYnqDzT4%2FRlnV6Jthzh8psEqG28mtmFvqhcpJ6JfYqJCRq3PTt%2FtXSXZlyQfZLLJYSRJCjvtTjM0SqzWFALCUhR327U5S0Zs7oNNrAMgnncgzWnDifZlcUFGkqlG4CtiK0iGt6CTS5SEkAniZ4ooqy0x6FBKCrk%2B0TNNojl9iYeJVwAORqNWov2Z%2BT%2BzIuqAMKIUBz0onGtsozLy5MkauI5n39qpOIUZVoScdCTAEJB2IHPyKZFr0XKViZfCSVFIIPSRtRgCqHVDfURHudveqaT7IPWn%2BSokjvH8KU4q6sgTbVqGsGEz15NVKNC5OtIcoQkpiYHb371Iv7AbscIAMACfrzWrG0UQC%2BszCyAEEbmRz%2FOvPzZ6SD%2BiIXNj6klIn2jmsjjWh6n6AbtnAI0BCgJoZRs0xyJgZ%2B0VJSEgifoKFQXsaqoDOsiSSkBM%2FNVOr0UMAkoUSpJ7kmTH5Vm%2BfdULeP9i6dXpI1ADrHP9xTI5LeifGLoc1LSQeI5%2FrTYPYucHWz5SynrAif96aIaPUXBWDOqBsYPNSL9i53QQYfUI3EzwTTVbf6FNfYSt3FSlJAJO4kSPimLJXYv4wyy5MFIXttJpsZJi7H6FHYkpSeRtFMjKiD1Cl7wpJgTM%2Fxq1NgShZ6SoyVKAntv%2FWjcq0GhJYBSkAJA6COPmlylZBL1Tq1KEfkaFkM0qdJMqSOsdRVJUqIO21lRBMExp3p0ZegJNoIJUmFQB8nkUZnaYQQuUjckxuJqAcqY7aI4kARzNQcmFWAogEoTE8nmoVxQTSmSBp3iSJioC3XSPnLJp4GQkjgT0qFOS%2Byvc1ZRaxG2eR5YUVJG%2FNHFeyWurOcvjr4BXmKsXYslOtAgwAnYnekTgpbIpU6RwT%2B1F9mrMOGpvnEWD77p1qUoJ4jpxSZxpqNJlZJLts4sZ9yRi%2BD3763rG5bVMfgIMitEIpaSMWPyYt0I5CxHELF8jXcNwd0yd4%2FhzVySa2aY5H2mdA%2FD3NYesWFXC%2F2iSD6iRtEb%2FlXBz4lGVo63i55TVWWbiWNW9xbqGgFxQ2PRUdKyZZy5a6NvJvs10zriqA%2B6FNEHgjclX1pqTb%2FQGRtKkav5muWHXXYkOJ9IB%2FjTHFdGJuT7Kov3dQWkad9jJmfpTYJdszzasjqzcNK1J9SIkFPQdo61qWO1cAUl6CNu6LhKG1rU3J6f07Utya%2FkrLX7DLeB3aVBy1ukJXI0gnmkyyX6GLHbLIwjDcMxJosXjqMNxppMLJVLb49j0NJb3RrhBJWnsMf4TmjKLybhmxKsJcTLT4EocSfcVHBMJZZr%2BRLcMzBZ3lqbbG8tqQqSFBYJQ6O496z7XoeqaIJmfJ%2BDXDrV%2Flm5dtFIXqCFK1KaPYRvFEvJa0IniT2gd5eJ3KW2wUKukcFKCkPdwR0PvV2k7FTjL2RrELfEbK%2FRePW9zbLbSSlYRBB7HvToyTFSTSuh0xjWF4itL2ltGIBQDggpK%2FiqkpehuLg%2B%2Bx0tk3fmlltduo%2BoL8vc%2FQUxSKnhcukOsKsmrt82y2m0OpELDi9God0ngGrSbdMzvCovaDTrOb8Iu2HsJunMw4e3uLVSvNUnrpj9Kd8Kr8WKyTgu0Xdg2XsHzzhbD9vheJZZzOrUpduppSW3V9thtQSx%2FYEZJrsJ5Y8NfEi5xG8w%2FArLHcLxZqJtnW1p88bwppWw6cb%2FADRRcl%2FHRSio9qy38p%2BLXiRkHF15a8RWMCugAEC3xHDyCkcbrKQdwK24MudbasOUIT6bX%2B50T8NsIyJ4qZTFpmjw0wDHsvEJLD1o8tNzhoiTI3JTJG4rT%2FeOTqUQJeNLHuM9kuV9jj7Oec37qweaztgGJ6AWXrVxhc9obVBVx0kntNPl4%2BCS%2FKJcfK8lbajX%2BP8AyRuy%2Bxd4PZaxdy6y85lnPj6EkOWt9iTuEYlr3%2FZp1eXCzG3IqR8fxo9RKWTNldSSX%2BFZBvFCxyVgNra2eZfBDMuXcFbSlLdyjM1viHlqBI%2FbFsFZ45XM1mz5IQ%2F0mnHga053%2Fsa%2F2OZ8uXT97Y5WwXLKLZStC7e6Upxt4kbBSYAn6CseTOpaihGfB7TNVfHrwbbdtTdYdgbGF3a5UsNJJanrB%2Fl7UeCSj%2FIvx6SaOa2L4Nf4NfOW1wHioE6QUyFb%2FlW2WSlrQMny0hEMWduhpNxhSwlwR5qFkx9OJpEnmfVC%2FwC3l9HSz7LfgBjuZsGVmrAFNXFopCm7tIfALbYB9SkzII5rLmx5JdjvGnHFL89G%2B3hTiOI5ZuUZJxLE1oV94bUkFJKlerSAOu8issYNPZ0Jx%2BTcWbp3F8cQw%2FAv8Ms7uyU06pN8lTckOJVIG3xP1rUr6QiWKltmkviSHsC8Q8bs3LcW9y8w88WW51FR9RUrtAjakzl9myGNJEIw%2B0ufKxlpHmrfYb84SneFAGPmqj%2FEz%2BTD%2FURzw5tzl%2FNWNZvb0snECllSkykRqlY%2FQUtKm2zZ%2FBKjcDJOaGLFhi6Z8i7w0h1vEGSofs23FGdvYEneopWbPlnKJfmUbfC3cLzXg9g%2BhvKqnEIsdCiVa0QoHT2MfrQShSGRyt1b2dKMNwxvGPD7IDYYtU2iC06pCUDSsKVvuPaa1fDKl9MxZZuLZEs6eDH%2BFeK%2FiTnLL9vci1OW7e9YKR6QUTq0qH7x%2FlTY4eJa8jlhjB%2FY4wbAzcZJylmi2uG7lxN%2BHLttQklpaSlSkkbCCRt13rVj%2FJUVlk45nFoleQMupybmFvB3rh63wROJIL4KSPMC923Af3QdhPtWjCknsy55c03FbRuVmi1vsJw2%2BsMMQhu6U43eIUVawpG4Un%2BH510stKNo42JcpUMLNnEV3%2BM42yEWQvcOt3W0oB3MBK0noCCn9aTB%2FYfH%2FuHswZaTdXmAYzh92t1ScMC1ICI217T9Tv1pnGP2HjnWpIl2EYB5GZ8r3jyli4usMuba6QlyEOveZMmB0SNPPWjcWxbkt2jXjxf8H8irsWsz4nd%2FdcSs23VWrNy0H2UrklS0hQhEcJnnrtSc%2Fj4%2B5aC8ecrqPRyV8Wvtn5VyLavsv2uD2uEW6ytll66m6v17gOvlsDSn07JEGB0FcP5LnxXRuyRpXLZydx3%2FAKv2J5WzNe3OW8qYfi942Shoof8AIt21Cd0NIBIE91EnmaKUM1%2Fiyl8KVzQOuv8ArmeOD6VJXkfB3r9AUGH0vqQGSYEhuCD9aasXkPSZXzeOnXH%2FAJJt4d%2F9bf7TGE3Td9id9gwsiufKucMaU0oHkLUlIUfbeanHyovsjnia9f8Ac6b%2BHH%2FV88Kc44Xhl7mDDl5VzN5YW8%2B1e62PMPUtBGsDrIpv%2FwCWnH8Zozx8bm70kda%2FAP7V%2Fh94i4fhd43n%2FK61LSFIKLzU0R13JkH2Na8H9Qi%2F5MvL%2FTp1fo6TYFmLCMcwa3dZxPC7xtwQ2%2Bw8FpJ7SDFdOHkwfTMMvGd6Kc8V8vZbxDB7q3uLsqdKCQChMK26TtTHKL0ZljfKv%2FBxC8f8zNeHWIXFnh1k4yyqYcWkHUPpzWHyvHvpG7xcrbqWir%2FDbxZskXCLh5xpxaoUsrBAHfnisKxSj6OlGbX8TbzCvEWwxVhpI8t07InX0p84L0ioq%2Bic2uLYehQcLrUxAgyTQRxewnBh1nHbUn0uJcX0hWyZ%2BtPTroXKNmeI4jbG0U4p5B24BouTeio49mv%2BaXWXbl5IhwEaT7e9Zc8GdDFOnZXaUoacXDckEHqK5WfFa2dfD5GjFTqnHfTCBJA23rzXk4mjpYszYi8oz6ExHWN%2F1rDKDaaN8Z2A7tSNHrHM%2Bknoea5uTx7ZogwI%2BrSr1aVek7EESRt9elct4Ysd8sgC8soWFgFfQjcigfjxDlJ3TG%2FnSdSiQVA788VIxiug6GTrqVrKknSsA7TAHegkoscm1sYKeCQpKinWeZOx26d6zzxRbpPZc8zfZi5dolR0kkgFRT89aVKEogxlZkm7BUlKQAIB32mhjlp7QTF%2Fv5CkhJISCNU9ZFOiuUrS0A4bH6bxEqKViEjb5p04X6Mzdug3a3rYSHIKUyQImRWjHCuhcl6JTZvr1pBU4T%2BLfb862QmLcSYWN6owDAAjYj%2BFdPFNozttE2w5wlaSFISsbiD%2Bk%2FWt8JpmedeywcMWVadYBVvEgyR%2FKtEYLow5kT3D0K0QBp424rQkZckvomGGpXqhBHSQNt60YmzLJv2TC0aJiANJ27x3rXxYiT2SayQpBnkxxVxtGfLkXQbZQUkhJ1djXRxPRiboLsBJA3GrgDuaNKhIQbSUJ07DnenxjRBdI2%2FAFcRFEVLo9KDqV6dRPETCaL5GhfF%2FR4NQOwKu07RTWgDAyZUVlQ33mqUUQ%2BWgr3SSFDkVail0MePQhBBhRE9jvVixw222oLAUpM9tjVBRin7FGyG3BBS71HMD2qpJvQLVMMMupXqATAmZPWhWL7ZT%2FwABNpSiSr06Tx2oVFfYhrY8QkJEDcjbmInvWrF9EAd7Z%2FiKtbah7b1wOCPQWRi4sU6lnYCJ770ueNDYtEfuLEJWQJ1RvA4pDjvQaf0Abi1PqCxtM%2FJoGasbpbI1d2cHgaIkR%2FOlNMZzQBdSpKykkQePp%2FzWd4U9k5r7EhOtWkCfc7mjhBRJzX2fGNRJOpQMRHtR2DKSaEwSSVJUpIHTuKZBmaZgXNyTJg%2F3NFSYqVvodsLCQAd0jjfk0VgqKYYt3CIMBQiNhv8AFEosLgg204DoAJT0A7itWOujPOFdBJtRWAkmEkc96dS%2BxI%2Fb9MA6560fGK3ZBfYEAz2JjYUMtvRDzSCZk7nieKrgyCOgAAagFQeapxa7IfIEmIBPxUSsg4aTBBJEmTE8UyEWmQfIKgTM6fmaMyuNhJshQAiTG8mSKgqUK2O0QSJntNQKM%2FsM25jSfVBP5VCc2E2SFHbSRHfpUBbd2Emi2VgCCf1psaKH4tWX4QvdJ6HrRJEI5jWRsOxdopW2JI3BTxQyj9BRa9mlnjL9lnCMz2t2n7ogAhR%2FDMz%2FACoY0uy1iTl0cMPtGf8ATzLhxG9w9giQSJbHpAH9azZ%2Bd%2FiJl4KjJys46Z8%2BzPjORMTudVupICiSvTGoz7cdKwzc1qQp0tC%2BWbNwFNu8lTbyfxETBpbH%2BP3osZxq6at1pcUpxKvwgpH6VlyQS6O5hcq%2FJFR5x%2B7uMOpWkhY6kfpSafsbZqfmtLjLiwl3Ye427VcFbpE5JbZUF9evOqW2v0qG8%2B9bIxrRy8uZyd0Mbe9cYcDa9a2zG8T%2BtOSkujPzb%2FiTXD7O3xJSHmB5TpBIg7UE8svbNEI2S9uwu7Zo6vM1xwQIUPbtWexjhStjdp9L1wShxetPAkAj86Cd3aCx4%2BX%2BC28u4%2B8iyODvXKiyrYtLHtyD%2FSlNx%2F1I3RjxWywE27bFqgXISbFQnzEb%2BWPf2q0%2BOkyNEEx3L9qt8v4c8LZ4H0OMkjUPcHYml5JJjI0kV5iT2LYY%2FBekp31Ec%2FPekthWmGU46i9YTaYhhzSgraQowfrRRnTFygRfE8tW6QL2zQTbkT5aSFKT7dK2RyIyZMEVtGFs8u0caU5cOqAHDfKvmrntaAxtLsLO3bt20t20tLxt4fjS4zye6SP4UMMb7o0rLjrZZHh%2FeMOKZdxJhmzvW1fsX9ex%2FwD1TT00kZZeNGbtG0eRvE%2FKmB3x%2FwC5cGw7M9ms6XV2bSLa5a%2F1JV%2BFyD8TUWRCZf079m0OC%2BJzT95ZO%2BHGcsn4vh1w95Bs8UKrO%2Bw5fQBawW1CODIFPhlQP9tKMd9G2OTcBxDM1jcXvizh%2BF4na28IF7ibbDptZky26kkKA95HSulgzxXZkyKP%2BhlyZZ8P8tZZDmP5Iwrw%2BzG0AF%2Fe8LIS%2BFET%2FwCJpQQDA3PvWrG4t6RcVKOpKrJd%2FwDVTL6LizTmvJ%2BP29iEI%2F8AmWAQpxkz%2BIsuCFj4VO4p7mrtAzhJatP%2FACTrOed7DFspt3uF5cytn%2FAAgJR%2F3NhBTbshP77i0BLiFDsFD2mim5V%2BKQeCKk6lJx%2FwzTnOPizYs2DlhjH2b8qtYb5eoYjlx44iyASYK2VqLqR8nYVz8uWVVKFv9UbV42NPWWT%2FAMnODxNx7MmI4g%2FeYAvL9jYBR0MN2qbVxsTyQpAO3G5rlPlYOTxndLf%2FAHKTbxzPeY7%2FAPwd61zff3y1eSU2zZcYWn%2FUTCRx3FXwm9AO496B2bfs5YBcpS%2FdYvaM4%2BU6nLNjS4lKuylzpCu4BNafl%2BNVJp%2F8gYssm9Ir3K%2FgVgtznKyy9mq2vsHwdZGu7W2Qkb9B1%2BlJl5Db1pGiSl3Rul4a5dsfAjN%2BIYj%2FAI%2Fj1tk1TTiXV2DYUXUqTATuRzsZI702GV8t9Cp4JZI0ts2stMp3j2b7rMFm%2B8bW5w5i7sMRCAVaVAc9QREH3oc0eUrj0Tx3xX5dovTLV3iFvmu%2BwO%2B%2B%2FXLd%2FbJxJIB%2FC4j0md594pUJNM2zhGUea7Na%2FtB29zmDO9tjGB2ryHvLK798iJQEaYjpxQZVYzHj4q7IA3frFmzjbDn7H9k2soEB1KU6RNUMpNEJzvbowd5LmBJdRhR0XAbidKl8pP1mgnG1oH5It7DPhfit%2Fe4DiWLtoSWrg3KtOn8TSfQYHfmlqLRpx5Iqzajwexi5dy5a2t64tVo3buvJS6QFhKVfiV1PAHxWXyMzXQ1Ots7LeAWYsHe8OcCwbEbhNxeqtVLZCk7NFR4nggT9K6nj%2BQuFSRm8qH5KSNs8Oy%2BzdO2hfKhaXWHG0WAZ8wwQT8Vvirjs5uXJUvxNEs13eNeHKM0ZLwjD3nMvpsk3DakolKBrghPuASY6RWflx0jq4o%2FN%2Bbe1ouU4hYY34XFNspCnMSwQuWdwkyVlsBQHsQQRW%2FHJcaOZK4Zd6NocCcXiuXsrOYmh03S7NpPmFGkq1ASOd961KdKmZZxj8lxLPyjl1ONYdjuE3zTYcs7ssphcSCRPv25p0Wn2jNknTtE5scoXOFWVm3ZIF1b27btu7HqVBVIIH5U1RSB%2BS22wjhWVwtrBsSlbdywbptRURqClOykhPEmR3imRg7Qq2cpP%2Bq39oDC%2Fs7%2BEaG2FtqxJ%2B3Wh5a1klomCQSeSrdPxPFZvPi3pG3w1G7n0fhD8YPFrOfipjuK4rmDE7h1p10rLLZ0NJAJgaRQ%2BL%2FS%2F9VGTzf6jDlrX%2FwB%2FRrzN4255Vmy2jrq0yRzxXTx%2F0530cXP%2FAFOT6stfwX8Fs7%2BNXiHljIeWrW%2BxLMGLXbdmwhpBWdSjBVA7Df4HtXovA%2Fo%2BOckpdHD%2FAKp%2FWJ4MXJt29L%2F6j9a2Y%2F8A9nr8MPCr7O7Oc8y%2BIOacRzSmzQ8sOuJAQ6UglCGx0KiQN69Vj%2FpH9Pn%2FAO18bb%2B7OJDzfMxY%2FwC4z5KX0u%2F%2Bf%2F8ApzZzV%2F0x%2FFPw2yg5m7FUXmE2qyn7mp5G60HcAkdYjmuJ5X%2FoqE5PhT%2FR3sH%2FAKviox%2BSDjfTfv8A2RHvBDDsWyfn7Dss5rwnEU3DzoaaesXFIKjOxUE7K%2BtfPv6l%2FwClZY5%2FimfQfC%2Fr%2BOWOns%2FTP9nrwzzllK1sHsNx3ELXCrlHmG1fdUW1kwSSkGAqeoilYf6fJJWKlNN3HRZvjD%2F3VkDBrrHr3HsXu7QpJ%2B7LcUtLcDpJ3BrZHxLaoV8vDbZxM8X%2FALQWGZpvbvDrrC1NupKih9AV6iJAlJO3yK6PxUqZnfmxk6qjXbCM7Cyui6VXZJ9Wnc89AB0pb8dPphqTrs2eyD4pXdyi2YZVcIVPBO5%2BvSsObHXY%2FBnkno20wLNrjjDZfUptQQfSD%2BL2nrWRRadvo6cG72WLguNpdSpSValTPwD7UxINyXTJG9iztw2Gm1lI467CP%2BKZGKStmVKVkPxRxS%2FNKnC4oRtx%2BtSatGjHd2Q%2B%2FWqCUhUjfbrHSuTmp2dLDliuxixdQEpCVL4AKjXEz4F0djDO9jlaISVlPqKjzO3auRng0bseb0DbppJQVSZ6kiQB1rl5030P%2BRkYuwNEkAq3JAEk79COPrXMyYXHs1Y9gG5WfLIIlJ3J6x3rNOEZLY6ORrQJcchLiAPKMbHbcR%2BlZJY6X4mmGS%2BwO84SAmSVKPpncTWFKadtDUMw8AZccUpyNpkkHvTcUHy5Mqxmu8bUhRCtIgbg%2FpWyUwVGnZkHAgp8xXmFQAKp6fwFJaV9DHIyS%2FGhKSfMJ2JEiKbyS6Bewgy64R%2F4ylQJEwdj%2FSmRpiJQokVm6vQFKWSsbKE06Sp6ZnpkwwpSXVQlalJ3PE%2FX4p2HLUrQEm0T7Cx5qkg6iDIPt9fy6V1o5FPpmLNk2WJhzayohMyANvetkMf0ZZtljYYwFKbOyNpIMTWzFF1bMs96LFsG4bb1JIJAJ24M1ojFGZxrZM7BgwPTJMSRyK14oozZnbJZasqUAiZ79a3RfqjHNWSW0ZATp9X581SyL6Mc4qwy0hcABKgehma1Y2q0Ldewo2yEASCdhTBL7HiW5UZSkGtBQ4Q1AAUSAeoNQg4SlRSVbhXBPb4q497IKxtGyk9p3NHyiC2ho4lJ2SeJBAEUaFyqxosKUNSiFR6oJiroGzCSSUDgngn%2B%2FaoQ%2BAJ3BIMbzzUJQqyAPxbGNo6iqbrsjYdaSlH4UiOJpaVlKSfQ%2BbdBkQU7mrlidWiOgkyCZlQUZA3H6UwVJbHt3ZpOswCYG8cfWuPJe09HbhKyOP2JjVA46dKBJPYywFcWUQnSlQHbvVTX0NpIBXNiEkwAT2HeskotBKZFLyy0lUiEg8zxQNJhfKRO8sTKykAHqAeKUx6ywoDuMmeCoR%2BInk1FFsjdjZbREkEpHPPSo0yhN1JCVFKiewiopULyDWFKVq2THPxRq0KFW5QSlR1EEnk9%2B9WmyRjQZYcKTBG5j6VpjfsGc6DFtqGggq1RHNO0lyMs8iYcaVH70GN9p%2FWrhKxKluh82mRq2K5HTimLsJsfpBhJjXHPST3pvHdi1ksVUZAUCJPSiGiJb1SSd47AzVSjZT6PFMg6QAB9eP8AaqUaE8mKgGQCmUnbmiLU2P0tkKIlHPbeoA79D1Cd5iO20bVBUm3odtJVM6k7jieahODCTBMb8CIJE0WgQm0VakQT9elTlXRAmyeJIgb%2B4q%2BbIF2lKME6AqImaYiBRCtzMgcc1ZBpessvoW2tKSDtxVcUEpNFG588O8Hxi2fU7asLUpKv3ZkdooWvoOM09SOSP2lfs4ZbxZF2lOCsIUNUkJ2PYcVly%2BO56EZYJvicTPE%2FwiTk3FLxdvbRbz6YH4d%2BJisOXBKJpjjaRr5i2MKtELZW0oQN%2FwC%2FpWSWKzfDyk%2F5aNdc8ZpbWi4QkpSpIJGrlRpbx72MnmjX4s1NzHi5duHNbilJPKe1OxpHPz5Givnr1K1kBMknrsB81s8fE5bFwixa0ux5iFqAO5MA7flWhY2nQSu6LFy65aFaUpPkiIgHmsPl4pJ7GXxei6cNcsLlhq3xNC1MQNC0QVJ%2BaxqUY9m2MbRHsyeHy1lWKYHeBQIJCVfiSofxFHHNG%2FQqfjOtMr9nMV%2FhbotcWaWmBoMg%2Br69KvJjT3AqOeS%2FGSLRyr4mWSUDDr1ZubFRKQlyQpH161mnhvtGmOeDdFsN4UzdsIubVdqthQ1olZ2HUH61mfjtO%2BjZyhVRZF8Yy9iB1X9oqyumjMt60qgdiKlJPYPxyW6IaLK1WPJaBsrkEp8tagpAPcDkc1JyT7Bc5J9DsIuLJlCAxb3qY1KaKhuOsHmnXURcly7HOGv4e%2FcEWdhhaWOPu94ogpPYKG6hToST6YHxx%2Bg%2FYW9q5fKS24hngFlt0Bv4GozFN4t9MDJjglbRN7DIFziAW7at2CmtJ1NJUHF6t%2Fw7j8qYoLsxSzuqRJcFyKVXItf8CubPV6VJLKfLcP8ArSQSPnar4oX8s%2FsuJjw3cwBi2uXLjMark%2BtDVhgzryG0kTCko1ykd9h8VbxJ%2Bh2PJL7LF8Pbrx6yfi61ZCx%2FPWIWq%2F2htr%2B1dVYNb7ytQDTe37pNXihT0FknN6%2F8Gzj%2FANp7PuVLVrD86%2BGPg5iLgE3V1huLW6bhqeui0UTq9j%2Btb8fmzXaKjhhVu7%2Fev%2FksvIP2xPCzNwGCYlljxPxW6QAolqzddTI%2F%2FSK8yInY6U966mLzoSVOIjJ4M5PlBqi9keIvhFaYQ3jtli%2FjQHGoCEC7Ytmm1mdkvLRDp%2F8AVJO1Ojlx97M3xZrptf8AY1hzz9qXOtniN1ZZR8E%2FtDYth7jgS0sKcWcSI2Cy43bhRO0zMVn5OXSOhjx44rllmkRbFMcwW1wF3NPjflbxFyXaP%2Ftl2Lii7cOjkBQWklImZ%2Bat4pL8p9C4%2FwBQhkfHC7NH%2FFr7WuSMQwd3A%2FDeyvsv4G4ooeS2ynznBuBqIET3k9q4%2FkeVkb4w6NkfFxL8sm2alHHrNNsq9s7tyxbWSslxYLiVHsJ%2FM1z3j3dE%2FuV%2FEnuQfGtLOLM4JnVLWIWKgUW94B6kJ7K9vcb1Sy26JLHKe7OouS28sZqybiNvcow24ufuYS0tPrLiOiVdx2rasi7Yp%2BPL7Lq8JcQw6%2Fypg%2BXrxwOWVpcC1beLY9JklKSqdknim%2FNaFZccl9BDFr7ErXHv%2B42vLQbZD9qWeSUpVIVI6bUpp32OwzdUQ3P6Td4NiC7Rtb2q0bLqNMBOqTIPMyaU3sdiW2aeXd4MByxd2lwtxFy1eNNaVpghKjPFA3XYc0ncWPMBsv8AGcdusOvXkqt2dL7gkR5cgCO5mrhTZz4Q1aJ3kl%2FD8uX9lhzq29BRdMNJCZCAtXERBJmqk3dI2xg6RsH4fYbYMZ5Xgt%2B0sru8LdbCQdOlGsGR7gClvG5aNSTcTqD4a3CGMJy7ZW2GzZKuy2kk8IMD%2BU9qLfQuTdHRrwwsxeNqwt8oectXkqQrVBS0okCPYc11PEbfZyvNXFWV14ueHVoM15bS60m6srl56xuG0qKS4FJOkk9uf0rVkxphf0%2FyXHaexjkPKWD4Dl%2FB8uYVhSHkYddKtlsLggMKJ7ngVeKD6L8mbyT5S7J25gOKO2N%2FbF8WTbD6BaFlcpaUggglM8EU142xUUkbiZbtLbFcUfubZwNs39pb3DqwIh8elQjncit2Km6MEy5rfL5Xg19c2KR94SlZXCNStt4j3inLuhfLewQ7hwRhJu3yhbinm1toEhU6ZAmmUm0iz8WH%2FwC0E%2BIF9m7xxyD4N4cp9DWHWK8RxADZLlw6qEn4CRA%2BTW7%2BneBznbXRl8%2FNOMUr7Pzy5xyjaZbwVKloSp5Q%2FeHG3Su1%2FaqLOL8kf9yqcHskPuoQlhJeWdIkbzx%2FOrk3RUsno%2FVv%2FwBKv7KeXvs2fZuxf%2FqNZpTheK5gwhdwvDsNfcSQ5boELSgHh1XQke1ek%2FpXiwyf%2Byv5PdniP6tmzY4S8%2BdcYaUerf8Ano6%2B%2BBv2hsA%2F6oWSfEXOLeKXPh7mHL7iVYblxd0Ib0JC0PPJGywVJjqBEV1sUn4mX4Miu%2FZyMil%2FWsWTPGXHLBXGC6T%2FAG97%2FwAUUv8AbM%2F6g32Xbn7MuH5SGesk4n4ueaiyfwO2uUruG30KKXAU76QCFTNP8aMfH8l%2FLVNfY3zP6svN8TFDHJvNHTpWtdnOn7KGK4B4i%2BImJYrd4FhikLtVFhoAHy1BJVIP06Vyv6vO4Nw6Z6v%2BjN8kpM70fZfvLHH8s4ai9V5zzNwWTqHACthXzHM6k0fRFL8U0bleLHg1g%2BbcputO2TT6C2dKNBVNTFJxaaMnkSTX5Kz8wP2mvsk43l%2FOWKX%2BGYUpq2LpIB1CZJj011HkT20cuGTdpV%2BmUha%2FZwzcxhiHncPCV6OAghQHyRvWfI0dOGZtVRIct%2BHWYsA%2FaqsFNkKlCtzqjqaxZIcuzfhm0XJhl3dtoQh5jygPUdR6z2rHnxKuNnQ%2BZtFtZavSFBJeSW50noOOo61jhjktDU9UWQxcHykFC1RxM7VrjFVTIkwVePBpRQ2fMAMEH%2BtC0OiqWyFXlytTioCCOhCth7zXKzx0MWWvYjYBMt6gArk%2B471y8kLdnXwZW0HwnWgBY1JMjkg%2BxNczPitaNUcjQzuGTGohEkgKE7xx0rl5cRrwZbIveMrSVqKQDIA22iax5MF9nUhk9EZuyVncNIHskcfNY5ePFPaHRkr6I9cuAfjTq357biss%2FGaVo1QcW9sCPiVK0r0J3I%2FKd%2FasLQXJJ9At9wpUU64AH%2BX8XttQtIYhgVkK%2FBsCBMcf3NDONEM5cAbQkIkHYhXHzQEHFvrjSonmSBBmrSKk6VhdhhKySNQgcA%2FhPz1rRjw5K2tGac2%2BiUYc2twFKEKcJ6lPPv8ANbcfiP2Z8k3V2WFg9qkaG4CVEAE8D42706XjRXvZhk%2Fb7LCwyz0KSVSpMAEAz8VvwYuKoU8jemWbhVppSlUT2nc11IQVmbLJpFhYVaaSFBQJI3HatMIroxZZaJ%2FhzCVlCjJI23NaVAyyytqibWLOwCUIE9%2F4U6K2Z%2BbJTaWwSRPlmRFPV%2BwG6DzLBSBEJTsNq3RxrsyZIt7Qbt2CClRSkjrvxTEJasKNoB%2FdCQeoMGoLlGhy3bqiQNvczNaAB0GNRAERHOreoVJ6M%2FKSCDJjg71BXJimhIMQkEe9Wostxk30N3rcSDOkzAPUntTLkVxf0YLa1CDr0g7bCqcmimn7GLrakqhKXBEdKNPVlHwYUoq2JE7n2quSIO22lBXqSVH53q3tFOS6HjYckwNKSdj2qoxoDiguykhJST%2B0HM05OlYp%2FofNpUNB2KeoNLlsrZM7iyTuAAPoa5ssaXZ2eUiO3NigFQKQE8A9xS2lWgov2wDdWadKlQQeoPFZ537HKSfRHrqyEEkc7880A6MvRFb%2ByVJUlHtxVSVjEmRK7tE6iVNgj24%2BDSL3RERx%2B00lYUEnrsD%2FAH3oJrZqgrQMXbKiUepXA6yP60PEqWOnY0WytKUggkav0pqQhxGxZ0gDcGD9asAyQ3p3HJ%2BZP5VCD5hMKP74AOx%2FjNNgqBmgxbIWIgfInamR7FNpIMstgBKk61DYQTM08zydsMsNFQgBYE9DT1jTBbS7CCGpSOVH8qJQFuX0KBmUwUwe0HYfWiUURT%2BzMtdQFAxHHvR8EA%2BzEMTqOlSgON%2BKGUESjINEFPpKTS1GiDhsCdWkzHTipQLjY7ShISSCrUOp6VAXj%2Bh22qCAoBO0g%2B9QNIIoTISDuR1nioA8YQbTAmT8ioKSoINlKkpEEjke1QZKSaCbLijAURJ24pnPQp36CbZJACSf5UKbCPFKEFLmqTzvxTkQA4naec2rylxt8AmqZaSNXfE%2FJIxG3fdW0hZIJJI2pKbTG8L1Hs44%2FaX8P8OatcQKrNCxpVOob8dOsbVlzZ2tFrxZPbOIHiOxh1rdXAjyHCVA7xpFc%2BVfRcVvjZpJ4hJYIcdZeJWJIGrgUhumaZYuOkaqY3eLZuXQF6lwZ3g%2FWtmFLuRkyZK2yJqeUtxaiQgnbbrW5eRB6iBLyE1VBvDHHGSkKR5jZHB4oZ50trsLEtWWHYM2zobUDocKhpUOI9hWPP5EpaRpUrLlyqu4tGw06l27sVHZxtIcLXyBWGUU9sdCUl0WlY2DK1t%2FebpNlbubNuaTonpI6GpGCW0aPkXszx7wwvX2kXb7bdzbuJJS62kEEdjG4oJTf%2BkksSfZVz3h1l999u3bxR7Dr0EpUXGDKT%2BW9B%2Fct9gPx4euyRYVkvOOXXEOJxTDcZwtYltxp7dJ6ApUAQeZqp5bVpDMUHHdkuTjjCmHmsSwJFviqU6fOt24LnbUAYPzSeMPrZuh5dKmiI49gGI37CL1BdtyU9RpWAOvqooqtmfNkUutMpa8usZwh1K2Lt%2B5cSohWtcwPcb1pSUv0c%2FJCS9hOy8Qm7ZKU3aWVXYGyVesgnsoGP51X9rb0Fj8lLT2Pf8A6o34UltBYbaHJSIMT9a2PxZLSQvJl5aSos%2FKXjbmfDHm04E63c7AFpSEFSlT01cfSqeCf0VB8Vo2CwzxQ8aMYXZXDeR8FttY%2FwDHiTZbbeH%2BZZUUgj4qoprTKlP7N7PB7H%2FFLMFnZWePeE%2BXLpp1JaZadxK4OG3MDnSp1Bn%2FAENiPeun4%2FJqhE4prTo2PxfwOxPEsFZthkTwLwN1xgKuW1Xlxa2bazIJUkrKusFRWTvsK0rxm%2F5JAYM84vjGTE%2FD3wc8H8gX1ucxN%2BCVxdqSNScAwZN04tA2IOvz7lYkfiUWxxApsYKHdIX5GHM5W0%2F9y3MQ8VvAbIa7ljC8t49dYkWvMRhtzgrrBdH%2Bc26UhSU%2F63FITHFMl%2FUMa1v%2FALBR8TK1dGhfil9qPGGsfv37HEsFy2%2BhOliywNpplTAj%2FwDuHyXlzB%2FChxPuBSnJv8rKywjH1s0czf8AbYRgd29ib2M3%2BZMaCdEffnR5J6Sskk%2FArXHKkqiY3ji3%2BS0c%2FvEfx%2Bzd4lYpe3%2BL5hxdFu6snyjeOuCO3qPas8sE5vkzUsqguOPSKuOd8bYZ8i3xa%2FWyPwtrcKkgeyeKVLwmzO5NvY0OdcwOrQu5v3XVpPpCgBHtWSf9PS6sYsjRLsO8RLpxxj7y24paVp8twEyP61hn4S99m3D5bqjpV9lvxyXiF5a5aVcssX4QdSXFR5yd5A7UuSUdNm%2FxJuT2zq%2F4Y31omzvsARo%2B7XAXcNwfUhYI1IB6kbkVcMjY%2FNXotNTl1dP4JelhryU2lyi5QpO6lpVpk%2B5kUXK%2BxEdq0fYHllOKtYg0%2B0bu3LDQQmZ1KmdKt%2BBTEk1YGRfZpF40jBVIzCtVqApeJKLWgRIRA2%2FOsUlXY6ONLpFYeGn3y%2FzDc3biFttu2CSoLVuDq2%2FQVWKVDnD2y0cvYHiGPZuctbZt2xfsmXL1sGfVpJOrb2NFytg0k02i9si4bmBWL5KzE3es%2FerppdsVFUqWFqgnf3q%2BSWjQpxb6OyPgPgNwcq4Exf2gvsYtk%2BR5xX6lkSJ%2FWtEItlZUls3%2ByFlHEbLFmXdTjQuLdIiAd0DvXRwYqOV5UlJaJN4n2GH4rh95aL823xEttXNrA3C217lJ6E1ulK1TMuL8ZbSIDlny7G8x1txKbe7RcIebKm9XmtrEnj%2FVqFKi0h%2BXGpO1ok2EvWGdWMXXg96ixeDoStHl6VJXEb%2FPFNeRPSEzxyhtvRfvhY1eJw9lSmnBidutbTqUjUmSJ06j7j9a0eNNmTycdK10bZ5XXrtkuOMNstPKDPBmSnr8GQa3p%2FZjnjl6IdmGydsFXNqw2FBKg4Fk%2FhHED4qJ1sYm6%2FZ%2BLv8A6s%2FhPi1%2F9qPNPizjNkbbJq22Ldq7vH0N%2FeHggJS1bIUQp0gAqIbB0jckV3f6S9NL2cz%2BoSc0r9H55PtJvP2Nkj7uwfJDkBRPIiu950PxUq6OTignLRRXhjmPBra7Q9jZhpuFpETJG9c%2BE09sZlxSS6Ok32b%2FAPqC2Xgvi1rgOeBmXxU8Hra4duzldNyU2S31AQ4W1HSVAjt3r0H9O83gvr9nmv6h%2FScWXJHJkx%2FIl6l%2FFlWZz%2B3n4qJ8TvEHxC8DMcxTwCw7HUrt3LDArgtabVR2aKgP1EbkxW7yP6rKa41yX7MeP%2BiylKTkuN9KOkl9GmKczYjdY4zdO3lzdXTrpdW8twqW4omVEkmSSSTJ3NcvLHk%2BUnZ2%2FF%2Fp%2BPFj%2BOFpf5P0I%2F8ATyzrdYPjeEPXDZuS7bPKII4Sloz%2BVJ8vI44eT0a%2FC8Ssqkj9EP2K8wvY3la4v16LVDuKLdQg8%2Fi2I9q%2Bf5cznkake8cIcFrZ2ysb%2B3Xl1CFLSpXlD1KHt2o1M57i0%2F0a2eIPhvkvOC3vKwti%2Buf33FNiB7UyOV3sTLDi5c3HZptnvwHabffSGPJswfSgJnUO1DPI%2FQzx47v0a94j4ZWFsVNpsR92T%2B6pvZJn3rJ8jfZuUEat%2BIOVWrS7H3JltpMxCU8ADk1byxitmrFBPohGGW91bn0JlQEaiePkUCmmtEmpomNvizqSlp1LaEiB%2BLYn4q0HBz9ju4vPMZSFIQUH%2FLtJpOdyXRsx409sjRaU88CAueR7b1hy7RojjSCFpa6SkjeDwUkAbx3rO8Sa2bMU4rQST6kQS5Mnk7%2B8yayzwJo2%2FImhqohBT5qSo%2FGxNc7L4i9obGaSAl22AsEJUhaZOmYM%2B5rmZvE49GjHkku2Ry7ZOkhSthMkn8XxWLJiN2KVuyJXjJ1pUSpMflB42rFKH6OhjkgBcNoGpIlAHKjv%2BYrn5cLfo1x6Ar6CVqIKNSUmRM%2FFZnjiv5IJOxqq3WpBIUptBAKSBt%2FzQ1B9ItsVbYkErBVzEkjV3pUofRV%2FQVtbLUUQA2SYAnaZ79Kdh8aT2%2BjPl%2FZJrKwKllCobXqA79ee1dLFBxVGV5eJMMMwknyypK07yPbncD%2B%2Ba1wg%2BjPLMyd4bhyQpIQ2ogkDcbfNPxx3swZfLfRYuE2Cl%2BWoN6RMmDxW6OJIyvI2WXhVmE6YSoqJgya0whRln5EuiwMNs0JSE6Ua5PXmtcehE8lk3sbYwgnpzKf403H2BJOuiZ2NukqQAkgRtvuK1md6JNbsRpJPB3AG%2FwCdFBWzLPK7oP27WpPBUPitvYqc2GkMD0DSPzp3BC5vQQaZAAITq2%2FKhcVYhyrseNskqOncHfbr2o%2BQS%2Bxz93mUwE9NupnvRAz6MvuwUpadzvvFU%2BhIkbcBRBQoDklJ5%2BadySIeeQklX7OAOsTFSUvRKMPJ0kEc%2FnSUQwcbBSdgocRRR7INW2ShUqQQOv8AtWr42DJWPUskggCdu42qcGL4MctskEE%2FoaC16LUGFENAgwZ%2Fl%2FvVqr2LbrY8DZMAKMRv70f4i5Sssy5tFQREEnciuZR3QBcWhP8ApETtG9UyAG4siraQTzvSuDJdAC4sjCjqSoxttsfahlB0aERm8sUqKhtPO4%2FlS%2BAXN%2FZErzD%2FAElQCoMGhnjtFW%2ByOXFgQCPSv0yNxB9vms%2FwtDY5WgNcWICQkAI7A%2Fzq1jL%2BeuwYuyBKwSkKmf7FXwQHzR%2BxBdgqVfhBHbpTviRPlR4mx0pAXOxgex6VXxP0BLOloVRZk6E%2BmTO4FMjFgZJv0FWrbSQkkEdoo2nQkKN2ywNSoHXmrjBkDFu0kKCYGnkgqppncrH7TUAaQEiJJnk0STZKHQZhMSN%2BOs0cYtMSm2ehkgA7IPB7VJSoJxl9n3lKIAMR3oebB%2BM%2BDcwCrfnbYCiUwla1YolG3STtz0oZSsNX7FUoMgmVE7j4mqVeyx%2BhP4CUwo9COaJRT6Yubd6HrQUG4CtJ5ntQMHm%2FQ8QkqgSI6TzUIoMetpTAVI2PWoEofYRaE%2BkcTxFGoASVMINkCYICv1olCihV0EogRJ%2FOjRCM4g86yCBJEcA1CUUXnnHSxbPKOoTz%2FfFDItSfRyD%2B1RibOIWN%2BlTXlnSr1T7HeQaw5ZIvhk%2Bz81vj9id7Z4heOJcKEJUpMBX1%2FpWHLikuxWOdGgeYs1XBcdKl%2BqSAOdquGO9Lf%2FA9%2BV6opvEsUL7zitQdUrkk81u%2FtFVPRmnK9gL70pBRsYAmRvS14W9SARIsNxR1AQkhLvcKpeXEorbsLHkSZYGFYm2tDYSE6ojnj3q4%2BOmt6N8JrsnuC4rilhdNvWNw9bnZRKVAH5jrWTJi4e7FvPK%2FxNlcseJacUYZwbNrVhe2ZT6VqagEnuRwfek8U9j4%2BRP%2FAFIszD8yWuCJKLZBesAmAwtWtpwTxO%2B3vQfF9GyHkp%2FydDq9xrw%2Fx1Ck3OC%2F4PiigNJA8xpRI32KgaH4n9GhST2iMrwF1Qdaw6xt8QYBIC7dUlXy2o6h9KFwXTAlP6RBMw5Px9TIctr9%2FCbkjZpTZAV7TzNHHFFdC3Kb6VFVYnkLMeJqS3eYgtD5Eh0qOgD%2FAFE8UyIp4JN7Bjnh%2B7YtgP5gscSWBOoXCG0gfBOo%2FlTaXRnlGnUgBfYXh9my4DcIuxA3tmCuD9fVQcnZJRS2Q1%2BzKHPPTctMW52CVBSFEn2NaMeTdNszzypfskWA43Y4a%2Byu6Q%2B8%2Bn8DzBQFt%2B4MzW3l9vQKcntdFuYB4kZjTcBGCX2OqtY1K%2F8AgecVf%2BzhUoj8xWfJHH6ZpjFPs2u8LPFDxMduvviMSuLVwoLKW7TDWl3LieCEgGECOVKIilKdfxdgqMb72bwZDzJhOE4Na3d3cXd%2Bq%2FWpCLbDGbZpLi5hTlxelCgY40tgmRyOa1w8qKX5uw%2BOXtMN5z%2B0Rljw8ZYw3B7u7s8VcZ0mVKuGUKkagj1a3l9IbASNpcHFNj5bf8EJzYJN3JnNDxj%2B1NimJ4ld2uEW6bRxRhKnQgrb3Pq0pltKupVuvpNaoSlLQMcnDTRoJm%2FPuZsTfdaYxS6bWsEuupWQVknffrTl4zfehGXNZSV5bqdJSXi67EyTWrH40fWzn5fKS%2FiZWmE4g%2BoIaJ0kTv0rXHxJMxPzZp2SlrK900ltT7qQOSQdxt2NMj4M26J%2F%2BSfQcvsi5gawZzFGcOvX8ICgldybdRaSrsXAIB9ia0P%2Bj5nFvi6%2FwOw%2F1HG3xk9lei5VZPC3dCkgbiR0riZ%2FCrRvjNPplt%2BGWYb7B8esL6yuHm30upMgxIneuJ5ngJLZs8fyeD0d2fs%2F%2BKZBsWnnfvD1x5SmQogaVjeuRCPHSOzHNGXZ0HwfEncTxt3D3Jt0OsXLjKNpWshKtI%2FL61pgnIOaUI6JdhqXdbWFWak26lFLrykABSNMkjnbkU6MWtGRZk3s0ozXki%2Bxdd2Lhp5a1XVwUN6ZKElXJ%2FSsT2dRKMldlW2uXzY5hxrB32fuVw1btott484%2B2%2B38qvGqYtY7e2WTYYqljE8RvUuhGKWNl9z0gQS0fSo9J4NXLsb%2FAGxara8Yy9d5Qat%2FL029uyhmEaQla1D1EHeY2oMnC%2F2bvGwKStHTnwm8Q713E2rXD0XLjdnjNoHUpWBqa0nXEdCSKb4uWXKkrMPnYL02dqsIxG2%2B72F15ei4S3qCSOhHT%2BFeggvZ52T4umOGbVrFsObYu2UXN406ssLI9R31aZ6%2FFMSbFznFlaLtjZZpQw3qLLrC0KTo5bJ23PUE0KtMOm4WRDB8Mcy%2Fmm2xO3UtWH4jcXVk8Ep%2FZpdRCkH52561KNSeqN2%2FCRNuq%2Bx%2ByufLW2%2FbNvpI%2FwDxO595EVuwLZzsrbX6NjcNbcQ1c4W96GlpDjC0cpPXf5%2FjWszSlaINm1K7pxhDLot9TLjeqNlqir9UX%2FGLkflE%2FwCr3lHDcOx208Sc4Xq3sNw9w4bguH%2BYSq6fWBKlEH07gqI%2FypArf%2FS55FJQguzF%2FUF%2BHI%2FL%2FwDaEwv%2FALgwB11IbduUnzdLfMEc%2FwAeK9Z5Kbx1Ls87gcuVvo52pdNs55Q1oVGk%2FwDtXMSOk7aHVreKQlQKlEE7iYmnYclOjFlxc1RIrNxy%2BeZZt9ZcO0d63ryVdGJwnD%2BKL8yJkW3Xd2d1iKipCTKpMaR81fzr7NWO3%2FI7ffZSxzKWCZYzBfW18wvMz3l4JhFmRJXrB813vpSIE%2B9c7%2Bq%2Bavi4yPQ%2F0rxoylbP0r%2FY%2FwDDlbGG5Xy%2Bm5CXWEIdd0q3WruQJrx0WpfmvZ2M87VM7KrtLTCsGQ3dlxy7KANIMk%2FSrUaMNrplSMYr9yunfvrabW3CipKAZUfmrf6CcL0VhnHO2C4neOW1s625dcBABJHzSZZKewsat0ipsxYdga8OfS662q9WmQgAGPntSHlZqirdHPvxSw%2B3ZurxpnywoGAE8x%2FYpUm3CzbgxSRrtdIVaWjhZChqVBBOxIp2J6HPK7pkasjqeIXuZJOx2poNr6D%2Bp9WlpIDp5BA%2FCKpqy4Qb6CNrZ%2BhAUkKUY3XsSe3tWWWFttvo0wT9voOM2pWzqUFKBMDjjtzzWNwdlRbsyNpKRK4BBIEzvNBLHfs0wm0Mbu10pUFpSDvx17Vmn419s0w8m9NEefYiQ4CF9v8ALWLLia1I245bAd2iCFatSInZW89Nq5ObxmujTHI10Rq7tTqlC0qciSOw7T2rnZcRph5m6ZG72xUkqmEkiQAZM9v0NYpYzo4vJtaAqrRQAUQhKtoB%2Fe9hWaWGL7NTzJr9nzbHqIQhSOZkkb9JmlLxIXoXJNbH6LFLiAZIUdoiYp0MSiqF%2FwB0o6DtjhocC1BO%2BiIT%2B6abBekDPykyW2GGIStKAhR2BAP8%2FanQw2ZMmS%2Byb4dhmtSEJCVq4iOK2RwiJTJxYYaEqT6RoO5MRA7bU%2BOKjPKUe6JvheHkpRpBgcmIMe1aI4mInJPosDDbQlLczzII69q2Qh7M%2BR%2FZPLC3PJTBJk06D9GaU16JrZW0mVH57mtEZIQ8jJRaMEbJmePmnRjydITNuiS2bIChoHG3xWpYVFmWaXYeYaTI2ASOe9MQsNMMlQ%2FAkbbdabGViphFpkiAQI4IoqAlTWx6hpXCdB3mJgUSr2JlGuxUWzhKZWPbeaPmq0CZBiCfLPyD%2FKrhK%2ByCgbXuEwN%2BAdvio4pkEBbKUYJ0777dKMg2LQBJClGSOgopxpWiGKmSZUVkk87b0agijBNtq2Abmem1GWLpblSToSUgHmgeRJ0SwgwwQNRCE7zv0%2BtAoX0Lmgkhg6TuTP8AfeiUDPNDpu39I4mf7ij4oWW9c2UgpCd%2Bw%2FjXLbaPQAG5s0n8TZJABNT1Zak6pAK5s4JUUGO%2FNV2ArAdxaAxDYV1pUo2HHsj13ZJUD6Ig896H42PI4%2FYeYkjywN5gwaHiyEcusOACiEEq3g%2FWiUG1ZABc2B1CSACTEHj60ucG1Qt43YOcsRJAQkk7EgGrji%2FyBJDc2KZVKUSeAf6U%2BSSKEzhoBUpJhM7dI%2FOg%2BRfQ2Mo11sUaw9IEJbSpRG5n3o4ysDJNDluzWFkKSmTweIq%2F8inNBNi1UrTqBE%2FG9Wk3r0A5NhJq0On8MJ4mnARVDxFpsRACRHXirLoV%2B7JUJ0CCY7T8VC3%2BzxLEq1JB0zyagNo9LYidOpMn6b1CuaEyykKJCIjc8fxpbgypSXdGXlkExAM6e1C4MH5GLotzwEuKO0x1NVTL%2BQfNsTMpPbn3qgJSseIYghBTI60Tmymh2lpQP%2BVQ5TA2FXCNrZabXQ7QyVD1AKB7ED9KLggZz1seoQZMQSOYPJokgOY%2FbRJEgARFWHF2L6SAARAP1qFgfErNLgWqIMRCRzUIa1eJdjctW9x%2BwU42EkmBJpU17DhBvo46faav8MatbsOBDaoUCDsUqjt1Fc%2FO67NcPMWPTR%2BbD7SD1ivF7xtvylallQIJhQ26fSsc5swZpW6iqOdWYmh96eVoAAJgA7CrhJpiZIr11I1CUaTHXrT35OTp9FDZpCS4A4htaJ3rRHPqkglKkGWbZhzSptBSeRBEfxqoyhJOUuwoRT7JTbNrs0BxMKUPeP7NY5%2Fl0PxNdExwvHmrchdwwCnnUkQqlSi32aIyos%2FDMTtsStgbcBtWyUrSICe0iltDEyT268cwNRcdS4q2UIKSqUuc8dOtXGVEni1ZJ7PN%2BGKS2nErVsSACob6B8d6ty1QzBSZa%2BEY9lttjVa4la3yCBKVpKVoHbY71lcWbeQtiWJZcxFKWGGg88qTCmF6EfUGalMtIqDMVjfWLrjK3mGGY1JbgyU9SJJpkIsTmnx0UZfYQm7ulOIYfQ%2FMa4Jg%2B6oimRdMxPemLDELXLrak4qwzfkiUstGF%2FJWdwapbI2orZA8dv8ADbxZfw9hdg1BJDzhWof%2FAKx5rVimopp9mHJKL6QBtcWt8OLbobNw%2BkEjXuknptRYp8VsXDK0%2BiQ4Lnm8vLxtOJ3Lz1qVelguKSlZ90pI2%2FKgnXpGzHmvs2%2FyNm7L9%2Bi2wzHLlLOW2UEvsWw8hgoHOpSfUsntQKWx2k7ZL81ePeYcYQuzyTht1hGWUMizTchABDaRAQ0IhtAHYSe9b8Hjrt7GTyyr8NGuGZvFq9whNwDbONXdwgoU8kK1vJHAKzuU%2FwCniut4%2BP1RzsrlatlQ2uK3OYrp111AQgjfeSd66mPxL%2Bkcny87i%2BMV2AczluwQWWkIDkxtVPBK6o50FOUt2Qi0bbU4CogkCDI4rbjxceypY5R7RPsJtysrbWyEpmQJA1VquEXdiJNN2bH%2BBPg8x4teJmUcr41iKMv5du8RtbK%2BxFbZWixbddQ2XlJ6pQF6oHMdOa6njThJq1aMvmylDFKWJXJf9v8Ac%2FV%2F%2FwBS%2By8EvsB%2FZGyX9ln7G%2BTU%2BMmTsZSvBc2Xj%2BCjFLHE7vy9a7pN2EqCrvVKoZJDQAEiIr0T5zxuME6XqziYsmLDOMJSvLLbk%2Bl%2Bkz8UPiJlVWFYg%2Bpdm5amdWhSSlSR02%2FlXz3zfHlCTlI9n%2FTpt97IZlzFFW922hSyHBuI2rzvkQaTO3ijHls6S%2FZ9zNf3d3h9izfIVcFTa0Cdh6h1rzuWLTO5DHGrO6GVrhsO4DjNzLOJ2lotpYCpA9I3HTerxqwkzYjI9i1a4DhL94287iF08S8TCnBvxPTat%2BHFGtia5PRCcv5aZK7jEMU1lT9%2FdlxRgBLAJP0EAD6UiOPRtm3yo5r5pOJ3OeLi4aQ4lh29WhohZICNUgD6Vgm2paHvx3drRc9zlWwTg1jiSrzTev8AouCgg6BuYJ%2BKZ%2B2XFNOmPsMzVid2vFb28cWtyxsw5blySXEo2SAPoKx5Ytb%2BjdiaX4%2FZ0O%2Bxm7iuZ8g4RmjErZDOJ4jiDrygpeym0u6Uz22SqtniXFq%2FZi%2FqWZNqP0d6cBxJt826Etp0NMJSpI4G%2FNekT0eazL8m%2Fss3Mli5YWNlidm07bIbfbUpQPpAVsZ%2FMVqpisWO3SIVmRxOE4hhziLVm7V5qk%2BYDAAWnff5CaVkTsdCLdpdAO6s7i8aetrS0VbIL33psKUNLbw2O3vNVKVrRcVxNicguXOHXlpeISEvOWiAlE6gSDuJ4nn86PHNr0LyPVSRtNZPoxPB7O6QQ1cslQSOPoTW2ORUYJxp6KCzPi72GnErR54NArW8wpQ2aEQqPaakstbNCprZ%2BP3%2FAK5%2BN43hviNkzBb2%2FwBOSsMszdqtw6Jub51Wzj%2FRA0CEoTK17mAkTXc%2Foapt3TMH9SkpJV6OCmHYhaZsacZ8xDiliCFJgafjpXq8OSLdNnCnS%2FialeKXhBi%2BBYw5es2rqcMeXqC9MJSeong1zPKw0x2Pya7KztMvJZUU3IKgIkfXes0sqSKk0TTDXrDCVIcQ2hK0zuVbKpMfLb6iL4pl8%2BFGEZj8ScTuLXBrd0YRath29uwT5duiYknifbrTZ%2BRx%2FkasHj83VHd37Eng%2FwD%2FAJvh%2BLW7Kb1qwKXLW3uVAaxO53iSf5V4%2FwA%2FzZzzcX0eu8bDjx4z9Wn2WsuPpYt8TdsLRi8iVaT6UAxABHMUzDk5ddGGeSLdm4GaMdbtkONsItnHkf8AkWVnb6CtNqhMuL3RqvnHPiLd%2B7XbhJIR61Rwax5cr9D8Mffo10d8SLdq8CH2rq9vVGdDadMe5%2BK5zm72jowxt%2FxRUGbvE7FUXt5dLdZwyzQmNIIXH9aROdu0zRj8ZvbNUMdzRcZiuLq4euCzayVlSzCnepkDpRw8hrQ5Jp2yDYjjaXw2zZMFTYE8wAI%2FSteKW9dickrYNtkutOpWVBbx9RA6JnkGt0F7YsnOF2Dj60uKSvUSAYMatqkp2XGTRKl4elIALaiDufjmlyVjVOx2xbelIbbKU8wKS1emE3XY%2FTbkApKCtwiAqdpnes7wb0U1YHvWQStKklMDeDxvSMmJj8ZD8QahSlBCSiY3B%2Fs1iyRs24s8UqI7cNIUsjTKuQYjYVglFKWzbDLrQFdYGpzVBnYb7FXv3rB5WNdpDVcgBd2pWpC0gmNyP8u3FczJCNW0bMcW19DP7kSgAtp0AwJ5npWWSTHRzJPY6bw4agXGyCNhI5HP6UuOA0LMpaQRbslhQSpOkyAoc6h8UbhXaEyd7ZIrXDUJSVKbSjcBG3JjvRRigaXslljhqtUrSsExA56VrxxX2FKUWibWFopBQVIOsHSSRxTotr0Y8sqRMrSxJU2oIUEgdO9PhfZznJ0TTD7IaQYGof6prVjXsV8leiZ4fZSrVAmfypqFynZM7K00AQ2pI5iaeLbol1jaqgagdpI%2BaZFq9CJP2Se0blSep6%2B9aIWZySWrOkftUgKkc8mtMb9lS6JBZ2x1FaUEfJozNPoOMW%2BlKFAGeN6OC9inK9hJFtKQRBSQfamlNWqHrdqpO4SUn4qCJRocJtjMKSI%2BTsahR6poJ4QZ7k0cYu7IJqQlcDTCuDtTYpIoxWxydGr3jmmKKaLQ2VZpWSQDPMRUeNeinKjEWgTPoIERE0txoU5MzQwBwhIPU8GihBC22vQ5TbIUgJKAeYM0zggotjxtgyYQACe%2B1W272XKY%2BaYQBMSBsSRRU%2BxbSY6RbyDEEnkmqBaouq5tZ3QB77bGuW4M6tAO5tNcqAj6USjqh0FoBP2o34iPzqmq6CAdzYyCBExA6UviyXQFuLNCgsLTv8UXBh%2FJ%2BgG%2FhwOsTBBoGAyP3GHqkiDzuaXOWwZSSAlxhupSglCpiJmqinZSmgS7hu%2BpYnjgxNHT%2By9MbmyASnYntA60SCMf8NKgCG4japZTkj3%2FAAwH1ABJPY8%2FSoDJoWRYSZEgg8kc0aigWkPGrIpgkyY29qNJdoFD5NmQdo1EzHah2IcmORaaiJMK%2Fn71ai%2FsptvbM12Y9kgcR39qtJlV6EVWsRMpPuKlEowVbKPB42mKG2iCItgVAbQBMcR9Kvk%2FoifoUTbD1SFaon4qrZONexdu3JUnTO5mR0phB4i1gwNld4%2BKhB%2Bm3Gw2JBEk7VC22%2BxdLBBCvwz6fioUOG7bSAoqKTPeoU1Y9ZYUOgnr3qlZnHjbGk6tIJjqP1FFwYSsW8lBBKiFbztV%2FGwlMb3FmpaFAR8HpVNV2Epr2VpmzLT97ZvhKWzKTUdBwy09HIj7XXgjeYthGJv2VkldwUL%2FAHSNRjaP1rLm8fmZ8%2BSa21Z%2BTH7U2QszZdx2%2FTf2N5bIQ4QCpJ3ExzWVeEmuSYvB5PqWmc4cbdU266lSHNUmZnmKtwpXIdL7IU40twSCSgcj%2BJ%2BKevIhWgRpKQ6EmNu1Nhl%2FFsgRtwEqJSpUxEatia5%2BXyX%2FABUaIF23nAkStLnUhR%2FTmk4cqiFGbXQ%2FtkPKc%2F8ANqa7byn4p7yweqG%2FLuydZbxJWE3KXFrbuBGkJdJAKttzvWPMldIdHKmy0LTMLhQCLlwGPwg%2BmkGluwgxmPDEJIxKwXcKjYo9NRL6JT%2Bxu1iOBrUVMEW6lcAqJKTPzvVsJRXdj5GPXdutDyMddbIOzSkQFduOaotza9jp3xTzSxbO26bq2uGlEgg2qSlW0DpM0Sb6ZneZXSZX%2BNZ5z1j4ZtF4ghqzRKW29m0t78kACT80aignORB8SYt7fQby%2FGIXxOpbbYKlKPWVcCih9NCm17Io5ct3DyluWTTDCTpBVPp%2F3rZHCvsCXBeyLYviDDLqlWqVAERG3PcirXjNv8ujPq9Mj1ni1z96UtBUd99onetGTBFqg6Z0P%2BzP4bq8SFsIxK6ThbSDrbLxSpC09f2cgnaetZcvjRjtMXU5OkdCl%2FZzsFYKpVriuDYnbBJCUMsKQEDiVISpcfJ3FaPFyP8AiaceKUXUkc3vtLeF%2BJZeasrn7r5bTLikqU3K0gd%2FYbfrXofFx2J861DlDs11y6RbONSQQYmOK6sYs8rm8ibptgzNWHvPvvvN%2BlPO0fSglF%2BwsPk%2F%2FbIGww%2FbuyXBoG3qMzUhGh052FWcWXb3SFqUlSAP3ep70dGfgbH2Hi9geG5TXhb9ri1u%2B6ptfmWq9HmLT0UoEEJ2G1dLB5CW%2For43LSZtpkz%2FrAfao8JPB3MPgf4NYhl%2FJOAXzsNYo%2BwrEMTwhgo0uMWTz5Ui2Q4ZUotpBJJ3roZf6rzVdAQ8BdS6%2F2%2F%2Bo57ZqxrEMzsKxXGb5%2FEcRfl11x0ypxZMkq95k1wvNqezpeG3B8I9FFurLF6ClZEnmK4XkQijrJNM2U8Es%2BP4LmC3QH1NFRSAuZKVAzt7bV57z8a4cjt%2BDkUnwZ3cwTxNuH8DwzNaFebhLyG7ZxGoSHAmTIHU1y4zTVo73%2F46P2dSPDe%2BscWssNxMOt6m7Vt0ogkNKWgCB8H610MRxs8FGVI8zqXbbIyRl9TDeKuBdilS4JBJ9Rgbzsaqb1ofjnLlbOcWe8mO5ezXbOJLrn7HUtH7wXxqj3rmSg7s6i8mTXQVxPDMWt8vWOCWocXcuPNJQlI1KWsxqSfoaYk3ozwUm2yYuZduLDH8Iw%2B0s0vXT7rdrcIWJKWBClg9%2B1FONBRi3%2BX0b%2B%2BAuK2DGE2WA2gVh2IoxIIatkSmEIXJ9I6RMnvTIOMnTZk8jDL%2BdHW%2FwAFc4sY3mDNGApaWtNl5YcdcHoExsK6mBu6Zl8jxPx5vs6GXtphOJYMjCndLbTyEp1dUmNlfoK7Sdxo89FyjK%2FaKmxbDWnXbK0lRcZK0EBP%2FlI3EnrtWdtI2Y9%2FkyPpsXH1vNWS027kB95CtlJj%2BRAFWmPotTC8Ss7XDsFf0eXbuPFCFfh0Hk7e21C8liUq9lt5cxsWj15aOXCnrQklB0nSlStyB7c02LVdgSXLpFZeNrjacPRilo6hS1FSQhB9RRHCR3JA%2FWmTV%2FxAWN3xPzj%2FAPU%2F%2ByBmr7SuT0518Oc%2BZazPmS1cWi9yzetW7N66QBCbFazrUoAfgH4q6%2F8ATvJxpcZOpGHzvCyJ36PyW4jl3O%2FhbjuJ4M%2FlXGcIxO1dIebvmFIuWFD%2FAPRn8In5%2Ba6%2F9zGL26OHkwt%2Bi0cvZ%2FxS%2Bw0u4pbX9wF%2F%2FbdZK21eykqEEbda1ryItU2Z1hcXshDngbiPjBjj9tkjB8PwXGnAXZLibazPcq1kJb%2FOKDLixvTY2VrpWTbLv2Bb6yuG7jxD8T8v3tqjSpdjgKzdOrPVAdA8sbcnVt71z8mLDjVxds1YPDnPctI3t8Kfs%2B5YbzBh%2BF5es7jK2UluJbZsnbhS1PrAG7q4GpZO%2FECdqweZ5jao7vheJFTq6R30%2ByB9l3MGAXNtj2KWlkxh%2FwD9tDzZWFonvG9cKOCKnd7Ot5OeCXCOztpll04Nl9CMOtmbZhKdKlBsICRHNbkktHJlptNmu%2BdM9KZvH2rXFLjEbgKlTSDoQj2UobfnScs0ui4bdLZp74p538TUqeusGs8AwzA7eFuvXRCyuOYTIrk582rNeOGXkuNJf8mlOYvtMqcfceXjL72I6fLL6gGmG4%2FyoRufmuLk8iXLR38WJqO9s1lxrxtbusS85%2FMNxi%2BIqVAt2yfLbJ7Jq4Zy4wCOGZzxPGHmm%2FNecvFGAn%2FInpPTetuC2wmkkXrg%2BFviyDiglT6kgmJ57T25ru48VKzjZ2nL9BW3w4MvoLqFADgpGx3rXGEqFWmWHaONpQzpRsOZ2PFIqhixhxjVdOSNW52B4%2BlA5otproN29oWU6tIIJiY6e3ah5JdDFj5K2xV1oJQXJSiR7mB1iqVvTC5NEKxRwJWolSAmeRz8xS54l7NOKaIncnzSpfp1DYc8Vly4q7HqUfsj9w0VJc1fijc8xWLJBtaNmPKkqAygEEqDhV7Hp71hnivUjVGS7Q2VbhSUqc1EAneNye%2FxXPy%2BJFmhZtULN2aCr0a4I4I3Mdj9K5%2BXx3EW42%2Bwg3h5WrT6myesxA%2BKSsb9jMWSUewpb2iUeXpSFTtxJFE4Id89bkSOysyFEJCpSNMcSB2NWsdkeaMkSuxw4Et6CpfqlW3NPhGhU8qRLrOx1aVEQOO2%2Fb9KfHGI%2BRsl%2BH4cSpMJBSeCO%2FWtEI0VTZNrGxBUkbaTIMdaalYjJFU2SuzsgCCnZR9qdHEzMvZLbWxI0zMEzvyffanRx%2FYmTJPa2p21AHoog02GNGeciQ2lqVFOpPB9961Y4KhMoW7JDbMAkFWopHMUyqK%2BMktozo0nYJO%2FPIqCMmN2Hre3PUwnnijinYoJNs6tgRI6UwBzp0OksEH1BPvO01aQEpWKhpIg6SrmDHNF8bYJ75CCZKIPWOKvjL7Izw2qB6gqe1NirLlV6ETbAAAEEnk9qbTvRRgLdSJUEEg1En7BlG0ZeUCQmY7zQpW9iZRaZkLcAEAAz1O1MSrogslhM8kd4qwXY7RbDdRG%2FTbaaKLoXOLY7RblII%2FEP505NNCHCQulkgpkhQ42FWBL9l63FqreEye4GwrjM9FHsEv2pKZCNh1IqDJWA7i0IC9QUB1k81KFOTBD9ioH0pnfiqYcZ62BHrQfvJgk7kDpV79B39Al%2BwUQApIIPSaGkS37AlxhsagU%2BntFDKN%2BgZK9gx3DVatXlwZ6CaHgxQKdw0knSExwf%2BKF2goyoZOYdEAhOkb1AvkMBYSZCTHSoA3bPFYeEiC2NjyRVpWVQomwk7N7CeKtQYDmOEWBHKQI3g0yKpFfIO0WaSQPLTPv1okLFUWZSTpRM7bCalEPlWhBIKCgzuKumQRetkgGG9hUpkEjZaQYQIP5iqIIG1IIPPuahDwWrh2OkRvB6VAYyscJtthO4O%2FzUCHgYCSJbjf%2BNWo2QctsqJT%2BzG%2FJ6R70z40U5JDxFqQQTI77ARVOP6A5iqLYAKJSQNietXwROY%2FRbLiQnSBxtNTilsWOm7JU%2BqZPG1B8yIOk2rZIlIKu8RV8ZPaIZm1Sdy2rpU%2BKXZANiFmnylApGk96FLdFpmvPiXlexxOwuw9bMvJUCdhufaqSt0Hj8l3T2cNPtc%2FZZyxmq0xZ44YyEFK1iGxIPb23rJnbhpDf7WGWVdH5iPtI%2FZgeyXiN65h5D9sFkdARyYI%2FpQY89vaDz%2BFLE%2BHo59YlhT%2BHPOMPNFCkmD7fWs3kR3dNGRpoAm2YJJ0Ekx8%2FlR4Vmf8AEOONvoVTatggI0hXc80%2F8v8A%2FQv4J%2FQq4w8AlQ8wxsd%2BKVlxxl0T4J%2FQVw83TcHT5jZ4HQUjJhr%2BJSiSE3KkpCSwgOjYkVnSadhLHboM2F66wkIVuiNk0eSSa0jQ4puwpcYghbf7JC0OGJJMg0pQpjXOwQjEEoeIdYS6AdhPJo2rACKMRceB1GEn91JEjvQyxP0FOVqhrdWjwBeYxQoSd9wdc9iP51pxYE9SMvx0rALt05aaUv3Ote8lR9Sv6U5%2BJH0OjdWwPd4raWxVrlS%2BXAFfoCetKXh7FykqtkHxTMK3lueW2i2QfUEoUe%2Fc1rjhSdoQo3sBh1T5JWlaR32NNoOMNk3yVgSMYxa3YtrK5xV5RGhlthSitU8AJnepZSls7q%2FZDyxjVg3YtW3hn%2Fht7CUrdecQ2hKf8x1hUwOREmsmaTcuKRsxtxjbO0%2BSfCXLmKhLlxlPLmLrbE3F49YJSpGxMhSUtnbokVswYVFJFSk5bRzV%2B2r4KXN%2FZZgs4t7lxbJcZDS0GUjYKVo3A4gK5rueJl3QnNB8Gmfn7dw97AMUubO%2BYcZdbdKD3kGurFpbPH%2BRh4toKY7jNreWQYLGl1PKtIk%2Bxin2krZnxwcSmcdXLgLTflIKRtG6fpWY2YotghkOlRcUSE9Ad5qGqeNpaQ6VdlbZSSsaVbGYk%2FFUzMhFvznnGhqUoHeI4%2BtQZDckia3ja2LEMuOALA%2FDqHMdaTlyNdHVxQivoq%2B5Qty6WZOw2rl5babNCDeXsVewnFrG7TKQlxJUO4ncVycsHJOJqw5HHImjtx4OZracydbYGhbj2FPOM3BbUnUdYE6h9K8%2BoSUmj0b8mTpo7I%2BDedrdzDE4VY4cVrccYQ7PLbaOVHsTNdHDNVTESxt7Zar7NnZtNXF22p1plt65ShSdSnCZI299qk4aoGEjUTMmAv5nzXc5qvLe5t0oRrCFkzpkGSJ57bdKxtWzfhVxoneWsITY4baXt8oP4g487coGifSFemD02FNSZaxflVk68Oco3mac8NZ8xy2TZ2GHLdWwhat3VCNKjHSTVStuzTPLGEHjW7Nq8r4HiVhjl%2Fd2uD4fb5juFBVqrSCq1aJ1EkzsT%2BtNhGXaQlRhxqRvX4F27uV7G7u8eWHcZxO%2BVcPuJVMgH%2BQEfStmGLT2c7ypuTXD0dCsn57ssct7NCk8tLSrXsogGNSfjauxgleji%2BThafInqzh98ym2cLTlwDrC0gAzGx%2FlWjJBVQjHd2yrsWYdwm%2B%2FxxNmt3Wn7moE7OJVtBI4I5rBK4s6EUmgdajEbuxwSxsnE6bd5a%2FWqSpuCCI%2BtBFNippp0Sy%2BzvY5ewHDUMOrLt415aQnltwEDc89aapJLZaTbqisfELxMwhvDWLe4UpYKFoU4G1LKUIPqVCZO5296qOWPJKQawSlpH5p%2FtUfaKsM4faBw5Ph74aXWO5ryjiDN2xiVmspacWoiW0oXp8vaUlemTxBrj%2Bf5i%2BVfGujr%2BL%2FAE6Lg%2FllR1xyp9iLD%2FtoZOazX4%2BeHuXrW9dZDtvZ4asW%2BL4ZKQAoXR2d23IKUg9q9F4WWbSm316OD50oQvHjf%2B%2F%2FANRzt8ev%2BjpmnwrbxS%2FyDiLmZsnLUBbNXDYViDcndTpASlKRxCZUevetHlSb3BGPDNaWR2aY4b9jjxctcxJw13L%2BF4VhLDcPqGkuGBOoMn1KiJrH%2FdzqmboeNjk7XRtDkT7FN85ggZxDxAwhbziypIcbNq%2B23PGlUg%2FIG1DPyG12FPx4RelZvb4KfZY8I8pstP4hhjNziwKVOO3D33lBUOFCeD8VUcj9sbBtKkjfzJGH5QwW0BslYs1bokwEkNCJ4SCYH0o1KnbMM4bsqjxG8cbjBBdW%2BALTizgnS09cKabPzME%2FFDkzv0OxxtHO3M%2Fip425kvL%2FABa9zBl7Llkh0lizbu4adSOqkjcj61x82XJJWb8OJRaZo74tfah8R7bEk4LjmcLPE8HW4hKrXDrXUQRyANXxzNc95pVTZ2YYsdOTNe8ax1nFrxd0LLFGFPhK0%2FeTBA90p2HwKFq0aYqLVIc2WAXWGu%2F4viJt7RgjUgEadQPEAmaJa2MjFdF9%2BGCXcQ865s20qZSdSlncrNdHxLk9nN81KMbZv1kXKl%2Ff2TdxcsoDRiExt3k%2FnXp4SjFUzzbXLYbxbAdNybdlhS3I2EbRWiLvoXJU6Blth16twIcbcLRBKiDEe36UrLBVYyGStE9w%2FDywhHoWVFRII2%2FOsDizVjfIkamB5epQCQCDv1HarjH7LIjjF8EEMNITHsnrQ5H6QSg6sr%2FEXJSAVKEq2Ebq26%2FWlLl7CgmgC9I1La2TO2%2Feo2mrZp1yB7jWlOkhY2kjtWWbXo1LsFOIUFrSFAgyeJEe9ZnjRrxOzFKEFKdKUwRIIHI4%2FKsGSKTHDllgoUQgJ0SeOneltB4%2Bw7aWwV%2BzB0o7%2B%2F8ASsuTxkC5Oww1hjYUCFKbJJOkjcH57Vl%2Ft9i%2Fk9kms7HStsrlaTwOTTl46RatqyX2lhpIHljVPChA%2FwCajxJBf5JZZ2RA9IGoHVPEUx4wJSSJpZWZkEJA52J4ooxfQn5iW2FkQlClAqJ3mtUYCMmR9kvs7MEBQSEkGZB6e9OZmnNkptbXUUhQChtPaiUWxMpWSG2skkhUae0U%2BKBsOMWpISUA6REx0rRD8Q01Qet7YAAgTt33FW3YiUnbQetrcEnSDBPBG1FGS%2BhE5U6D9uyqEAoUT26U0WEmmJiQkiYBHSiVeyml2x590SpOwSkHmIonNehUqvR6bPSkAiAOx5o0CfJtkyZZAEyZqw4zro%2BNqADpQpKZEx0qopizD7o4AZ9MmBO5pjlIs8%2B6rmdadI%2FMGpcgHMyNmUxASf771a5AN2zFFpEEwoc8UwEXSwEmdAA5HSoCpocoY9KSQlSehooxsGUvoXDIGwSAJpsVSMs8jukKpaJOxAPaasDvs2CdY2ICVLV%2FGuOehA79tqMKUUdh%2FtUaLtgl62%2FFCONqhcY2CnrUSopVsPqaotxSBjtkFmYSrtxRJtdEU2ugY9ZSSOB7Gqeyc2wY%2FYpUkg7E7ExSqdg8r6BjlgANMK0z0ppVg13D0QoKRPsKqiuaGRw5IIUUnT2iq4osQVh42SDsPbihcCCRsjO59PFXCNdkaQqizSOoB52FGBKKpmYtQIIJUmY%2FDVpWKFhacaUKPwOtWopltKjL7qtRkoQT0o04rTYp91Z4qzI1auI3TNMjKDGJCf3VsEJUjjk0MoX0xcrEPuSd4KtR3G%2FSi%2BErmxBdkdR1LOnrQuH2i3LR4bQGAYqKKXQCdHos2k6Dp9XcVGm9INTHaLdCldz0moo7%2FJkc2O0WqjIgo60apCx2i2goJ%2BajkqolDhu3AjggzQWQdIYmAAQQKcoqiDhLECQJAHM1TUUQcptlaNhJ43quf0RsV%2B6kiNhxtPSr%2BQW8i9A2%2FsVraWW1AqMgj2qKV%2Bg4ZEtsorOmGXLjTpQCp4AjtI7f70DhvSJDIk9nM%2F7QmFYjaW128i3caG4USCQR7xzWOeNzX5BZ8qVfH%2FI%2FOL9rDDErcxB1oqRqKisDcH6dBWCfh1NtdHQXl5JY1GS2cVfEjB22rt9aQQ4d0knmnrjFGRtdFCvt%2BU4pJM8E%2FwBaKE0%2BmJ2nYm05qlIT6yeTwfirySpbHx8iXsJNal6ZXA5MjissppbHxya2wvZutIUlSjB6mY2%2FuKTHPJ7di3lfbdji51aNKXlJBEyng06OTG%2FWxkMsKB%2F%2BIFlQa8w6oG%2BqrfjRbtFynBhJnEVlBKXVKM8jb6UqXjxXYl5o2IO3T5GtaUQD05o4Ycfp7Gqd9DtjEVIBZbSQ8eO8ntTZLjvsGc%2BOxy64rDEKfuC1cXsApEgpbP8Aq33P6CkTz29CZ%2BRJ%2ByvMUxVdw6VvOLU4d5%2FvatuOar7Fyk32yH3D7zgCULMb7SJ%2FWrGPJS2NG7a4unkoCVqWduJiqK%2BRMn2EZaF9cWlkytKlkjVHU9gZpWTLWl2Lk7OhXgF4D4Y9d2eIu2VywpEFTpAUE%2FSQaySnN%2Bw8c6O2Hg%2FlN7Lr%2BFXb9ljmZcvlCWWmLy%2BVb25PdLyfw9djQY6UjZxk%2Fejqz4f5XtsZwy1fsbtxAbSErw9WLKuUNHtr1K0n6%2FSurCbfRUJcHRSfj34NYgnAsUxIZFStndahYpDpe%2F1bgKVxuYUabHLNPQ%2FHkhPT7Pzu%2Fam%2By1eXpv8APeVbH7qoDVc24SQrVud0xzA%2FhXX8XzOT4s4v9R%2Fo7b5Re%2Fo5q3mFXTa7iyubdTNyjdQUd4G3FdJvWzzuXG46ZVmN2yw4QpC0kemINQf42VQf5KwbbWrzi0tBl0n3HI71TRul50fSDjGVXVJS866lKZ2SNtIq7OZkyOUrQds8OtsPhaG2lrE6VxJJ%2BtVYaw5ZLSI5jVy6rzQFhRJI36isueN7sH43D%2BSIUi2U6UKOpC5Ik1iejt%2BLK4pCi2y28lolSYIkpEyPasmVx6RoT%2FZ1A%2Bzlm22%2FwzL9m5fLU8hADiYEJHAjrtXGz4FbkdfxszcaOyn2ZMw2N%2FfPYLdL%2B7tuPa3HSuFLAkxM1hh2dN8mbHPZ7axPGvIU6GVwtvy1bFpCJ5%2FIVJ%2BQvYXw%2B%2FRSuG4re5sxZ9m2U3cq%2B%2BIt3koMBCEGVbjmkc4t2jZHHxdWbPYFgFo7iVph1%2Bn9kppShtGkFJjb5rTDK%2Bh8sUXTZauA4MjCrJqzVhrt%2B0%2BsJSWzpSptJBiem%2B80yOZ30VLH%2FwBJsrkvCLdeLOYs5auOrcSVFS1EqWZ9%2BAABWyP5GfImv5M2Ow7L%2Bbr68YvcMy08LNCAhP7QBITyTHWZrRDC29GRzxK1KT%2F7G%2B3hLlK9zNbfe3WsPafZY8hbSESEDiPY7V1fFS6o4PmNQf4t0y1HstY1hrJS3hdo25slKlvhBSAPgyfat8opOqsy4pxemyO3mBX2INhN7bO2q1rBeSRs6eih0H5Vzs8DZjf0yucYsrjB7iwFsyW1IU8grCY9J2IJ71j4tIeo1s1V8Sc4oy6vLqFP31zaMX4CiPxJQ4oRPxB%2BBWPPm4tKzZ4%2BCUra6NF%2FHH7SOGYQnMeGP4rdXWKoQ7bs2VjcpQp5cn0FelWgQdyATzWOfmJSdHSw%2BFr9nC%2B6wZOJeODTqsLOVkl374ljCsdcSWjP4lvqQFLcJ6kGPaszldsGNrIoyP1ffZDzZeWWXcvvrx26XaKaQmAlm5bKwBsXUwpRjknrXW8PyrXE5f8AUcLjLo6k4Vf4DmDD0t3xdcW4n1eYiUq%2BAZrrYs%2BtnDyY%2FvZS2d%2FArImKOXF7aYLZ%2BfBP7NhKFfIVG3xRckXDJo1izn9nLCMbZUhtOI4fdBOlDv3ZGpo9NxvScihJVJDFJ9plP2nh7jHh2EW7t9YY7aoOkuPQhwfQCktJP8TXCVdkB8SMSbuLJ%2FD8Oztb4K64hQLLErLhjhRB2ApeTJS7Cji5ujm1nm9ThWLOHFswovLpCS22pi2cKUxyVLUoDV8%2FrXIzeRTd2dGHiRx9lB4vnt68Qq3GSb3GrBCFpL7zIaWT3BTsBz13rJ%2FcqWkjXjxxWzTPHGje5xt3cHwxvCFFySkO%2BYUmd5%2FoKF6HxxK7Q%2BzDiqsuuM3%2BYMVtDeEk21ukhTiiOyORz1ooz%2BjSs3FDDJGC558YsxtOLu3LXD21pT5er1KRPU9NqZBtyOXl8i9t0dc%2FBPwXXbpsUXiW0WCAkKQmdMz17mvReLgSRgyz5R0dEcLyva2OGJbtmGyAj8QH4RH61snXsxcaIt%2F2606%2BtXll0neVe1OhNpaFSx27sZP5ZYaBWUoCum3NRzb7ZfxkbvLNVrrBQEpG5MgUpyY2F%2BmRx67Ci4nUrQffmqUx8k16IXiRQVqgrCuQY5oG7JGbuiIXTrRCiSqY1EqH4QDQt0PXJ%2BgMVtlegkgECdqRKXo0xar9jO6KEBWpQSf3Z6UiTS7BWWuwapK1KClBIH7u36%2B1JVv2acefWhRCfUAB6oJ5%2FvfrScmE0xz%2FAGFW2QogAEiQFT19x3pE8LXQ5T%2Bg3atpUpKYUJ5Mb0ri%2BgrJJb253WrUfYwSfrVrEn2DxRKLKzCA2rSBtPxVTxIuvRMsPti55aid0q22ifmlfGgW6JjZ2p9KFalDjmijH0Y5X7JjY2xSPUkhfeegpjx1pC%2BVMl2H2qdadX4pmDvRQTTAlIldpboEJ2CT7U%2BCM8nslVnbJIBWAT0k%2FrFOUG%2BgQ9b24VJAITPJ2pyhQucX6DDNsJB236iruypvdIMW9sQtII27xzUA7D9uwCUpTANHGvYpwDTbSfSBtxt1imgBVpvSAhMrHJ9qNQsTP%2BTHaWVESsn6cH2oowRIwvYuLcDUT6u3tVt10FxSe2YeU3pJ0pBntRJJ9gyl9Gf3UqSSkyB1JFaAEe%2FdiJHIB2g8GoC4sTDExBUe21QW4tHoYMt87jr1qAs8UymeBt3qFNaMksQOpSOaOCtiXr%2BRmhnVwFRHTrTUhk5KPYqllOoTuevSN%2F8AepYiePViwbnrPx2qCjYdbUp2kDmuOegGDjKtROnUmdz70aVkBrtnqUZATPXvVSjRaYMcs5KvRI7mhKoHu2u6joSAO45qEBrloT%2B4Pzok29EGTtnCyI5EzHFX8ZSVA9y0kLGkd44illOVOmMXcPQoKkA%2B9WU3F9jNVh6eEpPx71AuV9bGSrFQUohIgcbVCXL6ERaDeUjYbmNh81FFsHk6ZibUmVeXKe1GouwHJ9GaLQn8LSRPMii4fYIqbZ0RAJHt0%2FOrjj2Q8QwUyAAB1FP4JaYEl7PjaHgpgc%2FFVUQObMVWICYWge1XUSObEjakSCmBHzQfGwRu5ZyYUkKHHMVFBhKVCP8AhyxGkgGrcWEsiMk2KtwY1cgdIquDI8n0PGrFKdwnUo7ielWopdgOVjxNoTwmCegqXEocC0WJ2JHBgUS6%2FEpscJs1BQnTA96iUvZE0LotBJgASIMCrcWWLotikRoSR2NVKFg8kOEsqn0%2Bo9oqmorsFzFfJUdgCR125quf0VyXsbvNCFajKY3PQUXLVhKvRBMwWuHvoUlwNzBEnmh5sYkapeKHh5h2O4deNEIea0mBEmPio5p9gPxvy72fnQ%2B219lnEkIxTEsARcFuFKUkj52EfH60uXi8twGZPOy4%2FwAJK0fmw8Y8pYzguJXNteWlzbrQpQIMkCOd65eXBupFQ8rHPvs1OxG3JV6yoK6zQSwqtKjTxhLvQKSgplRCVAcCetB8Nqm2LlCPpjn7wlqAnYxyD07UD8anoXONCXmkOahK07nc78itThJKgWZqvynzEpc0kiINIfiN7sNJUNy55ohSAFdSOvvQVkhoBs90uoQXEuAHkQY%2BtXDIupbJZmjEHWY1LDiTzKuDWlRtXFBxyNaQ7N8hwSLU%2BZwFoUQR%2FI0t4sjf5V%2FsW5OXYOXD%2Bptlx1a5khY2I%2FOtEIpCmvoZos1tlJdbbcZn1J0mR8VUYXK7Ld%2Bg7h2VsLxEBxm5dSCCooW2oKPxGxq3y%2FwPim%2FZamU%2FCzMOark4dlzBAtSUBbjp9KG0Hq4tXE%2F8TWLyJyTqwn47atM2z8M%2FA7K1nmCxtMXtXnnWwkOXSBDQI5UlJTJAP1PasPNDsPi3s6yZA8G8uXmFNnK%2BfbnF2tHlqZbsvu%2BkkclLuhXTnSR70aX7Llh4%2FwAi78t5A8YcMStNleXqcuNkIQ4MSZKGZI5HrCd%2FYHsac8cm7RpxOEVTRsdkK9zfgqgvHMAwy%2BAKl%2FebZbzrp3EFQQBJmTPtTYp9jpfG1pmzmUTljOzKvv2Glp4T5rl1b3IW2D1JWRA%2FQVuxpNX9GDMpQaplbeNn2bsKxDAze5bvMGfuHHwst27jZIOngsAkSfc%2Fyp3j0pbegYZJP8ZHGHxk%2Bw9g2a14pjuFXT%2BXs4W5OvDzahKn5OxMfh45PcV6bA4cd9HK8vxlki67OTHib4KeIHh7fvJxTLD74CjKi0VCRMiY7Vc7XSs4U8DizX28ceVdONPYRdMXCUyU6DApcfLkvxqgvjl0kO7GxcdCC%2BhTTfIK1BG3tO5%2BgNXzs1YfGyQfK6PMQsWH3EMYc7eXQJ3UU6UoPWOpHvAoIZYxe3ZqxSl1J%2F8AAljuXMHw4J%2B6qvcZdcaTK3rcsoQvaQhGolUcSSJ5gVm8jy1Ho2wjapoh7%2BCXTrRe%2B7rS1qhKQIST7T81x8mZt2EsH0Jow02rLzK7YKUv94J3B6ie29JVs0xwJ9l6%2BEWL32A41h7luq3YZbXqUXiAmdtjq%2Bay%2BTCVUjd42JJnXzw08VENWIYu27PBL91pLrF22SpK1BUhJ4EHiRXLS2dtcVGic3%2FicrQcQWpVriiMRWm4GrVraVAlJO8c%2FmaRlutGvDFtJWXf4B3iWihdstAsri%2BcuFr07oQdyqex4pOF26aOhPBzTb9G%2FeWw3cY%2Fj1yy7b3l3bWiXUuA6iyCOg77c1vxxdnPnyiro2Cy1gir%2FCk3K3LdhQSG2kKISoJ5n5JrdHHS2KWRt0i%2B8lI%2B6NoaftMJecRCktuuBalgdugNWs%2FHoqeBy9m1%2FhtiS37915zDlWoSISr8SSqOCOlOj5XLpGLyPFVdm93hFiDdulRRbJtX3FeqB6XexFdbxJSfZwfL8fj3s2JxHK4xJLV22iVKRqUU7afeui8cmznRyqPZXN5lwYUbi5uUKuAneUDeCdgY5pMotPZqhNS6ZWGYrNm7VcsNtW7fLiPMSB5ZOxrDmNmGLXeznj9pHKLOWsEvMbtGfv1244thsxtJ2ExERPNcPzIO7O9%2FTpvlXo%2FJp9sPPuYsh5jxVi3ct3Mb%2B%2BeU4%2B2rqQSVAjkj69KwvG%2F5s6fmeTSqJqX4eeJbeMZww%2FFMf%2B%2BlSDCn799bjK1CN1SAfeP0q4R5aOXiyPlybP0efYX8VsDsFYfh2H3XlAgDy%2FvxuEvyR60gzp52BpkMLg7iMzZ451b7R39ylmd26tLRfn3bDKkBXnNqQFD5H1rrYs7o89kxpPZOcVzxfYVbKbs8Xw%2FEDAj7w%2BGynr0G%2FwBaOXkOMbsB%2BPb0au%2BJXivmVNm8lvH8CwhKPWtSJdVsfnissvOdWaI%2BBJmiOYvGfNGMYw7hmDeKvh7eISublLdmpZbHEAhQE%2B5PPNc6fnybqzUvCXtmvObMFzxjpvWbzMeG4uhxwqFuwtRU6gjoEJVHeN6U8zl27OjhhGKuiuGfD3PliBa3mVcJtsP8%2BWnX1%2Ba5EcJSrZA3mYp0U6I5qSKj8TsIwyyN4jFM14Rb%2BQn%2FAOS01cBZG240jcHsAKjSDWTitnNnOGcMVxTEbtvw6trtm3aWplp5LPlqcJ6id4pclvQuck9oxyr4d4hhYOac0l7F8YdMQ%2BdUHsPzptNK2BHHe2dCfs%2F5TwrD7f8Ax%2FHrcWQfEhCTulMgiAN63%2BFBLbMfkb0tHSbwvWMVuE3CHBaYcCEsNEQpQ5mK62KftGV4Wl3ZtaMUwq0w5NmwtLjhHq0nYH3nitCXsTJvojTd1b3D3kshg7xM887g1TTb0CKXOG62VKhJTxH99aNKXshWeO2oaDiVlCdoCRtJqpKy4yknplY4m62y24ljTJTAI60qSp0MWW%2BytMRunC44kmY2JSeeNj%2BdDezXGOrojN4%2BCspKkjaDHHNLm0x6QxD2pZBKSpMQZ4NAWMru5A1pWNSANyTxv0pU8aYGSNoGrukrWRAUOABx%2BVLjiaHYcdIJM6igiSlR333oJIfG7uOw9bK0lEmZiQDJO8UHFjP7md1RJbJj1BQASvhW8E9qR8TuximyUW7ULSQDJP1Bii%2BNlubJJYtSQlMJ2GqQT9aGeJ0Bknom9i0SNYnciN4BrPKKXbBlKkS%2BxtyFbCVdZ61eNXszy6JlYMEaRtJ5PYf2aaJJfZtcJAGrqRtIooxsCbJNZtAKSQJjptvTUqQoldqzqUCEpSD32rRjdIhILVj0CQnUNzzVlypBm3ZChCkifmoIk7YYZaVI9MD%2FAEn896tOhc02tBthpMJSkgfXmnIS0wyy0JkSD7f3xVkCLbIO%2BojaKdDoFwTY7S2ESQnrAjvVuwG%2BPQqhnWVSSPmjUGwJSb2zM2pCxp0qRHWieIBS%2FQ58gRAAjrApgH5GaWQRp0iesdKKLXsF%2Fs%2BDMAJiRP1pjhGtEZ55MyACCOYoMkOJD5LOgg6U0EU2Qx8lAJ2gzvRqMkVSZ55BkwIAA700DJFNUepbn0piJPHSoIy5E9HyWydXAA7dagCg30bFKQkiCIjtXKpPo79CDrAk8kR1E1XBlA9xlIB2gT1prVkGTrCVA6YjvSnjI2DnGkmD079PpV8AecRmq1JE6Y2oeVMimhiqy0ys6lL9%2BKbGVhjBdqQqBJMbzUcUIcGuxk7apMgoKCOoquCBGarWNQlJVPXgVfBEjJJUM12x17tKUr24qvjQUZ0hD7q2IHlkA%2FxoZQ%2BiSm32Zm1ATqUkDtqPNUoNgngZJmUjnodqJ4l9lWeG1STKkAyJpvwqgW36Pk2rPKQSJ224oo400AosyLCfV6FEHbrV%2FEiNNHirdKdIKTPT3qfGgXIbLtm5ICEg%2FwAKHgyuSG6rMQqNvrUUmtFmX3IyDO3vTk9EoUTaJB6GoQci0QP3QPc81VAuSHCLZIQAJI%2FvipSBlkHCLZJ20781dC2xdFpBIUPpFGoNguSWmK%2FcyoyJ08GRVOLROaM%2FukbkCf4UIQui1KAJTVNWXR6bckEFOk9v9qvgBaBGJWivKVoKkmKqUXVIvkigs83GI2Dbi2xukTI%2FpSXhb7GRl9mkmevG1GBPPN37v3YEmVkQk%2FNRR0Oj5aT2aY%2BKvi9lPM1o6h%2B5sHgpGlICwQonuKW5%2FRp%2BZT6OJf2pck5UxEX%2BIW9jZPFxJCiACoH6cVjyeWk9mx%2F03BKH0ziD4h5GsE3l25ZNoZUkEQBE78RQvIns5L8N433o1vxHDXbJw6wSPbiaid9FcdjFol1OhakAxsOI%2FrWLLklFvbCpPs%2BdaSmSlQUkbbjj2qvmyVysY8aatDRahIB59%2BK0RhOStiX2NkuLaClaHHBwDyDTJ44V%2BRZ6bwFIlKmzEHYxRQwQSuIjJPInpCaUOSAh1xYVyQJBp%2FJUMhJvsN4W1d27gdtXWtttKgCD9Kzy8mC7GX9EvtsOduyXnrRTDqgf3hoV8GgklNfQaiqDVngL3mBdqgP7bjUCUK%2BO1Iebh%2BL2HCSXZZuXsu5ZU4hrM6brD4SSF2rZUtRjYQDtP%2BY8UH986oZDFy2y4rXFSba1wnLn3rCcLZhxKXWvOMdSVAgT1kg9qyynydsao0bd%2BGVrgwZYv82fc7W3cZCGntBtxcnoSkStZM%2FuiKz5JLs6uHUejeXI2Z8x5VDDGWsesbvCliFtsv6i0meCy4FKO3AgdqOM6CThLtF1ZWy%2FmS6x6%2BxTDfFbKdw08jzXMKQkWV20Z%2FeCHSuB%2FpT%2BVaYRv2W8rquJsrlTN%2BTMrttWuZ895VwxrTqfUcbfefUsTJTKD%2BUztWvHkUdSZz8mCcn%2BMbLhRnDKPiCwl7L3i3lVeHtDZd7a2qy6mNoS8pKwPkSaY2pbi0SOJruDLHyde4xZhV80vJOYwoaG3WU%2FdnFp44QlaI%2BFCafiaivyQjLBN1VFY588OLLNGK3V3eheX5CglzWs%2FelKIJSGmkyqI%2FeNPxeS4u4sB4oJa2avZ58JjiwXl2%2FwPCcz2hYV5iBhylPNnhIKh%2BA7zpmSea34f6iYsngxT5HM7xW%2Byfgts7iS2%2FDDFsrBLqmmxdkquLhQiXCmAIHsI3imZfK%2BRVEKONvo1Ud%2By424G3rLL2Ku3KlqgqtVgrA7SP0rC5S9mmPjL2QjF%2FBa%2BwOxvLtnKN4nyyEp1oPpVMARO%2FSglka7ZcsEUiG4T4C5lxx22vsx4ZieDWZc8tKXmikqPPpQd%2BI3rn586QEMYningdc4e86jynnsNRqDZKCE6pjnqZ27bGsM%2FLl6Zsx%2BLe0kVRnHw6ucsWiLy6tre3Kjsgk%2BYB3IPE1F5bb7DyYWl0Ul%2FiNlY4mw8u3Lnq9KCdWke5rTPM3Gl2Kg30bNWWcsTfwbD0M4rcvWrTfpt1KBDQjfTtt8Vz8lR3Vj8E23Ui6cmeIxzFhLWEYw%2BtrFULDeojZ1I%2FDP99Kzyd6R2vFkujor9ni7x7DctuIe1PJW7LaVpkmOAOtJlNxdI7vjQ4xbkdDfB1jF7i8xbFX7yysheFQVrVMICdoA35rTgnX5N0Xk4OKTVm42RMBx27w5F5c45heYsQUoltLqtBQgH8KEde01p%2BV1VmCeTHF%2FxZsblxOI271jhl3asNqUQUzb7j21daCEnyVgNxmnKJut4aZbt3XWXHmbhplZ0rE7A%2Bx%2Bleh8Xxk%2Bzg%2BXmro3EyphyLP7utakraSdA22A966GPxlE40ptmyuXr4BpFqpfmBSZTJ6fFdHGqWzBlhrQnieFsXCbkpSopUQQCdjFDPHF%2BgYO%2Bigc7YBd2Fwp9i3ZU0oTqSkkj2%2BnauX5OKkdbxsn2a7%2BJmRxjeU0qvkIfuFqKSlbYkatpA6c1zZQtbN%2FzpSuJ%2BSD%2FqTfZ5t8Dzjj2araxeh29FrbonUhJCQNfYSBEVx8r3xOxkfPFGSOPo8OM0YbjCLm5wLHLi4t3fLtLFhlTiXV6Z2RxpSIUSaZgjTujlyyu6R0K%2BzB4kIyKq2w69w%2FEsQunFB6%2BvlDyWLBA4Sl1I2kwCRydhMVuyYZNWtCIZ2nfo78fZ18X7XNGFW9ji2G3uKWylarVTa1IU0kdFkOb%2B0gH2rL%2Fbyhtj3l5G2ubbq5Vb21zgllZ4OZT5q37ZVypxMdklIB6eqaOUXL0Uor2asZi8O8y5pxTEMQvcfuWcOICklm8NvBPQQPSPaTWWXhyfTo6GPOoxpIjmG%2BCV9lUjEsSxLDsqYYtK1LV6rtxc%2Fv6ypIMjpFBLw4Y3ti15fJ%2Fkgcvx28PMmtKwXIdli2ZcQTC375NsyEKIO5U8tekDsBNThBfwGwi5rka%2B%2BLXjN4o4u1dt2F3gGWsJW35jz5ly5cQRulCth2%2FCNqpWOwRo0j%2FwAAfz1ZYg5lvJxbbacUt%2FE7tAQbtz%2FMZ9R%2Bdh7U2OK9orNKF%2FkV%2FhXhrh%2BUrt%2B%2Fx7FbbEsUcSXFMsKCG2%2B45B%2FIUfBI502%2FSDIdwYpZxR02y2knS2iTp1THpn8RopdWy4OT0zYvwsGK5rFq0hpNlYatDaEJ9b2%2F4iR09qfjaZNJbN%2F8HtLXJuD27bt4W3tPrJ%2FF2gRxWuOTiqRhWSUn%2BK0QTFPFkW9yjBsNu0pddcCdk6lATyfetMct9jXKK1JbL%2ByM7cos2rzE1IU4UpIDhgpHetcEZck1J%2FRNMXzUhprQ0RIHJ%2FpRiyocYxQPqWsugmR9DUIk2VFjWLIQpwgwkE9zIisc5Ux6hfRAbnEJKilJCTuSRJP0pc8mtmiE30Dl3P4BJKQkyD2pTimOdPsaOLASlWnQIn4P1pllPJFAi6WrStesHcp9J5qALPbqhoy55jgMhaDsY%2Fdih510h6yJEmtVFCwgqVqPtv7UWSS7YxZKJNaR5iFBJIO8lMbf80gPHkbZMbBMAqWhJVwQOQTzSuK9mjkiU2yQsoVELidzVwSexeRkjsmVBSFEQOP7npRSSuwCX2LZT5YHqA2G%2B%2F8AvWecU90KnFE3w9knSBq1e%2FJqcYr0BZNrJABB9SiRx70FRfQLbJPatghsCZo1GhTbZLrFoEJ9Jng7URRKLRHA3C9z7CmtfjRA7bNyAVSQdz1ooqkJlFrbDrKEqOkDfrt7UTIsd7C7SCdiJHMxzUSsr462E2mlqKCEiJ69K0RdWLckGkNoEEDcbCgjKxT6CTKeARqEbjimctUA9LY%2BDaFDdMDuJqRv0Z5ukKogbJCifmtMHKrKgmLoTqkkQeg%2Fs0zlIMWQ2CQTt%2FfWrLFktpVyCrmqsCUV2LBhMgFSuOgp8XoUfFhMbnfn61dEE1W8kekz0Mx9KuhOSbRgW91Qmfkc1BazswLMEnc%2FG81CpZE0eFtPBAFQUYeUABAVB3gVBkMjWjYZbJ07fiJ561x02jrSg12NShwaiVQOd9q0AqTEFbA6oBjbTUDU372NChPqgHeoXzGi2kq%2FEkk71RVx%2BhmbdBgo1I3gwDUI1EbKZMyN42k7VL9CxL7soknSfyFC0%2FRdDdy1bURACe%2B3NDxkQaOWYB2JUY4PSjjbYPFDBdl6gobbxvzFE0ENlWGohISNQP0o8ZBJVmJASBtye9G46IYG12JASSOvagWNkMk26jso6jyTRqNFM9%2B6oSZAE8CaITyZ8WBIO367VCm2JKtwRBBMb96gNMSNrIMwD7VCuCMDazOoiKql2EkZJtCBuCrnYUSi30RujL7qAORt7VfBguX0Li1kmAkjapwYti7dqSoaQCe9WsbBk6VjpFmojSQD7mi%2BNC%2FkY6RaCAmAoDrRoBu3Y4TZEBRKR89aha7M02SZjQBI9Uig4IeLptRAEJT7USikJm3dC%2F3SQNp2orBGV3hupKtISe1Syf5KlzllpN1avJWlAJB3jmqsZ8hy%2B%2B0X4WC5w%2FEnRbNklJO6YidtjQZYKcdIix3vR%2BbP7SjebfD%2FABK%2BFq7f26ElaknlP07GvOeV4s039GqCpHMTO%2FjtmRS37K9dedBkKOokn9a5jZojH2mak5pzc1iVyp1Q0Ejnc%2FnNFLJKhvK4u3sqTEX2bgiFJbUBuqefrWzHNuNBNx4kSubdCHNlpE7mI%2BBRLDfbBjgTVoScCilI2JAG54V%2FSs0kk9yFLA%2FsZAJ1GUyqSJ%2FOmf3L6TFOLXYqlhSgHChAAEQI3FEuE%2FYSivsRNsXPVpBHYnmo8Li9MZHC6sxFslAhSCmD2iD809ym9CnBj5hZQjYkImArqKXHxUttj8eNabJNYYk6plLbjqXt9J2E0Tg%2BompxhPaZK8NxNFr5ZBJMbqnr8Vkyxd1WxMsCsnuCZxtGLpp69ZTcsIUFFABQHB%2FlUOo9%2BazfDLtobFqOkXvZ5uyYlLGIZNwnC8LxzTrcSt1YcaPTSpR0nvA3pLg27NUckYrXYEUrO2L3CMaxe%2FuQlSpbUm1KVKTHHmTCvneKsPjOStMubJ%2BbcwZUT56mrk25XBRd3KUI8wjY7QYjqfzpc8g7FDj2zYvJH2t8u4fi1kzmXBMpYS8yPJVdWeIKbQgz%2BJRQCtXX8KifY0WPLZqcuXs3py54vM5wwa4cy%2FnzDTZPaTOItuv2xT08t6%2BYbUO8QQOhrbCbS7%2F5M88kV%2FJByyxvPOTwXV2%2BQsMWtpTi8QsMStnVrA41IIGmegAg96vl%2FgW%2FKfUb%2FwDks3Kn2pckst2aM2%2BKWWLbEUSi5tzjDLV2uBsAQdj%2FAKREU%2F5FVWJfKTtr%2FgsjBfHPHMxXP3vJ2X8bxPLgQpaLqzvB6k9At5wq%2FNKZNAszb0rG8MdfTLDy94g4jmRC75Vpi2G3zTag264%2BtTNkd%2FWVJbA1f6iSaZ8km%2FoTLDAiWO5cwbGLhjE8yLx3HMZKPMS45cOH7y2IO5WSoN8HgA%2B9NeZr2SOD%2FpK7ZwOxxzMAt28AcxPE2EAWanVH7theobuG3Qd520he5mTFK%2FuZPS2G%2FHa2yPO%2BEFhhmPXDuOWLLoQ7rLYd1LuXT3j0oAMSAJHFA8k%2FaI%2FHi9osHCfAqyxlTeE32BW7lytJu7u8IH%2FxWTEDXEqcV%2BFKAYG5M0UIt9oVkwRS0yvvEfwAyfhqcSxgYcbZDTYQ1rI8plPCdUwZ23PvWbyKXaG%2BJ47l0zhD9rPJN1hDrruGO3GPNuqUrz2gNE9kAH8IiJ4MVixJt2bPNahDemczrvCr9eIKQtDqCkT6gRBrq48TS5dnAnJ6cWWVlXEl4fcsYdfh1gKEJUpW8nuOopuXA5rqjRDLyVLs2d8N8qC8zfYfdr5D63UFbQRGl2AdoPWZFcrLjcY7Oh4U%2FwD3FbOzHgWbrD8v2aby2Djyi4C1AJQAOZ%2FKuTLJL%2BT6Pa2pxVaNkcHzxbYS%2FY2K7du1t1qAelsq9BO8kdOtLeZPTNeLwZcbtHQfwutcMvbVi6bxNLKgoLbc0nUkdxPSK6niYoT2mcvzJPHo3wyfZYRiDVgLltL9wkApdKRIIPOoV6LB46dWedy3Ftm2uWLq0bt27ZtxMphSY2Art43x0jj548nbL9y2269beWF7lIVq1cma1wv0ZpcVposjL11fNPsh1RKkGAZmR2NXGLTFyUX0WU3eLu3G9UpQdlJ6%2FNGZnBXoFYjh1jiK3bZ5Os%2FhSSBt80mcI1RcG1tFWY9kl8m6b0o%2B7pEpC0D1bcViy%2BG%2Fs0RzpaONv2vPAfB%2FER3HrS1wlGLXj100ryi3KWCkafNBPCQCdu9cvL%2FTl%2FI7%2Fi%2BSlD8ujj94p%2FZItcW8SbtnCLrG8Ly2ygIxK9tSkOfd9PrZt0lQJdXB1OGUoA68Vm%2BJRdroPLjTg2n30URmf7M9xnbMbN54fWWP5by%2FaIAw6wRfpPnJjSlZb8oqBO5Lri9SuUoSBNaVN9Iy4vHeOP5ezavwb8FvHDBL3CMJy%2Fi1y7ZW6y463cPB9m2UQPSp9wdeSkaj2imKDauwZyikdUskZYz%2FAIdbtt41f4deAkKcbtVL8sRzKtQRM9EmlN2IjN9h7M2CZkumrduzzccKU4ony0WwQ%2B0oAQAslYQPkUE42aIy1sqnEfBjHMyXzOIYwvBfEIsDzHkYriX4COIQgoSsiSd6W%2FGcu2V83B00MMbt8PyjhK14lkDIKbjSQyWk6FAb%2FhklIHuZNDk8d1UUHjyq66NPw9mDOWNu2Fr4V4HieKFzSXbVakshIO3mEEqVHYwO1Z4YZXSOmpxSu7LOzZly%2BytlZGErwOwfx25SYw%2FD8JTpSn%2FWtWwj%2FMo1uhF1swvyouf5I5%2F%2BKbd7hFxZ2WF5Nw3EceUr0qkLaaUeNRGyiOwkUueGb6RWXPzdwRVeDeEeP3uPW%2BLeIeItO3pOpDGrdsTsltCdgOmwA70uPiSu5MHDObdM6FZUxTJ3hVgdtc4k5Y4atxEtMpAU%2Bsd4HT2p9RjsPK4y7Gi854rn6%2FKMDwa9YtDslx9XqWOQqBskfNA5ubqKCjkqPGKokeWsjWmW7teKYk4m%2FwAaUokFQBCesT0FdDFhaVSZjyuK2%2By1bfFsTu1DVJbEDmY%2BK6EIMwTyRT0Fni%2Bq3C7hawRJKQdjRygl7CjvogmLX60pDUyI2g7f80iUkPhhXbZUuO3sLc9YUr36f0rHNq9GuLitJkIXiDilJmAkfh09%2B4oGvsYpRs%2B%2B%2FOrBBhQO4iATUUUgqQoq6iFndXRM7k%2Fz%2FwBqtoW8KfbAd5fqUFNEATvI2j5qqBjDi9GVk%2F5i0JAUIgAz%2FSpK%2FQybfaRMre5VpQiAlG8nmfr9KWsfskYfZJrAqKwsEpCQJ9REfIp6wpxsY4KrJthm%2B4MJjbjmf1pM4IEmVrvpSQCQOnalpUMhJIlWHAkBAEGdt%2Baqd1okp%2FRMMPa1KC9jG89qXzfsBuyaYY3u2YgDb5%2FOgKJth6QCNW87xUjiBlLRLbNHqT0%2BlPUKMryfRJrVMFIJjgemror5GSm1Chp41Ht0qwlyfYdtx6gBO4ncVCZekGbeAQkEjrUE0guyZCU7p9qOHZdBW1ggRt7E02xD7CraQooGogDcJO9WmUEGIBE7fSpLsDIPURpkkz7DipF70IbQ6QZ6DY8960wbuhlqhYqCxACCOx2pwI6REAEj44qFSdIcAAwOR79%2Fc1VbFObYslGwng8QdqfCNAiyUBUz%2BtEKlF3owU1pEad6gqeRqWzAs77gaeagco8ltiakHVtpI6xyKgiWNR6EVIEEplRneBzUBElJOqTB6b71CGxOlTg9KdJ99oFcr4ztTduxBaCoAKQQRwd6OMaBGzjGoTpXqohcVQ0VbL1FKUqEd6gyhFTJO50EUShZTY3UySTISd9pHt2q3jZYkq2k7pKge%2F8AfxU%2BNkEvu6j%2BLWD7cVPjZE6PCxM6kgJHG%2FP0piWinkrsRXa77J53qyWhs5ad0CB33%2BtSyxsu1RMKQD9KpxT7IMnLGOFad99pFVxS6Ac0mJOWwAOgQr%2BFTZOaEBbGJhII2PtQ8mKYp92CkiQqRG3U0UW%2FZBNTEEggAydX%2FNEW1qxBNuFQJSO0moUYi20gkJJnrTfjRDJFoVEp2PQ70LxgT6FfuvrJ2KfajgqMs3ZkbNIkg7c8zRC2hZFqkHUBIqBKTXQ5TbCQQlP51AnkvTHabVIMQJ9%2B1QCl6HCLZO3oCahB0i1BiEgK7TvUILJtBo3SnVO%2B%2FFQqhZNqnaEnntULM02v%2Bkx8%2FrUIZG1B2KCTzvvNQgCxLBG7pK0qRuf73qENZfErwzZxC3uAppKkmfxCfrRKLZceX%2Bk4bfbE%2By4xj1hiF0m0Uh1KSoBIB3jr7%2FFZ8%2BBPtFyi632flk%2B0X4G3OXsdvkJt1IUFqOydO4rkeT4sYPo34m1Gmc7M15XurB506XCkSeOa52PJHpRNMJbplXXbaiDvsBumYmnY2%2FSo1qVewQ5stCdJaBMwNpFVkyJ6RFS2eOvIWl0bq3%2FKsPDi9mf5ECXXEpSob6iNtpq3TZlySuVidtdq80hIUUkyd4n2re%2FEjxtMAmOFO2twfLdtkBfEg9P760K3C2a8UnWiTvYKltkrQULQRtBn86zY86bpoOMm9SI4%2FhiPNWpsICh24J%2BK2Ti5rUtFZMTdA5y20FW4S4ZCVAbSKyrKoMRcY9IwQu7ZSClBUlEgqB%2FUVsWRNWOx5H9WHcNdt3nm21MP%2BaYnqfcis2Rziu7NDTst%2FA3Upb%2B7s2irpBJUVad0EddYHPxXLbbY%2FhBaTLIwjOWL5Ofw67s8zYi1aIMi0NwH2z3Bb3M%2FlRQbsL5FHrZNE%2BPmVF3aL3MOWcuYjcfgKL22ISox1Qkgj5Jq3FMn9yAkeJ1nid09cs5Oy9huG6ypq4aZ0Ntp7BW5gdpNZsmLdpDVniWfkfMP%2Fc1%2BrEWcSZw%2FDGkhLiW8T%2B6ByOiSsz%2Bk0XOS70NjO%2Bi%2BbDPeX8FbZu8T8QG8NBbCVC0xI3q9IP4Any1KUr5NWsv2w42%2FRdeWM34bmC8ZXkfD2c04mhSS2rFTa2pX1lxLm3O07U%2BE41oVPHem6DmN4t4x4i7bWzmB22XkJdJdTbYm04wkc6UlvY%2FA%2FOj5MqGGjbbwbv8AxNxe%2BascRx3xEzTbMoDNvh7Fq1%2Fh7Ln%2BpxxxBSR1ICjRRyPpoDJrtG5ln4Q4ZjtzbX%2BbnVqft3Ul21w1guF89laFRpSOVLUBztWv41dsyLymv4FjW2W8m2AdRkW8y7haEqBufJfS2yyf3it0wlS4ifxGicY1rQ%2BMpy7QXwH%2FALPw2%2BXb4Nhl7mTEUlTirw2ZNshZHIUr1umf8oCarnFdq2LlindhTE71yxt7%2B8uG3VXbhSXHr99DSWU8Q2w2fT9ZNLz5uMRsMTbqjnV9snx5wXKuUrjDLi%2FsXMSU2p1jC7f1uvngLdCvwpB7xtXC8jypz0ukej%2FpuB4nbR%2BYzxY8bM7Y7mm4vb7FQ4Vej7syIat0zwmu34M2o9Hnv6nP5Mrv0EcojAM3WXmOlLGKAEKWhOuT7oP8RXfxKEl1s4WWNPZHcdyfimGYq0h21%2B82alS3dJSIB7EDiKVmxNbR0PFypKjZ%2FwAKsIucAxDBcVZuZdQsKKSPSDHPwZ4rznm5pybidXxYuM00defDx5d%2FhOH3OC26Hb5VuS4mZKV%2Bw%2BtcRePObbTPUxmpLbNk8NyHmS7xPLeYywq1Wpny32QNlEAAAztJpq8CR0cXkRUXGzf7wiy4jDk279xb3VrfLGnQskp2%2FQCu74PicNnD87yW1R0AyLfWySw25bJaiIKDAn%2Bdei8eFnn8sXdl5YDbKTfPBwqShfqbKeJ9q2ODFNaNi8oYiuzH3Z8KeWVCFRuUk03Frs52WDe0WzZKQ242vVp1KjatJmf7J4yXg6zdIUhKjAknkT1qAWuqDqkl5lTyG0FfXbb5piSYukJqs2cQsnk3SPOeUCknoBVSgvoFxadro068W%2FDC2cssUetbN1eIXB8przXT5ZTwVqQABsOk80jJiTVUMU239Uah4f4EYpf3V4tWXLa4losIWtvSPL59U7CTv27zXIyYWjoY%2FJt1Y5yZ9mvA8GduW8St7i5SpfmHD7Ul1C1nklJASsmN1r1bDYChx4t20TyPKdUtfv2XzgvhChtCrK1wVqww0mfIbR5aFT0WsgKIHtA9jT3D6Mccq%2F1OyS2XhFl2ztXlYjh1u9pXslWpwA%2BylEnbvt8Umfiw9jPmk%2BtIrq%2F8NcmYai7RZFnDXFalFTTShJJkkAGT8nvWeWCK2jRjyzb7srjGfCqyvQ07aPqdSJV5fkr0ODsQSPnc1mfj8npmt5dbRVr3hrlxFwprFMAwV7y5X5z96tZ3nmfSgf6QZp0MWqkZ3NN21QNdwnBsHYvWcuNYaAr1uqw1KWwg9lqPJ%2FM0ccPpaLnkTVLo0x8S824bjmM3GXsMxDFMPs0em7KLJTmtQ%2FdW4VcewHzVTjsHEoK7Ts1i8QbjG7xyzy9kPCc0YziLkIU9h9ohvRO2yyIA9xG1Zp5ZLo6OGMauTKRzArDPC9axd3txmnxDKQo2nnpuG7JZjd5SfxrG3pBjbelSzJbathLnlvVL7D%2FhpljMfiFjSMbzMld3cqg6LgQPaEjgdhSYpzf5Dv4rZvnl%2FIrzNu0A2q2YSmD5aAgHaOldLHSVGHPk2SX%2FALXS2G2ra0StZ21FWomt%2BOa9nOyKyU4fkt5lo3F2EpX0REbfP0rVCK7QvhoiuZii2K7VrSBMEp3oZ62VjaT%2FAGU1jdw0yw4JEiSVHaszmno6GFy9vRR%2BI34fu1FYLrYJghJ3PSK52eT6RofjruwGp1olSFLQgk9TE%2B9BinXbIvHX%2BRe3YWVBSUhxIJnbn2rXYxOMR%2BoKSlPqCF8mf0kVaMzzSYBubV11aXEpJE9B%2BdVY7DmS0wnaMBpLZlRSYSYBkCPejSse5Xsk1ohSlFtJgjklXO%2FNCyiaYchLIC1BO%2BxPNJ5N6Fu2TPDVtL07A%2BqUgiI96JwaFZZyVEzsWULQg6ZM7b7zQWE8r42yaYdbwUlQAgRtA%2FKiir0A8pO8OtDttAJ6GglBN7CT9k0srRZKdiVRsO1FoKWaiX2NtoASUGes0agmJeZsmFk16BpSRv1%2FviqlH6Fkjs2UkDZUyevFAQPW6SNknT2EcfNQLmw1bcRCgCZ4qA0GGjpKOe81CBFtWpR5mDJI5qULyLQUYXBSmR%2BlPXQsLtqKgJPsBRw7IP21EAAkj5pklaKa0PEqEJKgI7GlSTQiehylZSSQncwKNS1sg4kCRsNuKPsg7aUVp3j6mYp8ZWSx2mIIEc%2FnRCZp3Y4TEgHeD16VcXQKY4EBKfSRttT0wZRtUKBIO5ClL6bxUM%2BTEl%2FET07FUAienNQTXoTVKiSd9%2B3FQJQbElNiSoFYPGxqDViktobuNjgE%2FU8VCssNfs2QLKB6R3may8EbuY3VbrEFKlFNA4P0T5EJqZcEAq3%2BJirjj%2BxizWNFpcSrcpjrIoXD6ZfyP7MHGlHlLff4o4Qd2Ryb7MPI1SqQPpRlWvYipgbiZjtUKeRejzyDyR%2BtQtMTLKtQ5SahTS9mJtSJHpgVAJRVCSrYmZSZ6GIE1ClOhotgzqVBHf2qF%2FIMl2pAJEpI3qFNpjVTRBBhX1FQFITU1%2BGQVdahQmWhqBiJHXmoQQU2AQNh81aBc0kYhmCAdOnptzV8K7B%2BRCot1GNjPxR3ICWUULJJCiBpPO1XTAWZp2hRFudR%2FdB4q1YuUrdijdqsmCASNuasEVRaqJPOmNjNQg4RbSAD6Y496hB03bg%2BmBJ7VCDlLCug0jjbpUKbHCbcCSomY5qJEtCyGE6dlJHtR%2FGwqF%2Fuxj06fbrFXwL4fsVRbrggJIiq4ojTX7FTbKJMgGPeo0q0U3%2BjFdnqSBKQevX86AoiGYcJbeZd1pSr07z1onJvQXKRpB4z5FwrFrO9Q8y0sKTHG1COxtS%2FGR%2Bbj7cX2fsBUjE8RZaQ06lJOmAJ7xFYPNhKaNOLA1LT0fmb8YMu2uG3l8wElGgn0gTI377156fjTj0zpPInKmagYza24C1JTqVABKTt%2BVL%2FALmS1ZTf0QS9RpJHpCQQYFMx5r7M%2BaTQHcCwZ9Bn847USyY7uSszbYwdbUtxX4gOIArTjWPtMNRj9j%2FCmmWrxhdw2AynkKEinfNF%2FwAWDFL2Wc1hdhcWScRQ40XUqGlDQ0BQ6%2B8%2FFL5I1wk1oKtIw95YTb3LuHSAPLc1KSD%2FAO0b0mcI9rsJOcdULP5eu0oC7lxlpBEpUtYT5g%2F0%2FwBxQylXsp517ERlJsAO3WL4fh6vxJQlYcVB%2FwBKf5xROEHFiXxa0gU9aWGGvpW%2B3e4o0eshsK%2FQ0KjGvx7CSaVxQrc5qYYYLOH5YwzDgE6VuKK3XFieqiY%2BgEUiePdN2R5GvYKGYMZvEhLmIP8A3dMpSyowgewSNhS54uDrsiS7TF7e6eW422VhtQkykxv%2FAC4NCGu%2Bxy6JdbdD9q6Z5UoEn5FQNsl2D3Ng9oF%2FiN0HU8IKNbY7R2HxS5uxkGWJl9WGWV394dvpaX6VAoKE7nvJ2%2Bk0qUdGrC9my%2BQ8q5YxRpy%2BsMVydg%2BIs%2BtP33EnGGVbfi1qQY%2BtZ4xRti2tk4yzl62Q5cF%2FNuRLTElylX%2BH4o%2B6tc8AOstj8yetHaXs04fMje0bUZX8TM%2F5eRh%2BDs43lbNF4lohtN4tF3csJHA6LIHYzSZZpv8AiaZfFPb0XphH2h7Sybsms3YXmJhKAAy3hWCqCy6IMrU4ot6eekzRRzyT2Xk8XHLaLqH2k8NxHLZcxDAvEf8AwpYISyhbVn96IJG7aURB7wfanSySyoyT8WDddENxHxw8TsSw9uzyP4TZ4wLAgoABqxdWlwwfWHllHq4khMdjWeUZ1xs04%2FHwxX5Sv%2FsL232gfERnDBg9%2FcrtXvUlxi6uv2gI2hRQ4mT%2FAPrfNYcssi1f%2FIvJixRfKkUnmr7TWbsq333VzHsuPWRB0t%2FfSkJ%2FKYVP%2Bugh4c5rcn%2F3OhDPDjyRzh8dfHDO2fF3S7lWEXKSYRb26lAKQOq1T7zuTNdbxfFjjicbzvOb6ZoJfZFzDj109e%2BShThMlSFAISOyd9673j40opxONlm%2F5N7JxlHw9xGwuG7zQ6i7ahRSlzQtPuO9aVOd7MM23tm1%2BR8BTmBa8OvWUN3q0Hy3Hj%2F5z1Dk7E%2B9Dk81PTH4Z1os6wyZi2E36cNTauFsgpKVCUp22INc7OoSncTr%2BLmdbOrv2ffDXELLLWA4rdONIcWpAStK5ChtMEdPelrw1GWmdTDm1xZ0oscD%2B9KZeLCm1gBSW5kEgCBHSt6g%2FaDSX2XVlSS6kKuFs3KEdVCU78Voiq7DrRs5lC7wxf3dYuWlkKhYmCk9960QnRzs8WukXzh12tm5ZUh9CmVDVCen04rQpGNbdUWjl%2FG3LW6ae%2B9yWz%2BEnkdvajxydhSwqS2XxhuNi%2Ft9ZdUh%2FYgz%2BE%2B%2FtXQ%2BR0YXhjHRYGAYi%2FcWLhuH0KAXCY%2FEBVc2Zpxron1pd%2FsypkcEbdxWiD2KnAPJfZKlkJDKikCO9HKS9maWNgbFLBq9uEqIS4ngJ5A37VTpgSj9CjGTcOfbcC2UK1%2BpQ3hR%2FwBW%2B%2FxQvEnsVzpjj%2Fspq2%2FaNpSANw2NpPv3HtxQrGvRTy32RvG8svMsrfLbiHyTLi1AkT7Db6VWTFYDyU9FI5mwkWbZu1X1rbWyAS4t57SCOZJmE79N6xZfH%2F6TXDN6KUv7jVdJQ%2Fi7LSCVBCfLIJJ4O4mPyrm5INabN%2BNtIFusYXcoW5c3AxtJToIcQoj6JG0fNAo10OjMrTOuTsRxW0Yw%2FDbd3B8OUBpCLIqKwNyREJHyqtEI%2FszZM6bpFV4r4Sqs0wzeXDCHAEuBwEuK7kkKgD4pnKMQHCXqRXOJfZ%2Fy0u0Uytu5vXiorCQnyiTzIAJJ55JpLWNvego8o%2B7KSz14V5iYw9WA5bRd4HaOoLbjdosl98cQt3oPZNZM%2BO9R6NuJqMlKXZrhZfZaucKxVt19VixckFSkugLUgnqSYrKvFrZrj5KWkzb7w58O7PL9gtdhlh3HL8J3ecb8tlJ7zEmtMF9i5%2BRyX4q%2F86J7h%2BSMy4zdTiKrTDLJJ%2FZsMnp%2Fq61uxxjRhbf2WQxkSwwxlJBS87E%2BhHJ%2BaapV0ilC%2ByJ5hy9fLbcU5cNWTGxKVEI%2FXmmxkmBLEa75mw%2FCLXzVXWYMPZSncpaQ48r9AAfzqOvboqEN2UZmB7JbwLKMxY8UkkEtYWAFH2KnBWbPw6TN2OE0roqy8a8PWlK1YxnFZJKSpFgwN%2Fq7xSpcK2a18t%2BhpZWXh9clJZxjOrZBkBzDGFye3%2FmpbwRYUoz9V%2FyS5GA5GW2Qc1Y7buBZMuYPIT8hDp70%2BOKP2LnzXoyOUMBuVqVaZ3wY9YuLS5Zn2nQpP60%2F4YrT2Y3KXtGX%2FwBNcYuUupw28y7ir6RITa4k0tSp%2FwBJIVP0oljXQUMkVtgrEMl5lwlRViWC4pYoSPxuMq0K%2Bu4NZpwcWa4ZYPSYla2pG4CSr8Psn4pLY1P2iTWjCk6Y1FJHE7bD%2B%2BKF5YR1WwOaJNYIUkpIXPvMCKKORdsCUk%2BywcNCwEwW1JJ6nc1cnFkdSVMsHDWFaUBxJ1SNu%2B1DxSVmecUuixsMtP2gSAdWxHtUcUy4yfRPcPsVamwNJEE8b%2FU1fBCZdEttbNZ9Wj1Ebg0SVCiR2lqSQSExO2%2FNWnRak0SG3tjKFD36UEohKT9hFDUAgiD2jeaSSU%2FoJsNwAAqTvHcVdMYmEG%2FSAZBUKlEsfpUQobieDtx7VLoVKQ%2BacgJ3AJ69qKO%2BwQmy8SSSrUnoOtMSogSbWO5G29EpMg8aUQY9J6RNHGX2RsItqGlMfqaU1szvsUK91GSDHWnqWif7DpD2kKPIMUcJb0QeauCNAA708g7QsEAhWonpVNip0O0EFI9QI32705TQFikwBtyOKK0DI8JBIkxPFWKji3ZgPTvINQdR4ZiSBMVTZKGroI3TsOtRNC8raWjaN21PVI9qQNu9jBbEHgg%2FwqFp0JFrfcJJHvUI2YKbSOQfrUKMfKQSTpAMdKhdsTLMfgCfnrUCUxM2%2FYBVQv5DH7srVIQAP74q0yPIefd44Sk9ZipoXJtnn3WZBAUe9W1Eu2YqtYkaB7VVbpFWM3bXY7bxt7UyMPsg0XbmYgCr4oi2M1sJkyk88DvVfGim0hutgAHUN%2BSO1X8aM8c7bGSrdJ3KUg1FFD4v7EfJMSUq42okhOWq0epZMkETvPwKhnFkMKO0dZ7VCC6GdhMJFQgsG07%2BkHbvUIKItxsAkR%2BdQgulgkbCP76VCCwZG6TyN%2Fmi4sgsGhJ9JJmNqJY9EHzTCYTttHcVONdEadWORbpH4hP0q7fROTM0NKVIS0IFXxC4P6FQw%2Bok6NInbbmooInBsUFouR6lA9RFEOXQt9107FRG30qPfZUlaoRXau6SQsrHaqpAfH%2ByM4xbPuNOnTqTHXpVUkFLJTo1O8VMv3NzbXKmNTatJgd%2BaXKvQqUt2cQvtdZCzDiOFYm2izNySDA6%2FT23pGVN6SH4c0kz8o%2F2mcgYnhmKYgq5tFtuBSgFFO6oJ2muB5sckf4o6PjyU3ZzLzLhr1q46kBYPUERFclPe1s1Sil0VzclxuQkGRtIG1OwxUpbESt%2BhmLd14EmSSJI22rS8FvSozrBJsPWmWnrtJ8sFW0enpU4Qi9oZwjF1JBy2yVcOqbSAuBsNW0%2F7VlnMjhB9Ms3CvDLEXWUrbSNxCUjrS%2Fll6Dxw32GbbIV82%2BWrmxe0hWmdPX%2BdU5S79muUkfX%2FhriyG3H7UXCm9JOgbmfYUUMrRj%2BJtv2QG8y1iaFuQy806nYtuJggd6Y%2FIdU0FDHJaSQi3iS8PSli4ZS4B%2BIJBIPzPSlrE5dMcm4%2FwAgPiV1h%2BIK8tm2LKoEmDpPzWqGGUY8mwXK9NA5OHW7KkoCSEk7qTseKzzlydlJJdD77qwkJSl1pY66hx9aEsDXFqGdTg2VzI4PtUEZJjdF88hBSp1bKpMhJj4qCvkfoXtMZeaUsLcu1M7EkQYqqChlkWblrxlcyt5LWE2LQ0KlX3lDbwdP%2BpK0EVnfj%2BzqY%2FPaVMtfDfE3MmKXKcbdbw6yuyNDKLSwZaJkROgJAA94pTxVtI0xzxfRKMAz7iuHYoypzN%2F3y%2FdWS7ZWeKC0cePYupEdeB8bUWPArugZ%2BRx6LtwXxn8ULzFbaxy9lfO2GuFGlC1X6n9Y45WQT8zRtX2aMefasu7K6PFS7TijGbLi%2FXibiQ6j73C1KUOiVa1dDU40tMdLO6%2FETs7vOOG3L1xjmWEY%2BgSlLdy06ttoqHUpKBB223ml%2FH%2FkZjy2qZPBlzMuaLNi2VhOAYfoBdbYwbCW2PKR1l4ElX1NT4k1tFvGo7X%2FACQTFPBvCW3bi9Xl52%2FfRy5eOqWlo8fhTyfrUUePQuc51RBM0ZCwS5eawxeEWd0FIBdSlBbSONgZ3pkcq%2BjBl8Vz6AWGZLwbLLihhGA5OedJhXnoUFJT21Kn9IrZh8mmYJ%2BHJFs5T8DsDz%2B0GWP8NwLGHVBLambhtaHD%2FwC5UI%2BCBWuXlctIGMKJtafZzzVk3H7fDccsXLm3%2FcukIka%2BhCkkpM1hlGV2dDF48Z%2BjaTK3g9mZ67w9k2rGJ4I4QhToJ822VHJBG4puKO7rRuxY4xN5cg5bewnL7WEYgq2N6wpJQdQTxxA7bV0OKbs0qFvkjaXA8VC8PYxREPrCShYB9SCB1%2FKjNWPFemEsJxEPY6m5UthJQkE78g77d6h0YYNUkbR5TxO2W0l5%2BzhscOAdOBP5U2HRy%2FKwNddl7YLcJYDVzbvodaVwFGRPanQsx8ZPTRZuGXCHQpx5IafmI7itOPoFxa0WZheJXTAS226U6gIjrWqL0IcI3ZcWS8wtBQtLwLaV0VyFVLf0YPJw%2B0Xba3zaQFCFjmQf1NOxsw5Mcm7oOou9QkobWDtNOlKxU06FUvNuuI0KAgiRETUtCGnRZGEeWWUrSkpPWk%2BQ2Y1%2FKx%2FdFKWlq0gnvSsSdjJ120QPFAbxS2lM7CInkVu46A4IqXM%2BTWMTYcXcXYs4OpOwVoPQgHaev9KXPGumFCo7NVM3eG9zhdwbvCsPxnMF2VelxaFOqCjyoJBSB23394rJk8ddpDlm5Oiq7fM2C5cv0YTj1yGcYMktB8feV7fusoJ36QN9qzyxtao0QbLZwVVpjtsG0tYjYLdSCW3VA3Laf9Zk6T7bRVL8XTRFL6I%2Fj2T7BDi3LbLH35KRqLrl0pS1L%2F8AXrRZHqqJLka8Y1l7Md5eONN4RmI2euSgMjQo9idUx9awtSvo0waa0gxhOVMy2xTcO4daWVvPpQFaSB7z1qKN9lt66DdrkS0xG6W%2FdYL51weVNokj6gVfxA8v0Ol5PwrDG1KuF3FukDdLq9h9KNRdWgLT7I45f4Th5UiyetBB20iVbUPyN9jIxSWiLYzmtxphTrj6GLaT6pgUUZWEa05y8QW3C8m2Wp4QRM7fnToToOMvRq5mjMlxcHUpYR6hpAIgyaRlu7GlP4viDj69JXMp06iNp6UiVgxtvREnMPeunFL06U6jJHt0j896Uu9m%2BEGlskuH2TDKEBoIKukb%2FSK0BkzsrFS0BtwFIM8pjb3psVoTkyJBpjDYSC6hRAB9ROwMU2HL2Z5Pl0ZuYekCQlCkRMq5HuPinFtNJMTtsUxTBHlDCcSv8PbUACGnVJCudomI37UuWSPsH4nL0g6xmrEX4%2FxTD8GxtAEE3VqkLA7BxGlX61mlHltD14%2F2wml7KWIH9vg%2BKYI8IJNpcpeb%2BiXACB7AzQxwL2XHHJdMkWGZdsLhKnsLzJhr61cN3KVW6z7eqUk%2FWieJehOVfZYNnl3F7RtDj2HO%2BSSJW2A4n%2F8AiTI%2FWqj4ye2A%2FIXSJjg1rqKStBAB5niqeOug3bVloYTaBKUK0EdRO1TixbZP8PslnQVthYO08%2FpTOKFSlZMLWxgylsFXbahnH6FNSvQetrPRMAkg7R0paK%2FIMtWZIO2k%2FwCocVaK%2FJ6HgYAJOkE%2FFDKKY1dUOm7ZQAKUcHYURaQuWdAEp0k8kdPmoMUBUJ2SQACDME8UtwBlFIXSRwBt%2BdDF0wXGux6w5BiST0k04oJtPAAJURzBqEHzboBjmoQfoc%2FCCUwDzVCpxSVodIWFEbJ5miUb6KjFtWLiUkGJ9gORR42U4tdjpt8jkD6VohJJbBHKHdWkGQJ33q3kS6Jw%2FQ5bd1KUCDI7npVc70LlAdJUogx6U8zNHQB4Vg7yD7zRcmRHynEiSVCD0BqWyrMC6n1GRx9frUtlia1pJmAodRVFG362ATKfitFCo5o%2Bhi4xuTAJAjc8ULimVky06QzcYHTYz16UKx7GQmmuxupk7H6%2Bwq%2BCDEy3IGwJ7VfBEMC2DsDEczvQfGyrRiWx%2FmB%2BRU4MiaPCiBMg%2FAq1D7Kcj4N7ekg%2FFFwQPyK6PSgxJ3HEVfFEWWP2fFB56R3oXDdh8kIKRzykUSQibl6GzjESQDv%2Bgqwfmkuwc6yACSFfNQCc%2BQzcZ%2FF1Hv2qCoyXobLbB1AKBB%2FSoHyf2N%2FJG%2FpgcxUI2%2FbMg17Bfv3qFCnlDhIgdfmoQUDUmd461CCyWuwO%2Fp5NWotkp%2BhwhkDYkJPT3olBlqLHSWVEqCZUY2NW6RbSXez1Ns2RCiofSj%2FIEcttBI0pbUs94qU%2FstRY5TbFexhA%2FPeokwlBvsept0AQTJiPerDUUhVLY2SkJJ%2BtQD5BRLc8xyfpUKc36ZmWkmAlaiO3AqMCMpez4tK21CB3qBcn9ni0KIBBK449qhOT%2BwHiQOkqAIEAGrlsP%2BRRuc7Vp1t2QIgzPWkuDK4O9I53%2BOGXrW9tLxK7VCwQRsJ%2FvpQPojlJJ7PzVfbf8H7JwXtyzbLaKtSlQkT14%2FSuX5Umm2zof0xO0pH57PEbIzNniV4hslcAiYia87mmm7SOnlyR5cTXvE8mPtuec0lRbSJFJc0WsMm9ARGFrtlnUyE7dBUjNdoGeCcdsk%2BFOJtVStjWBE7QSO1aP7vjsQ8PLZcGBYVb4mEqb%2FYE7L1dD7GkZMrn2DPxWlbLlwCxt8NSlp1xDiZ7T%2BVFYn4pLosC3Vh7ogmyWZjSscDvFRjcTrskLOWsOu22i3bMqBgpUFBQVv1HQ1Ww5NeyNYz4c4dirq0qt7dlySkKgJJPaetWyY5UrIe79mW7uk%2BdbFtbZkbICh7CRUWN9rQ3myJXn2YMWtbsvnDnl2uoalMngVqj42SSpvQOTyIrTI9e%2FZ6bStYdusTtNyQjytYCegJ2pc%2FHmuuhXzRIbivgZiVnKrB8vpTAlY0AjvzSKdk%2BSLKkzHlC5w7zGH9abvaQg6gfmanJBfAntMrS7wG6aWpYdbWpI6gg%2FlVpivh%2BjywubyyQGQpl8TJCmgv%2FAPmpkYwl26%2F2Knhkl2HbS4w%2FEbxk3lipkDZfkpS2T2jcgU24pOnY7Fj1tGx%2BB42L6xtcDsLDNV6z6QG3sR1gbRslKRHxWBo6GGUVHZe2Ssos2oSR4eYoq5CYcXb4ei4cKf8A2dVCfmkNO6NMUn0bMeHuYThLf3a%2FssZw6316RYspabDiZ66wqPhPX5rLPymmafHhGrkXSrEcBxnHEYjhWGWAxVKkuOpxK6Lam0dNKG0%2BqYiPTT8WVSdh5XjrQYzrlnMFqsYtZ5mcwxh%2B21thm3QptsQZ2UTsOIM1sm6MsPIjdVsjfhpmTOF3mJOHvYknEGEHyi41cN2yVq6SNAbgduaVjtjZZW10XjjeSMLxS%2BWcbxR1N60sDUzdJKSed1mECB2pk4KgsWRV0B8X8KMt2qBfZlVdYgBKk%2Fev2iQk8bJnUIHelxjEJXf4kyyf4EeF%2BcQwi4YwDDWn0hKGmXVMEe417cdqfjwxYGSMu2mX419kTwnyvYo%2B6LvAoN%2BZCHPNUtQ6hQBI46U14K2jLPPK9IJDw2sxhyUYNiN7dWLJ0hNyVIUjpCZ68%2FnV%2FEx2LO2S%2FKWEqsw2nDnHW4MKStcqHcHuK0Y9OkaJZNF6YDhaE3zd6ptt5go0uIPCfgGtcWSEnxXEHourrDMVxVhtxAw1TgUUBU6dt%2Fikznv9HoPHinBV2PLbHLa%2FxEpYfW2WwFapMCB34pEs3pHVxYJLs2uyVmNTeHMffbhxbagkSlII%2Btb8EvxtnOzeO%2BV0bK5ScadYQywtxEnU3J4%2BK1Y5WzlZpU9lu4Om6uHQlxwtLQJBnY1phZjnkiWZaXbjDTCnFLUrUY2rTCX2ZmovotvLj7dwtlbakhOxgfu0yzNmkorZdWH3ZSG1FMp6gGjgcybVknZvREIWQk8daaLePdg84r93fbDzqUL1DcfNLlkcZBSjy0XTl3E2XWUAvaSRvttNXl2tHNywaZIXXLcJIU4p1ZB2HH%2B1BCMhbojqksJK9ISmT6hJJP1raugIv7IviBtlqUkIWpSZ3A2H1qmkXFyfRWuZMKcv7VdtbvvYepRMut7qV7SQSB8fpVvoGK%2FLaNdW%2FCC3ssSfvrq8uUuuHUtSEBqR0ISkEz7qUo%2FFInBXbG8q6CFtgGXMooct7Ry2wRtxZLr7rhLrqyZ3UokknsNhWfJBN7QcMrQ2uC%2B2957b7z9sT6XEA%2Bod%2BN6x5cSu0aI5fQGfx0JujbMWd46hKt1PMmD7xxWdzrQ%2BPH2ObhOH3LDb1xbuWnEBLYO9Vz%2FQFb0NEO21sHAL0NNdShJB9ulR5A4322RfF7vLWlSH7x28cP7jkkGfinY52tgJQ9WUhmdNinzVYezZtQDGhtKT9Sd6S4e2x0ejVjOSMcVcOalvqbH4RqkD53p8MaAg37Ne8w%2Fe0h5bzyGx2ChvVuUUNXZTGOXSlKJQHVqSnadtR%2FlWeWSx1lf3z5C1aQNMjeJM1kz5JJaH4%2Bfpgdt9ZcSC%2BXFJ2J6H396WoOW5GiKfsnuBJbcOgLGocgDYVvwQv2SW9FmWVukhKU6UCCIHH1rZVGOcG30Gm7RI0oBCuRufxflV8rAWbj2hrdtpQ0UgI1EGRETQyWgpZrIm%2BlCHZOknqJkn3rNOD9aDU5PoUZUdKikJmInk%2FwBKCOGvY1PYUYZRuRCV8wP5f31pteg3JPsmuGWwISVtqIJkDVvv370ucX6Yv%2FBbeXG7u3WkWr1zbAc%2BWop%2FMD%2BdMVpVZmk7f5F2YPdXL7baL23s8Qk7F1oTH%2FsmDVkr%2FYsrC7TCLlKUqtX8NMbeWrWgH4O9QVJk7scF0pSWnmbhPtsR9DQNPtAOSfRILew0GFpKSOZNClIXG7DVtaglAQ1MmJjY0fBDOSDDNqqCSmenWgfHoiafQsbUpCQW9z0qqX2We%2BSvt1iigovshktkCdzzA4pclTCtjdQBPE7b96gXJJbPAkAggQJgzS24lSkmKJUU7BRnn4ouRcY%2FYqy4UqjUrTyYq0HxQTZdB%2FCdUf3FRyQlquwih4QkBQ2O9RNMqxyl0BR3JB6jrRWyBBl4rmVCR%2Bv0qnGixTkykJHcCjUxcobF%2FNUmCSdUTG9GpWRqX2LpdKoKQkA70SYtqX0OUrckAaSI4maP5GTi%2FoyLi5AlIX%2FKo8jL4MxSs8qJKeYNDLIynFnyjq4WYG%2FNCpsGSaEvMUoepSpO2xiKLkwo0%2B3RvKu3UQNisd5ro8Gchwf0M3GQJ9IMiT3qmqKcWuxkpkHdQgd%2BtUSMqGq2uiUiek7VByzu9oQU0BGpACv96gSzxEi3BGxT9OagiU2zwtpgwkCoVCrpn3kEqE7fnFQY5JPSPQx%2B8EgQagu92fFnvJnpUB6MPIBiCqiS%2FQbae6Rgq3PdM1dfSJFvuKGq2SkyAU1XFjHK1TGbjSSo%2BnUPaqoXKNf%2FANGLjI20gdjtvVxWyJJuqGbjR3JSJ%2FOpKNEcH6EiwQAYSB80JUk12Y%2BSDHpSodY6VdP0UhUMxsDA%2FhUoJwl9GQZBCSdMe9RKyKDF0NxslIgbzTYxobGFDlDW5JAB70MpegJZF0LpgQIj3Aq477KTXvYuhqQV%2BpMfQ0Y4eIZSnYISNuh3qAuSXYslsqkiEgdeKiBtPpmXlkEpUoQOd5qC%2BT%2BxVLZEkgK%2BeKhQuEg7hIJ6xUIKBtUaiEioQWQ22ZKiZ9%2BtQhhcMEDXrQpI3gbbVCEbxEw2YAgg7n4qpSofGNIofOLiQlwqJGxSfah5%2FoBzaZpD4orDjF2ElKtIP4ulL6FqLbs4YfbDVb%2F4diQWUiUKAkbA9%2F0rk%2F1KXFWOx5pRaPzZ%2BLGHIuMZv9LKEDUoE%2B815ecq0eh8bCprkUBc4Ap0CFLnoDG%2B%2Fek%2FIvZpfjtdAB7KOp10OJQATyKnyR9F%2FE6pmIysAEBLVtrB5jn60di1hn0iRsYcbFtKEFsAJ%2FEiaZGhc8M2P7LEbuxWtsueegTGvYj%2FAGphmHdxmqxZQA%2FhzrTgJHmNnfjmglaNeLK0qEcP8RtBKmMdu7Uj0gKTpI%2BCP50HJjXOJObLxHXdNhu5xxi%2FCSCCHIX9Z5ok32LcsX1smeGeMeZsIdTb2%2BJYaq2J%2FwDG%2BkiQe8HmiUmujPJwb%2FiW7gXjusoabxHLjNypwai8zdp3I6xMx7GtGPzJRHQ8RS6FcX8acDtELdvrVUGQhoBJnk%2FWtEf6hq2jDm8KSeysb%2FxR8MMbQQu3NnebpLjydKUnsEjpVPy8T7Rn%2Ft8qZWmP4RlrMDTr%2BDow28BOkeWQTPYgdeajw45%2FxYCzTg%2FyRQOZfCfEnm1PWzBt21KIkdfgmly8NxVpmjH5il3orC6yBe4a24H2nAgbqUo6Qr%2FisjUl2jS5OaoSw3BWba5aKm1FtQ5mEhP8aCWShmLxXe0XVlnCMVSpm7wjDXmEoE%2BY2s%2FmAIk78b1llN3o6awRXSN7%2FDPJv2grrDcMvcLwLBMOwm5WQ1d5guf8PZcP%2BlKwFun%2FANEqqY4zu2gJzjHUjeHK%2FgTnvMi3l43nnDcRzEy0kFvDsLu7RoDaU%2Fe0pcUU9N207CtChyf%2FAPBsskXuKYExTwU8QcCxVpu3zU3hds7%2FAOa3sb5twIMkDzCqHVz%2FAHvVzhTsfjhBrSNi%2FDW1yRbvPZT8VUZixjEXFSypjDbdFulMfg8zdfvJk871swSxpfkrMPk%2BFJfljaRKsy%2BBX2esyNJs2rF5l%2FSVErvyVspnohStCI%2FzEUGWMJP8dEwyzR7Y%2Bb8Dcp4Fgf3awzPe5ksUehxq3KH9KOQFJO0dCRIpD8VNdjV5eR6kg3beBuK3rWGnKzDli0EBIaDIOsTwUhRSR9Nqn9llf8WaoeZjWpOmW3hvgwrCha2OZsqZQumVKSVtvtgGe6CODWuPiTX8qZiy%2BWm%2FxZfuDeGuHWjSU2Nk5Y2UaUoaXqS17AGdt6248FbSRzcnlvoh%2BdPD115BU6hN02PSlbSihwbduvFBmimqaN%2Fg%2BdTIfg2Xf8HLBfdbea1yrzkmR7SKRBq7OvDIpLRYwubNuzUGG2wkj1Abz8U2ir9FJeIWP4fhyWnS80rWCkhCxqAP%2BbuKR5E6R6H%2Bmxk9VRW%2BWMz2zWKuW9ishKlGeoH1NY7O%2FJyWjb3IWd7VvDmcLWoXWr1L3kfnXS8XLapnN8rxm9o2lyRnWyauGkPXLTbSD6UlW%2FA61vhPZwfJ8OUt0bPZWzlhz9w4p1xtbRSNKh1%2BK3wmujk5%2FHlFaRazuOYYLBp7z2Qop2SVb8U2tWY8UZXRJMoZwtWZbbW2uSCPVQY8yug8%2FjSaplq4dm95zdt5DaT0KiYp8sldGZeNFdk3wzNaChYdUCk7EztzVLIKn4vuJGr3Fl4ljluxZOl1kKEkHcq96rlbNC8dRg3JGxGAYh5DDYWpQWQBurmtcOjz%2BTbbJSnE1kkIWhts7x%2FvRGe1dUNDi7hWB%2BGeARE%2B%2FNFyZTg%2FQs42q9BCypKvY7GijIqqYgbcteghZT13gUwW%2ByC5hcZZZdaZDyHCCVBIKykdwI5%2BopUnbGRTZTN5kTAMbuVXWIW%2BJuOfjaW6SIPcIEfqTWecX2MVkcxHCFZbv03Djir2zSnZlxIUsT2O0D4FYPIUlsdhnF6Z6zjDr4Uq3w9uzbPdJJV771iSNcX2kIXNiu5HmPAHqNth9KJKy7ZAseRjFo4pNquyabI9Mt8%2FrRrGXyZUuMZzurEuW%2BI2bKkpBlWiNp96uLBc5fRSecc32V2y45ZllnYkqAA3pix2hM5tbZqLmzML6ri5W3dPhPUhXHvtTL4oLE3JlNYpmDEwFeXcLbG8lUGQfmsryXZvxqPTKtxbNF22HC661q3P4Bv9aU2vZrhCJUmK5xdSsFtxK1kavwCsufMqqLLlH6EcPxa5xBzWQEJJnSlOkx25peN5H0wUpl2ZcSQ23%2BzSJAidwN%2Bf1rp4ZSSqy9r2W%2Fh9upKEomETq1EjjtWiNv2Z55EuwwtQa0BBSpBMyB770cY0Y3%2BT2Rm%2FvCr0KWklJgz%2FAH70MmPjj9pEXddl0a5Tt6hEKrLOTNcIhK00EJBKoIHPO3vS8csjewWqJNh1s48tvSE6R32NagJSSLZwTCSpDUAE95%2FSlSm06FubZb2B4KvU2kJSAAIBFNAotrCcLWjyxoQB132%2BlRUKmywsMw0r8txQClCIqJWDf2WHY2ZGg7pM7bTNM%2BMr5P2Sxi1Kk%2BrSsCfxdRQyjQO2EWLRexQ2NA7dfpQP6LktaQVbslADUAT%2FACoHDZIRo9WxtAAUP1NHxQQ3UySPU2lKu5pcopbIN3mQEkRO3IPNCpUWvoGq29J0qHQTx8UU0khnBCRkRER%2BUVncfaLUEj6eJiaHiwqMkQFJOyvaabHog9QslaY1J9oqyuwi2owCTG%2F50m%2FZOKHKVQZUAY6USm0ShdtemdwU9afKVlvY7bdUpRKiiT0oRUo%2FQ5DqhuQgiYNQGhcOA8kQf0qIodJeJG2rT0Ao%2FkZDxTxBEq1DpvVfKQ8DpgAFRR7TU%2BW%2BiHxfJVAVPTmr5kaMFOIBgCD3HWq5spxR0EeZ9OofX2ruKWzjp3tDBTSeSIP99qKi%2FwDIxcbAUQQkGglD6AljXobON8yIJ5mgcWKkmuxBbck77e4qqJbEfIGolUhMdKoh593HSd%2B3SrpkMgyAJ3Hx0qUy1Fs9LCBAMzUpl8GZ%2BUjoAB0pkY%2FYUYNdmHko5lQoxtia2UwSZI4MGoS2NVsSQAQocmoSmMnGIIBHSoRqxg41EgeoT02IoeItwrbGam0LKiAQRzVpEi1Qh5JGxIAjmKpyRfNHgYED8Rneq5onyo9Le0zMgEQJiqlk%2BgJyvoyCAFJlRAieakZNgxyOxZLYBGwIPt%2BlMs0N2OUtgKgD8xxVNFNJ9i4QkbkBRmanFA8ELBAmVAk9R71ZbdbFQkSNI3qCpyt2LpaSZmVEfrUBFUpAG5npv0qEFkgKUkbRNWlfRB1Ab0lUaidoPNNpJbBcfdiwCYB0gDvNC6Ft%2FTPVKb4VpP0mKF0RNjS58sJKgkd%2BeaEOKfsiGMOgN%2BqRuf4VGaIpp7NeM7XGlt7%2BzQtFSUb2zQ3xYxJDNte76dj12j2pc532MhKNpnBX7X2Nec1iCApZSUkFKtu9cbzHcXYGOSc2%2FRwHz9dIfxbEJKG5USE9AZrzeVJ9Hp%2FDf4kHasEupTqDbiI7wRWWeJG3Y2vMKYc1hRIUOgO359KUoIoBOYE8CkocUhmIJVTOeqIkMbrCVBuU3AB6K3Gk9qJZK7Blj5EOxG9urEuNKbS4OZjffaZ%2BlP5s5%2Fx09lf4jmJKA4lxxBUY2JMdv96q2y20tEfcxKzdckrDZKphBnpVNV2Jy44zWxS0vig62lazHMyR%2FSrafsLDCMVSJjgzuJ3jramVIdQOCsgAe0mqSHxlRYysLffZSleJmzcCQAlklcn3ipxT7HRlN%2Bj1eWXp8y%2BexQNQNKwry0qP1okrE5YOL%2ByKX2WSEuOrxFvfZKTqJA%2BSBH61Uo0JWTdEQSrF8IuC7hV1iKnhv%2BxlIn4FCpVsa4tokWFeK2ecMdSzfsm%2FszspLoJP0kVph5kv%2Boy5PETdNbLjwLN2Rs0K8nH8Pdwm6VpguW5Wke%2B0xTF5EJ6loOH9PnHaLrtfAjKuMYO7j1i3hz2HtkanW3C4d%2BBpGwPH86p%2BDauLsfDzODUZxZJ8ITdZIaYRknBRh2KFwITdlpTj7g6hPJn3ArK8LWn2diGWD9G12WMQ8VcHssJzfjubnMmtrbCUlWIuNuvK%2FwBQIKyfYT7VFyXbI4ctRVjprGPtOG6uMau%2FFvDrPLS0%2BYhC3BdPuJHdLqwpM8T%2BgqNv7JBY4L%2BP%2FAtlnxazBYX7t1i3iFlS%2FwAQSmWmbPBGri7QqeD69APQlZO1T%2FPYueVtUkWHiHjnijzKrnE8JTc3ASA7e3yLdD6Tvp0oSgx8JJovkFLxeS26MP8A6iWmZcAu8xMNtOX7RT99ZU6jyVKABClITBIPxtToR5JsS3HG%2BNgDBPtVh3GGcsIey7k62SQHXba20oWCeySSSfcU7xpJyqReXCu1bOjHhTi2P4hYtLxDNOSMZwR1aXUv3YNoSOoC1ET%2BVemw%2BLFJOzk5%2FIjHtNHQbLWWMFfscMvbu0c%2B7kALQi7%2B8MKEcpO%2B3Wjl4cbOdPyJplnu5VwhFs07h2hDZSYCQNqXLAktIbjcpbKhzHlG0duVl%2B%2BUkiQkEA1gy40%2Bzs4p8F0Vzi2Urm3Cyi6t7m2kelSQYHtWeOJL2bsHkxWqI%2FdYAo2Trluht0JBAQTpHx3q9D4%2BVHkqWzlF9qjMOZfDfELjGGkvloE6ylJKUkniuX5sX2fRv6LOGSHH2aiYZ9q3C7a2axC5xF1N3r%2FaAiFI7jmuXDKr%2FJm%2FOlF01s3E8I%2FtO4JnBkW%2BBYipd6BpUSdhM7RWqOaugcUYTdPRJfFD7Ul34XWrWILuHHVqTOgAkp9pFXl%2FqMse0dLx%2FFg09aI5k3%2FqrNWyG7ZTFwVJMAFRg80zD%2FXEltmHN%2F6fxZNp6LLP%2FUmzzjtxbrt0N21jISkayDHf%2BFKy%2FwDqFLR1PB%2F9E%2BLxtK2bc%2BCn%2FUIbXe29jmkXKVKI%2FaJMiT9d6njf%2BoYye7MX9S%2F9CP8AljOwuVvFzCcSwGzxwX7YtnUJWkhW526Cu%2FDybXKz57k%2FpUlPg1TJ9h%2FiM9jLX3W0beaZUSkuK2JrVCbboV5XgRw7fZe%2Fh0x96KkLDZk6krUZ%2Blb8dezz%2FwDUMlLZsOkOWzMofRbgEEekyK2KaWjgJh2yuHnkftVuq66lCP0ok7FSSsKf%2FHPl6lalSTuSP4VYptkgYVatNkpQ3rUBJ9qOLXsXJ2YKYQ%2B4pS1oUk8p7fSjUkBJWRrFsNs1ftXnXoRuICkAflsfrV0mLSaZAMYfNmxc3LJuU6EgBb5CG0HvKRJ%2Bm9KnFo1Re9lD4phOK3T6r9%2FErfElfiJALQbHQCRJ%2Bprn%2BTFyQ%2BDj67MWXrhsJDjD7iuDpGoD61z%2BP0a%2BkPnL1ppuQJc5KVHf%2B%2FamJCnl2VbnXFr1VutTdohbSU%2Fi1EEfIFM4X2U5tmoGdc0KtkvNLuWmlKJ9JkEj681PhoV89do1fzLnCz%2FbIC3QsEjYyn9DRRddj1kT9FD5gx4IWpSUlW%2B28R%2BtSfFrbH4rT0ikMy5svk60sAlUxriRz0rm5csYo0cbRQeYsdu%2FNfbu7wMlWxCl%2FwAunxXOyZEVjTINZYrarcAS66%2B5qhJ3IpEmvRrhS7Lwykl64Whx1tsbA6diQa2%2BM3Y3mr0zYfBLdSUtSqJO8bR7H2rpwhuwZvRZFrcIbQpIJ2gTM1qgc%2FNC2DLi%2FguFTyQnoDyfjtWqPCtgu06oit9iLYV5bS5Ow3AI%2BNqzZa9GrDB9sDh8vPHSoqMEApSfTWFs1NpEpw1pSijUpJP707SabCaaozyyp6ot3LuELWpCz6htI5NOi17M%2BSuqL7wDBEgNQgJPBHNSdPoBTLmwbBVJCQG9%2B8cVHFkckyw8Nw5CCQQoEEDjrQiVJPonuH2CAU7HcjbvUstomVnYo0ohKtO3PWtBnQcYtIEKQYG29C5roumgkyykEAFSx2pc2vRcZtdD0NBXI08Hjn9aAtZH7PXEiVEhQ6Gq5LoYnfQwcCQo%2Fu8QeapxssGPABSt06SeKSQEOAeomOZ5mjVVsdFmChPI2paWgjzYR6v9qVyZDNIMyTHSriyD1kCCEnbj4NNY9xXsfJ6wVbe1IAm11QugpIPM9TUFiiSmRBBMbyaKF2QdJVv%2B8QacQyChuJSKhGhUL1QkKA3HPX6VCnBGYuFSmEx1qA8EKF8kSFFJ4kdqWoK7B4GPm7bkzRdDFhvdiSn9KklJUI7datgcT1b0gjmfeokX8aOkKxA1RP12rtrs87jfoZOjdRiCB%2BdOoaM3Ez%2FDioQaKSmSFDg96poqUbEy2dgme%2FNA4sV8bE%2FKgiE79DU4E4SPQ0RsQNz%2BVHFUNhGkehvaAoJ7VZZ8G%2Bf6VCUZBox6p9qP42DyR592VBKSQINEsYEpv0xNTGvYk7AcbTVqKRFb7MTbJSBp3E95q%2BN6AB9zbEnSlBjpS5QooHLZVIAAigL5VsauMRsAEmeoiahoGq2zGwBE7xQOH0BOH0IqTA1CY4IoeDA4MxCFKAmU7ztVygT45GYbBPqKVD3FFBaGRVIXQ2dgNQ%2FnRBC6GwBEgH%2BFQgomRunSBwagEpU6FN1AQEyNvmoBKVi6W4kkJn2P86gIvsABA%2FmKhD1IkyIPyahGLJBCtRWkD2FEnQHJ%2FQohUEghBHQkVHKwke60kkFaoPShIo0fKDYH%2FkQD71C7B1y8CClOlMcniahai30QXHboIQ4ZQFQY3qDzWbPuIhDb5SoJIB3ng1CHPLxjxxTFu%2Bvz0tohUTzselC1XQvKtHAv7XOYGim%2BR5iBOrafaf51xfPpJk8ZnCzxAuXl4ldKbUJKjyfbia85NKzs4vJyJFds4%2B%2FalKCV9iNyR9aCSXZoWef2P3cxrWCCsRzyRvWd476NCztdjE5qcS06lC0hIBHq%2FhSpY5JUaFljVoCXecmEJ1uTMepCTufciijB%2ByvliQTGM14deA6kFoRAnc00x5s8HLTK4vbq2unP2bpPTf8AnVp0Kkl3Y2Tg6dCXGlb7HUkg1blYmco12FLTC3JBbukKc7BJCopicaoXjzNeiSsWFyyQVXVwlXRJSSB8dPpRShCtPZoxeQ26NgvDrEvuoSp7D%2FvrSD6niQAjfk9JpFP0bY%2BSq%2FI2dw%2FxF8PX0psr%2FCMGfvdOhLi2kkI99R%2FOrUZAR8loPq8MsiY6ym9ezVgmHB8Shm3b8110zwNzHXmKjixizRfZkn7K9jijQdRjz621JGm3bZK3D1lRCdKdu5oHiZpUm1oi2IfZTtrZxCWcIxLEUkEBx1JkfkYFIWAqkNMK%2Bze9a37LYsTeOxswkys78bAmmxxNbobjm47osyw8Fcx2F1bX%2BZsdcy3bsR93sMOSfMA6CTCRPJJ96ODlF3dDHlUl%2BUbN3fDXHsBwDDWbbNDOF4FZuJKVXTN2hdy4nb8bSYnr0rT8l%2FyejL%2FatLlDsnGOYB4fZusNGQcOyjjr4BX51224q4UZ39BPp6dIpjwxk6gBh8jLjdz0v0aw568Pr60W069lLJbbxMrjA3CtKQOkQAY3%2FjWfL4tfyRoj5amtS%2F5C%2BWWvC7CGPNxMYst9bWtb102q2ZTHIZQ2g6%2FkkkRSHfpGfJ8remn%2FAPBX%2BesZ8IGzfnJ%2BH2ODWM63b99ep1wx6jpCZSJPpBJ56VS32PjglVyas0Gz74w5r8NMXtMwZew9zGsJcUVNOvalMvpndKkREH3rTikou6MXkQk9Fl5S8TfC7xWuW7vGLNORcQU2kqZUw64wpR3OlxvUpI6QU7V6Dxs2Ga%2FJbOTN%2BVjf4bRvt9nfEkeFmO2%2BIeH%2BP3ea8u3bn%2Fy8MubtV423tuQ0uFBO%2FIFdKM4KqF5fMzzVSVUduvCe5w7EhhuI5SazJhTDgCnbZFxpYCo3CUlI0iRxFPeNLaBU31I3ktXGXsMQ2cIe%2B8tpCilW0%2B4VG9F6oPcemUbmnG8BavXrU2rpdIMqJgfEnmudmxxb2jo44SlHTIXpu75XpftmWgYCUJ1E%2FXpQfHH6DWnYwu7rDklNk%2B1eNvTBLexP1q%2BEfo0xUq5I1b%2B0H4Ss5%2BwO%2BsFWjCG3EyVOpClg95rN5eLlCkd7%2Bl%2F1GWOaaZ%2BcXx2%2By5iGWMYxK3sU3CEoUf2gSQSJ%2FX5rw%2FkeLKMnXR9X%2Fp2eGZKc0ay4Nf8Air4RXZey5eeYoT6Vokfn2FZoylA7X%2F43DPdEe8RftUeJWY27fD8221gUIPKBCj80yc8mQ5%2FmeLHHFpOjPw9zFYZhumgVBpxwjZR4%2FWs%2BXC4K5GbwEpSULN3Mr4uzYNJYecQ40I0nVz%2FcCuHl2%2BSPo%2Fg4%2BMeHs24yBYM3wt8RZuWWwkoJESAT1%2FWm%2BFjk5JIb5eZwjpWd%2BfDLDseyhlbLYvLpjFrddq24yQuUyRO%2FuK%2Bhy8WWGCUz5dm83D5eRxiuMl6Zub4a5kTjpdw63ZSb5aAslxYSFE7FKd5rq%2BPlUqrs%2Bf8A9Yg8c%2BT%2FAIm8%2Fh3YLwVplxfn%2BapA1pUsEDboZrrYsNbZ4z%2Bo5vkmXmc1O2lv5hhraApSSTM9q03WzjfF%2BVJg1rPaHnQ0%2Fd6ekhBSCfaOtRZq9jF44btsfeuCpK9bzJ3StMAj86ZGTYM8aS7JrZ3L620aVakBO5Vz9Y2o%2BaWmZ5QRKLB4OgAqIMmJPNNjQmca6HN2taUKT5SFGRzIH50di%2BDuyCY1cWifLauPu4eUSEylUcHmP9qCT0VK%2Feym8z3FmEOM3dmUtIMpcZ3Sn6HmsebY3Epdoq1WKYZbOK0XywszBPprDjxW7R0HkbVEcxnMd22lwMJ%2B8pAJnQle3uJmtigjDklLtFEZrz7gyFKZxJd3YPTsWitrf6naqk4rsZjwyl7NZs9ZnyM6lxOL3md0BUxcW1uy8AO5JUD%2BlNajXZPhldrZrPij3h%2FdOhGFeKhtlnYIxK0Taq%2BqlJ0%2B3NIeKLHLK4fy1%2FsV%2FjuRMexdpTuX8YxXH7cokuYYu3ukjYxs0uZ%2BaW%2FCi%2B2bYeRPjcIp%2FwC5qjn%2FAC1cYYpbGOYtmfBnwTJv8MuEJTJO%2B0gj61g8r%2BnU7sW%2FOldSjx%2Fya1XuA4JitypFtnjAnXOSlT5QQeIOqDWKXgp75G%2FG5NWo2ixcseHF0tbTlte2N2QZlDyVCPz5qR8FJ3ZHP7RtBljJ1zZNth3SqBMgbfNaYxS6Is8UWnbWwQlIUXEgiNxzvWuFIr5d2z66vC0lKQoohJGx60VX0GmmRTE8T9JlUmSiSBB95p6erZccKW2yHOYmVuOEAoEyABuOkVknmvoY8iDFh5rwnzCCYBEnmksuOSJaeWrBT7jepAJOwPf%2BlMxwS2KnkjWjZbKmEavLBZgyIPMUyzDkmns2Ly5ggWhlJbA%2BeeaZAW3q0XBhWEDSkBtOoH52q8kqF2n2S60wxskaEoUBvSwuS%2F0kot7ANKT%2BEq2MjpUZXyfZJrRopExqVvtG1VRUZJdILtMlUkpSmN6NQb2VKdjtDIQqTCR8%2FwAavjXYJkpErJSEaTMHtS5yS6LirdDV5zSHIhQO0nihjH2NjGgU46BKSoAT06UtybCBzhkbb%2B%2FbehLS2DVkqkAbAyRVST9DkhKSpIAk7%2Fypbv2WZ6fwjdO%2B470JBcIVp9MTNQmxw2FgnUNPeCTR82E8yQ4TOo6vxd%2B9AC5XsXQqBuOOvtUILIJjlO28cCrUqILoEidgSOlGp%2FZBQk7EFQnpV80Q9KoWd0%2FBqc0WkeJUo7ApJiKvkhrxnus90q%2BtLk12C8f0YlRBTuPcClqSatFrF9ialnc7E0MJtvZUopIwLgkbEUwWdMXVxHG%2FvXo49nmYtJ7Gq9twD%2FtThzGSlDfaSD%2BtSgPkQ3JJOySd94qi1NPRj5e8biBvtUCPNAC4%2BvHFQh8kA8AzPaoDOTW0fISSev12qC3JtUx0EaQCAkdNjzRKbQJ8G1DcKTB5jepzZD4JUeVk%2B0c0SyEPiiZBSk%2Fzq1NsqUqEVNgRIK%2B9XbA%2BQautlKhCY%2BtEmGrfsYuMyTLYKupJqP8AQUotAx5pUqSZMUmV%2Byhk4gJJChO%2B9UMhJJUxuW0iRv7QZqhhiW%2BQSqahDNKABJBgfwqEFQhI0nZJqEf2ekAAkdetQXKaaM0jcA7ioLHCBIAkpqEHrSExpLalDkb9O1Eq9kPj%2ByIgGfY7VHXohilIkHlHSetUkBORkVpAKtRSfaowYNmHn9dRUPc1fJjRMLBSdiD1g1HJsgi48IISDqPtQkAd%2FehAXMFI5M81A4TSRVmZcUSG3CFExO%2FMVBpqb4hY6UNvlax3iahTkkcw%2FHfNqWbe8BdUEwVDfYCkZp60VKPLSPz7%2Fafzcm8ubxJutSZUNIMbd6835fktOiYMdOjlRmO8YeuXV6tQWT6ZnV%2Bdcqbvs6OHI%2F4%2BiJFVsttYUpIOrYgb6e1Ujcsi%2BjNtq0KFBbYdMSSRx9aCUbDjkg3uIi7gNjeiW0gkgwlJAI%2F3qKH2MyS1UFsiWJ5PQtLi1eeCBuT0qJRFKMn2iB32TbspK20rcIH7xE0rkV%2FZkNXlW%2FS4Qll0Kj1ACdqZGehWTw5ByxyxijZbWm2vCmARCfxb9qqUrGQw16Lqytkp7EWkpvdbZVBlaACB7VQOXGn6Lxwvwgt7hplL2I%2BeSISgaRHaVVTyRIvDdWO8Q8GM026VG3ubp6ybSFJYYCUiP502MkNfjOtC%2BAYLiWC3LRxLw2usdYbAKkXClae0kIAP61baEcJfRtJknxCbskWibbwmy9l1TeyHU27jrk9wXJI5qWh2LI09wN38k32I5otWnP8AtEupUUrJuEpSFcbIE%2FPSsbj%2BV1Zrxyg0%2FRZl94XLvnUXD%2BG3VqkiUqFqLgtiPwoSSEp%2F%2FhNaOUn2qG4ctL7I7b%2FZ7wxIuW3sWzM2X5U5K%2FuylbzEoA0gb7E1Lr0M%2FuZL0H8O8A8qZbtGnE2lxZW6xsptwFb%2B%2FwCIuL1LWd5oowgtvTJ%2FcyZKrPwUs8RbRfpTidsw4sNpSvEkoU6e4WQjSPcSR0mmxjG%2BxUvMrss4fZyynaWn368ucfxG70HXZ2CmltSdx51zcLlUe5APY0XwwW0Ij5Mpy30V9nVHiXlS5bbw7DWbvDkNy1YMYazeq7aS4k6Rt7AVM%2BacemNx%2BJ42Tf8A5KnxfPmamWkf4p4c5LXfaClSMUw9DrjY%2FwAqUIUBM9OKVH%2BozvaTD%2F8AxvjepS%2F2ZrBnvxW8WL0vqRk3wFwHC2QpVtbryyl9%2B8Vv61hStCUjfpz0rRHz2t0gpf0vxpRauX%2B0inMq%2BGviR4w4oy%2FmXC7DEmnnQUYdhmBIbacO%2FqAaSEhI9zQzyyyvdV%2Fg5%2BTxcOKPHFJ3%2B2boYN%2F0%2FwDBFhl%2FMN9a%2BH1spKXClu0SC2f9RSFR%2BZp2PDXToyybj9v%2FAHNz%2FDH7G3hxg9xheO4ZjGCZpxxoAC6adU2em5QkifkiupghfsL%2B7tVxOi%2BSfDrDbK0Ddtcfd7sgAsjTE90nmurijSM8sn%2FUi%2BsLwl5dsuyv3btxO4kf5feKNzQicl2kVxmrw0t7u4KrPDytc7BUfw69Kz5FbtGzFmjW2Qt3KeI4Rbrcu7QJaSTCAQOnU0lwo1Y5RkytLpF8cSdFvh1s48QIClFQSPf3rLlk7NiwQq2CMew968t3Pvag04OUoEJSPekynrY7DgS3A038avCVGY7K6DeDW93fLEJuQB%2BHfb25rl593SPWf0vz3jq3Ryd8UPs6v4c06u4silKiQAER6up%2BK5s%2FE%2B0e78H%2Bpqa0cjftN%2BFVxl9r73ZMONthZCxo2k%2FwqYIRi6oX%2FXPJk4Wim%2FB22urK8Yurp2VA%2Bkf1FI8%2FGpQ4pHP%2FAKN5LUueR6NvDmd1m2M3Ckkfvdto2rz%2Bbw5euj6B4n9Qd3B6NrvCzxXssMwy2tC82%2BtRGxVt%2FwA1kw45xkqR2s3mRnjpn6JPsmZ%2Bx%2FxZyfZZfvHQ%2FYMIShlSNnBsAAV19T8WTy4qZ8m8rj42R54%2FyZ1g8Ncms4W7bKTYqQ%2BlISXFgEj5P6%2FWtODAk9Hg%2FwCqee8t2zdbCbC7YtGktOodVpCoKBpO1dqCPHyyKToxxXCcevEpNhjV3hkGFJSEKSv5CgYq5LQ3DkjHuNmeG4VdqKWLwtOEGC4n0LUfntUiqQrNki%2F46JvZWCbdSNSbtC0ndQVP1JmrM6nrZaOC3qC0EupU97Tur4FNh0Y5496CjN4kvFAYeaSTAnn%2FAGpsZUKarQZcCXbc%2BYsrbIHpVvNN0xcY0yE4jg7TwdQy9dsgiPKQ6QjnmOR%2BdKmvTDNe864M7ZXCnEJRIBKdSidIntXPz4r6H450a8Y7ihQ4sLd3BPAiKXCPoPnsp%2FM2bX7Vl0B5SyOCrkUxqmRu3o1wzR4xYth63mnH27tgyPLfbS8kj4WDA%2BKF5Wg148ZdopXE%2FGbJl8PuuPZWsmm1%2BkuYfcLtVgdSEK1tq%2BIFA8ykaIePKPTKdzE34T5iQ4vCc8XOWLtUw3jVoosj2L7GpI%2BqRQfj9jX8nuNoorG%2FBHxDdbuMXyWxa5ubQCtN1lXEmrpxBE8oaWHU8cFNLn8i62BkWBL840UPjH2hvtNeG2IP4Pd5ux9y2bOlzC80WQvEjf8ADFygqA9ge1KflTw7aCXhykrxS%2F8AP%2FD7FsL%2B0B4eZ7dbtPGD7P2VF3a1AKv8t3CrJzfk%2BSvUgx%2FpUKCf9VhL%2BcRmPDkx%2FlSb%2B1a%2F46Nh8mZB8A80FCMieIGM5VxA%2Fhs8wM%2BTz%2B75qSpB5%2FzCnYliybi6KlmnL%2F8AZr%2FP%2FwDC%2FVeF3iTk22buVNDFcM20v26w826nmQQSCI96d%2FbVtOy1XT%2F4Ev8AGEgrTilj5G2k6UkGfg1fJrTDlCK%2FiwRf%2FcrvUbd1Sp2AIAPPWmWi5Phtlf4lYXOtwtpUlIEhPYfH51nzfoGOW9IDt4Y%2BFFxTajIjfgD3Hes9hx4p%2Fol2EYe4SjS04RyRtP51LJJb%2FRfuUMKX%2ByJQsk7yOntzTodCG5eja7KeF7IUEExHP9KYlZHNmweAYZo8tREq20kdNquLp7EuHstSwsUhAGgpjoelH8iAcN0SVm0SNPpjtS5U3sFxoOWzCUzpbIJ6HrVNL0MhNJUw1bMobUCQIjrxRQkkLHE6QJCvajeTWiNsylKxpMxxueKTKf2FCCexFxxCUwDO%2FU0py%2BhijXQHuHQSQCr3k1ObHRkkgU876lQUgUBai2M1unTGrT7AdasLg4sSgckH84qgr1RikEmZJHB3pbgUxYaAZAI9pquJcWk7HAAUQCIHUT0oWkHOSqhVIAOokj3FB8gsWTtE6lJmTPP0okyC5E6laSOnNWQzSCQCQonpI61CUxcEyZBTUIZ6jETI22qEPVGUncKnkT0qn0HHj7EyqJKYIjaO9WU9dMSLpBid47cVU1YKk7PlLBSVHbbeNqTJVodGVjYvQSQP1q4umBKLsRU5vyBvNHzRXBnUJekiFAH5r0y7PLQ29g9xZKjBSOOtNDnN2NFApidPPU1BZgepInftUInTQpqB3Ij4NQZ8h8VJMjb3jmoX8iPtR4GxqASlYqEIBgnce1G1oFCgQqSRHz3oCCvlRABWJ32PNQHkvs9LRO0K5qWTmhMtKA4Vqq0yc0eFsgEqAPxV8r0y%2BS6Yg4gEmNzPbpVqT9EQ1eb2KtO3xRxYTlfYxW2lweqAf72NW0n2VQGeZ9ZPB96S0RoYlG433FUWpNHnBJURsORUGfIjwFIASknnmrK5%2Fs8WqdwSY61GVKd6R6J4IEfO9UALNoK9wQKOMGyCyIBBkd%2FmgZByXQB6TAPUHn5qEEXF7%2FiBHXeoQSLm8Eqme%2B1QpoxDhJIJgE7mahZ4VqMcjp81CrMCtSd9Qq2g4xvoZ3VzoSohQUeTvxVBLGQPGcSS0lY1J471ZPj%2FAGUJm%2FMKUIfJcIAnk7k0HH9grG%2FZpV4pZuSzb3BLqe4E9PepGVStlSVOji99p3xURZM36EXydQQf3pB9q5flZG22Mw9nAnxxz3cYpc3M3qFlZgqHavNZ53I6WPxado0wxDE3DcLStYM%2FvH%2BMVnk62jXGAOXfoWn0JWrbSYPFByYx41WglaXzYKQp0AgACR196OMl0wJRqJNMOeQtaYUFL32Jjtx%2BtBNy9GrxWqv2HEYY7crBbh5s%2BodRB4mlpSTNVhJvJty8kf8Awg4NyApJB%2BJqpzT6DUGO7fJ1jbOpViGHJZIA1%2BqJG2%2FelBxxy7onFllPJt62geWEJ2kSQU%2B8c1al9DOC9lnZc8NcjOLadcu7xKjIUgLUI7HmmNLjbIsUbsurDfDTItu0k2t5idy8DB9UgnvSJZEuthPDFlqYTlnAWrdhCSsrSIClCSR2k1XzyKlHj0S7DsEwmC2jDmblKgPURBP84oH5bi6YUoxXsmOEZLwdu5Zu3WEMFJ1ABZWkfrTY%2BbD2zM6L%2FwArYrl%2FBmwmzt13F3JSD%2BIj3EHao%2FMj32ZM0JSL4y87Y4uk%2FwCIpvGWyDpCRp1D3UVc1twZFPsDHy9EmusAy1aoD1ngzCbmNIUp4uOEfMkD5inSiltD%2Bcis8SyHgmL3yw4xcXt36VOti9WlDQ5hTgOocfhEUurIpu6otHCckYLcPW3n4nZPXEah5jyw0320JA4A9%2Fk0ajH7DlKl0ELzw%2B8PWblp%2FGccxDMGJgFxDFrbkMMKP%2BXUdBV7kEir%2FH2wsfmZ1qqX2BsatLPDWX3LXAtVuGiEhRSkqPvpgnsSYrNkySj6L5ycqZz18TcTFrfuLur%2FACvaB5Rat7Gyt1IWtZP%2BYEqUkVy8zyP8maFFJW1ZQ7eF4JZXrl9mDNeDYk00SpdsX0M26SeAuAVqPSCUiqxzfsVLyJPSVF4ZWzT%2FAIELJy68YMOynZvNJU1hWGBTKS2OAdA%2FD0k10%2FFzJLsz%2FFbtQtls2niSy9jSDc%2BLWHs2xhCUIVc3CQDzqKk6fpWyElLtly8WVXw%2F%2BDbjw%2BxTC8Ns2LhrxFXjDDxOgMNpaSs%2F5fVua6vjqEEt2YJSd04%2F8mxuWcduX%2FIfFtfW1pqMfeFbqg%2FiBjiujG%2B0Z8ifReeG%2BIbrTaLdlp1wAEaysaYp20rYC8ZMn1tjRuGE3V2422mCSpRG1D8iFR8dt0RjHXsLxa3W4q4dXYjbbbURzFKbb7NOPHJdFR5jzXlbArVabJli2AGlJWsanT7Dmk5JR69m7H4859so3MeYrrEsMevAm3w%2BxUSsOPrjV%2F8AqjeuXmk3%2FhHY8XCk%2BK2V9hOM4dmhxyw8y5vW2oS6tIhA7gAcT71nxZU2dDyPHa2RXOPhjg2MpWRZqcKwUla0k%2BWnuB%2BX5U2cVLod43mTxdHKj7U32QcQzPgeNIwWydu1KQryiUkRt9Z7fpWbJ47Ss9T4Xn%2FNDhI4QX2SMbyBjl9hOK2T1neNLUkp0EHYx1%2BlY3S7Dnj4qkFri7uTZtoV5kHcSaS0mN8ec10Xj4EZRzFnLNuEYJglr94un1hMIPMe9Lw4W3o9N4iyKPKb0ftI%2BxF4OWfhjkDBGH32XcRW0FXWqJ1QDEex%2FOvbeFiccaPnX%2FqT%2BpyyZeMVo6QZex%2BxafWi0V60SCOYPuJrbwSejw2XHKXZaGG%2BIqbcIZLabhYO6ULOr8qJTowS8J9k3czWi8YFwhbATAKpVCkj3FMc9GScNpID22a7c3gH3xl1qfUEEEj8qD5S5YdWyeIxNh5lt21vn0AwT6eR2macmBUvol2B4lbuaAi7ccWeWlH1A%2B1Mg%2FQrInZZVo4xcpAU4p4CPSvYpPzToqzLJP2GLd1poFBfBUeitjH86tyfQE210RzH3xYNOXjTetsckbEj%2BtDJ%2FYSWrZQebM2YXijT9ihlvEjBBY1hD6Y%2FyH96kydiY5bezUrNWFpvxeXGXr1y8LQJcYUIeZ%2F9kc%2FWKBr2HjnJyr0ahZ1xS5s0vs3CiHE%2FurO9Kzx7NcJJTSNRM8Y0hbTilFGvcqgzFcmU5dHVwxt7NQ874%2B2jz1NPgiI2IJHwKzZfIl7Q7H3ZrFjWcb6zfeDN7chkkygmQf6GsL8iTdpmmMZPa6IYPE1xl4P3gVbPAgpuLdakuA%2FTcdeDVx8mSe9miM6LIwz7UXi01bJwoZ%2Fu834GgAfccwWzGLMRP4dF0lZHH7pFaof1XPBUuvox%2BRgxzdtV%2FjRYeAZz8Oc0OIOdfAvK9rdqXqXd5UvncKWmf3vu6y6x1mAE%2FSr%2FAL9ZP%2F2RRmh48k6hM2Byx4ceFuMtMv5N8QLjA7yd7PNFr93mZhKbpkraJnqoJrXhWH%2FQ6JKOZdx5IvbBcH8WfC9hF7aLxSxwdaioP2zqbmxuJ%2F1JKmyD9DWtRnHp2I5R7vZO054ynm1o2ee8uIsb0jT%2FAIhh6I9XdTU%2FwNMU%2FTM2Vzk7I9jfhC9c25xrJ2LWmY8KAkeUTqb9ldQfYxQfFbtMOGaaVNWVsxh%2BJ290pm%2Bt3kOTpUlSYUBSJRS2aYzTJIzg7DoSSypKjBIA2PSaqLVUOi6DmHZZ0XLZSgKTMGDA%2BtXxktoueXlovjKuCKYWyUtkogGT%2FOix5LMkpu0bO5dw5TQalMrI47%2B1MTYE5fReWB2RQArQNJ2idqoib%2BiybS0PpCFAERz1qwJyfQbQxpT6R6u8VApRSjofsAAbzqmZNQWP2yNQCtj%2B6agUVb2ONlSSpJ6cTUHLWhsvUmRvpHBHWkSdsqTeqBNy5q2%2FDVFgp5ZIAJM1CDJRURBVr9oqqGRY1Oon07%2B0VOhgs3b6khEqkncdqloXydi%2FlaDA9KfbeanY2MW0eaVJKSBuNz7GkMjjXZmCCopO209vmluT42OvVioIkGQTFBGdegGkxVB4A9J%2FSmLJYDiOUIBkDT%2FMVMkmlokUm9ixQRAgAzI3olfsfJ6M0GfXwDxvR8foV8rFdJCT0Hf2quLBc7MFJIKiDI44qgbQkpUJIJkzuKpphxkl6GilBIJJJ7AcfxoOfplNNuxJSysFAII5NBKVhw12NCvZU7RzFRK9B8kJ6kagpR%2Bk7UXxv7B5o6freSlIiCYr1p5f5RopaiedvcVBcnbsw9IMqEj5qFKvZ4lST%2BE9eoqBOS6QsUACB6d9jM1ARJSSnY8VCGSTBEiahBUbiJjpV2QdJBJB01foByQ7QZ20wY7zSpaBSTMimIIHHG1AWoo9I1GTB6Va0TgIrRCeaJSBjG3QyXuU6Umf5U2L%2Bxzil0N3UqJ9I9XE77UxyoU5sYvJ0SkBPuZqRZan9gq4QFEkhU9qCcfZfMGqbgSYI%2FhQBJ2NyiAUxB9hULPEAAEBJkde9QODrZ4lG8kyOeKhXFttmXpB06TPc9ahJQ1ZkFLQdtQHxzUBMwviQY6bUdohmpYJBSlI7yKF1egWjAlK4CUpSruCaiVkihLUJ5iD8VbVDIwbMdaeJIPvUtDPjEHX20bx6jVFNJege%2FeqhROwn%2BxUYHNkevcS0h1KjEDvvQy6CjJt0VFmjHA2HNSgSN5mqh1sYasZ8zSGk3CtfpgmpTF%2Fl62c2fHLxETaWd%2Bty5BISdgfms%2BVq6fZE2ts%2FPn9p3xOuL93EP8A5ai2CdRCpjftxXF8rya0jdhx8tyRyfzXmFV5cuBa9agZBn8Q%2BtcCUl7Nqj6RV9%2B55plJgah13ilt2PiqRH13LzSlK8xwgDfeqoVmxt7iOrbEXNahr24M7VGVjhL%2FAFFg4HeBSkandCeZKv5U2MkXKNF5ZbfbCULUtsbbHoDVTQcH%2By37C9sl2qFeZbc%2FvHf6CsM%2BSWjr4XTHNzY22IKSFFtAA0iIiKy%2FPJaOhGRnh2VcGS8l24fbSuPiT2FU8smSUvssnC3GMNSkWaAowN%2BSR7UxSnQqGRPRY2D3tzcFq4HlIJVpGtABNNUk1TGcGS0Y8hl7yXFNPPAbhJ2Aq5RVaATT0w%2FY5kQw2kqdKZOmEEqKZ9qzZI2hjxpxpIPox951wGzcxFsgj06Cfbp061ilhlQtwcVtIuXKGacRUWfLw6wddB2W%2B3H6961eJjkt0Y5Y1ZtXlK4GIpZVeWlpeukSQ0PLbRt25NdvDOL6EPGy%2BMKZwq1t%2FwBpg1qhxQHKdZUff2rXqxcscntkgasGnGWUa28OsiPUkISyp5U7%2B%2FaiivoXwaJKqxwtH3a3urjD2mj%2BBJG6vlKYn61JRjVAvkv8BNvCrNlHmhvDGGUjVIalR95OwpDUbLjv2UVn%2B2usVt37a2Fnb4UmVLTI1ujstfKZ7Csea6HYNdHKzxkyhcu3V8m1escDbbKhNoSFFPbzlGR7xzXCyeVJS4pHZxSfHZq7Y%2BFuTcKXZvYziF3f4WgffLhN3Ck3SyZHp6pniexpuOMntqiss21%2BJJ7PIFz4g3V1jOWsJYxDDbdYFwH7hSkNAcHSBxsISBXWx%2BMu2ZY5oxe3bLMwLwQxK%2BvbNVpmphvF3lDy0G0BFudtkNkAAieTWiMN6Ll5TW2v%2BDf3wp%2Bzl9oO4zXg%2BOYr4oZjwDw%2FswNFmh1Kl3YCdpQQYBV17V2%2FD8PJ3J6MHkf1TAv9Cs6A2nh%2Fi1xZJZfx%2B7v3VEapWNUTxtwPaunX2%2BjBHyYd8aLbwTJmEM21qy%2FepduGky4lKxyOhNM5L0Knmm%2BkMMxYJfY1cNWlq9cptWx6W2VGTH%2BY8RSMkJPpGzxfIUP5D3D8m4xeWy2rx1xhkJ0oEzA6mrjGXtEyeTFPq2QzG%2FDBq4u1uffW1tp2SSkfi7z%2FACrPlh%2BRrw%2F1DitogGYPDTBbWwuLa7uF37xELccWJ%2BB0AFZckE1TNuH%2BoSbtEMwfBcDy%2B2pDLdui3J9WlAhZ%2BetBiwxh0bMmbJkWxwu7eQu7unEWqrbcMAAwPmnaChiTQjaYPhuOYVdMO%2BW4pTZJJSJCj2HSijjUtC5ucJJxORP2uPse5YzTieM4xgloWsUILinEJAQtfXUY5rn5v6fa5I9h%2FTfOSxtTVs4A%2BLuW7zLWb8NyyUvtXTI0uISdjBiPmvM%2BW3F8Wj3%2FAP6f%2Fpvy4XNRs69f9PXw4sbBxGYbi0Q7euKCWFqTsnvua6%2F9Lkjo%2BfhePBT0fpN8NHrhq1tWChbKVJCk6Fkpn5%2FWvXeLkjWj5F%2FVcEUrNo8EaLa0OLStpazJVMgj%2BdalJM8fmzJ6Ja5Z4U24bhdy7b3JHITB%2FMUTivYiOab1WhdNwsJUhvHMTeSBCkLEEjqAdpFJcqRTn9xHOFYo7bXQQhDZQDsQdB%2Fv5pMZNO0JzxuJdGX8XBSS64t0E%2FgURPwDt%2BtaITXZzOL9lpYPcpulITapLbwEepMOJ%2BOhpwrLGKVstLCHnwUF5S1rSIBKQkn6VoMk2mtEnfWVNpWAhyDtKTIo5SsRz3TKzzbndrB7dwXLaVIjSUaoJBH8aCw%2FZppn69bukqxezS7iGFajqdaJRdWK%2BmqOm0A9e9Im%2FZSx27KxexdjGQ398vbh%2FEmkw3idn%2ByvmB%2F%2Bkbn9qn4k0KyP0MliT77Kw8Qb3D2cOQvxFwtGLYGv0M5hwtoKSO3ntj8JHWBNE4NlSlW5%2FwDc0i8T%2FBrE73DLnMvh1i9lnDL5OqbdzUpA7Hqk7cGKx%2BRhpG3w8k29fkjmD4hXGJYTdO2mKWFxY3oKvS4Ckk%2F31rl5bSpqzfh82GT%2BBq3mHES6p0hYCgdwT19t65LS7SNLUkruitX7p56QFqKzzB4nrP0oXXoiyckHcAwp991t5tRTvMgnY0LGwxtm3mQcNeWLdN0ySpX4lA8e1bMWOL7FZ24ukjbnLeBo%2B7NqUn0khXaDHWtuKKi3QHyvpl5ZXv8AGsuOB%2FAMTvsIUR6kMLhDqeykbpI%2BQa2wy8U2BkcZfyRYTWMYBj%2FozhlG1ZuVzqxHBYtXvlTJ%2FZL%2BRpNGvIUtNGOeFx3AkWBeGV8h%2FwDxXw%2BzOMTcjUWQTb3aRz6mFbL4%2FdJopQb%2FAIsWpLqaomduljFy9h%2BdcAbTepPruWWvLWDMSpJ61OH2Pc0%2BjC48MrZ0G4wa5bvLcwQmfUPkcilzj9BOf0MLTKd3ZvDz7MgEn%2B5pXCV7YLk2W5lrCIS2VNaZ6neNqalXRV0X%2Fl3DgFNqKASI53JNESUItWi38MYSlIUG9pqFJ2iY2qQVBRBkGBtxUI47sJNjcJVpIPFU3QrI3Y9S2pJnUD%2F%2BrzS1kt0CKoUlBSIBJJiKYy4utma1yPTAPBJoXJoP5EJKlQ4A2ie9KbsNO1YKfBKxMA8QTVNlg5aCo7d%2BSOtA5hKFiPkgrlRBT13qfIUk%2Fox8hAOpIAMwd%2BRUcxqTa6HCEJSSqATwd6WB8Ml2jFyCdIn%2B%2B9QdCXFUJLSCSdweKpq0S37Gy1BMFJT%2FAF3qR0ihJoEqKSoE%2B44q7IFG0kBKZj561CqHjYUIUJI9u1QJQ5aFogiJHUjvQLJfQzIrV%2FR62QTAg70YodJkpAI29qcqLTXs%2BXqB3BG%2FaqUEwk4%2B0M3YjqJ9qW1RUmn0gYuUjYnbsKFJk%2FH2IqBM7Ez7f0qFNJ9IbqJBI3JnaiSZFB%2FQ2WAAmRwajjRGmjpslxapkEj3616jizywoNxO0%2FPFWoMhmQNII1fJq3CuiHpRPCge81agQxTts4Y%2BKCmWlvZ8VbFMhQ6E1RR8FFJMCoQVSdQIgA9qhBwlzcJI2qULlF%2BmO2iJTIUSe9LnYDv7FpSQCNNDf2XG7Pgd5kfnRMceKGpJBO29UwOKEVNpBBgn5ootsCTGbuxMHvxT0gQc8DqVvA4irh0Mgl7Bj4CQVAhQH61J9BShrQJdUNOx3%2BaWSMRoU7wTA5%2BaoZCN9mBUEJO8GO8ioNUUujHzBsQsnfioW5fZgX0gAKUkCrj3oFtCgeJP4hHzxTGpEqJl5w4UTHT2q%2BL9gVH7MVOo5Cdo%2BKHhZaklpCSnhO31irUaI5%2FSEHXxGkr0DvO9XormxoXUap1rG%2FOoUudXoC7Gi7lISZUT70JcdtWBsQvglMFQCuB1qN0NUU%2BivMWxhLSXFBYJ32nc1XJEtLoonN%2BPoS3cS4FTwSeKXN7Ky21Zo94rZvFsxdFT4KQCTB5q%2FlVGnHaVHHb7RXiSsDEG03pDABkhQG8HiuJ5mZ9oOGJPbODXjrmxd9f3iUvgiSoFJ6%2FIrgzT7Y6ndI0mxLEPMedLi%2Bv%2BYk1la%2BzdFAR68Z9ZK0kTAChED%2BdRIME3N2laW0oWQjsCZFUV0YNvpBCVDadyR2%2BatItMk2FXWtw6XHAnTIHG%2FShl1oKK3TLKwO7uUtI13Dix2n8qdCzNLsuPBhdLbZWi6cKlGRG9BkRs8akqbLiwexv3iyXbllaCI2TH%2FFY%2FjTdm1TcUS52wdC%2FM1NKTwYj60xRaf2Vcu2N1v3tssaWNakp2AGw%2Bv86yeRjk9oqPeh1h97nvEXzb2anGmIOyUmY6dKzJzQ5QkXXljIGZ7h1D1x5iioCNtz7%2B4pyzT9sJY3f5IvfAsqZjt1tttMLcUhO3n28aQT3%2FAJ02GRN2w5paLxy5kvGnSo3tknygICmyEgfQ0Lyyv8WZ5uieWWTcGYWF3buNsJQon9nctAE9o08UcIx%2F1sfGcmtFq5YYwlh4IsXcx3Lw4BKTp%2BsjatUIxT%2FEz5OSNhcHtGn0IuNd826CBKdJKZ%2BetbMUWZnOS7LJw7B7GC64hDTn7y3FBS1dpUd5%2BIrdETKV9Mkdtg2D26U3EMoRuElKBqd4n1Heq%2BOPYpqwbiqrEFShhNq9zp8xer%2F%2FAJq3BPsijRVuM4Bc5oS%2BhptFvboEuuOnSy0I9xE%2B1ZMuByV9GnDm4PZpd4r5QsrRC7TLLWGNuEKD%2BKXzClJA%2FwD9dgkAn%2FWv5jpXJlgxw9HU8fLzZTbX2eMq4DlZ3PXi3j9xhmW7t8KSkJ1X%2BOqE6WLdI%2FCk8lUwJ34AG3D4sa5yejF5Pm3k%2BPx43fv0gFa4%2FiD%2BIYLh2TsAGAZZaX%2F8DCrQOBLKCOVqBlx0%2FwD4ihtvFPir%2FiipY1FcZy39m93g7lXGcIsXs15o8P8ALOCMgj7oXG1%2FeHuJOo76f9RiTXZ8bBrk0jl%2BXmhahGTsvjCfEfE8wYi5avWSrZpqAlFsQEFPuVDf6GtHP7RX9vFbuy6sEvwGFOfcLnW5I2XJO%2FccUyMk%2Bi%2BKXQ7RmJlvFGcHw%2FBbVLs6nXFL1KT%2FAO39KBJt7GrC3HldFh2t9iKkgsW4baA6wEmeeu9MqgGoiBzS1Zum2uHQXIICeAfeB0onJv2VHAvREMw5jcSw6q1hlvqtMEaiOB3peRLs14PFUv5M13vrPFcxYs9d4v533DlKCSSpPsOgrLxtnchKMFxj2QnHsVukThuBYM%2BlyNKQ2n8A%2FwDY9figkmjZhxf6pMK4Jg604c8t5tYfabkref1FSz037VIr7DlkjZLssZeDOG3N07evXQVq0wNlK557dKfiQrNmXSAGOZXTieFYmjEWEJtQhQSCNCZid61N1sdDNTTR%2BZ77SWX%2FAA0sPH%2FFv%2B4cVw60uQsFKEqHpBMAnfn2rwP9U8WU81n6G%2F8ASn9SxQ8Lj0zpZ9ltvKjWBYajALm3VbpCdOkhQKhzuODTv6fSfH2cX%2BvZr36Ou%2BQ755pmwf0pLbaQHN%2F1r1OFtI%2BUf1WEWqTNpcLxZu7trdk3Dts%2FH7JemUjrsa248irZ4vJip%2FomVjjFy40LW6NupwAgrUdiOm5%2BlPeRGdxp2mMbzGbVi4TaXzIt7idTa0zpUnuOk%2B01nlNWXTfY6ZxNTzhXZv218wNtbaiFD2UOZqckMotPLrhuA08iG7pB0uIUI1p%2BnWnwSOZmbL%2Fy620thAJIcCfQZgz2rVFUjm5p6osmzuFpACtSoEkTBSK0mdx1YpieLJZtwRdBDxEJWTA%2BD2qCJr8jWvPGNqzRaXtg6jy8bYBCmjt5yP8AMmeTsNqg2jTe7zHi2Xr9V5h915hEodYcGpLiD%2BJCknp%2FCky03RrwKPTK5z%2FZMYhhC885PU81ZtEG%2Bsgf2mFudD3KCeFfzrPmxtq0SGRqVS6NfUfaOzLlB24axJqyzRgbqQ3c2l5sXm%2BoKgPUYnmaxY%2FKnGWzR%2FaRk7jLiQj7hlHxMxF3HPsw%2BIV14a%2BKoHmvZTxG4S19%2FjkWrhPlvjn0ncA8VtnkWVV0c%2Bfj5YSvtfadM1jzz4t21zev5I%2B1h4N4jlnF0LUj%2FG8OtSjQZjW5b7ah1KmzG%2FFXDL8cuGXo14pvNG0uS%2B00pL%2Fw%2FwDsa754%2Bx9aZtsLrN%2FgrnTDc7ZeUkuBplzzFMzvpWPxtn2UNqzeR%2FT45HeMfJ5W6hLl%2BupL%2FK%2F89M1Au%2FC3MuW70WmP4LfWD0n8SDp25hXBrz%2Bfw543Ul%2FuP8TNibpv8votTKmUChxkPtJAAkjkR80hR9nZ5xiuzaPJ2XhbobLrKYPEAz7Vox0zPPMn0bF4FZIQhCToDR2MdafCW6M8kqssXDrVEhKpU4DB%2FPanxVujJKyyMEwxBKAsJM9jJq5KtBRSotbB8AT%2BycCDMykjYpM8g9K0YY1tATqWi4sNcdvGUWeYbIY%2FapENrcOl9of6HeT8KkVti%2F8AcyuKT0OHsipc1X2Wbpd2keosE6H2%2FlPUe4qSSbJ89aZ9h7FwSlGIWwd07KUoALn3oJR%2Bh0Zpk3sMEsnS35LhSeYKYINB%2FkNosbCsO%2B7BpBlIn09vrUkleikifWzYaQEgGf41QE5fQbbc0ABBknc7wKhUZMeN3aAQdcE8yKGSbRapvbCbS9SQdR68UnoWPGm1r3CUjrsOD9afZag2LKtJj1b9iKjYbx17M%2FuxKRs4pU70uRItLVg561lKilQ%2FnQBxkmwc4wsEJ3V%2Bu9Dr2PTQklgkLJQPnvU4II88qE9B9KFwXopqzFbSQASSR%2FOqlD6JQl5cEE6pmYiqSZYg6lMkkE7dKogKdGmSJ9xFL51ogpbtKUQSQTU5N9FNMMtoVI4G1GU5BBDREzIAHA5Joopey45fo9CTv1gbiIopQ2FydUZJZ0rMEQf74q3XsodpRAIPPaaBu%2BgXI8ea0pB9R43ooMpTQMdTyEhIA696k6DGKkCSTM9B1FLIYlCgQdtUflVpjINLsSLRmSY6j3onMJz1aYg8g6SCOvBHNC5C%2Bb%2Bzo6hadKSnf3Fewf6PKiwcAIJUD13qiC4dgGQon5NQhmFwdztPbmoSjMjVGkkiOlVJWQxUkBQEqJPsKpQRDFS0pkBISDtUpIJRsxDoOypHvETVSqiOLQo26mQkq1dAJpQDHIWkjSnnqJiKglxaHaXYAgx80LgUK%2BYqd%2BPYULiFF0eF0CTVOLLbsQLomVBYHc0xRonBjV11Sh%2B7HSnxjRIwsHurSQdXX35q4xoKMKdgi6cH4AFfMTQTl6DAziyD%2Fpnk0suMbGb9wEHhJPB3qBSdOloHrdUVEBRSBxJ4qA8n9ifmTGtSj2g1Cm3%2FAJG3npSoACVfrUIZC7CfwiJ%2FI1dshkm%2BJJ2QaK5EsxXerEAjR8Vf5EEXLtcSpQj5qpX7IxBVwuSAUn2HSgDUGxuXjAIUCevvUL%2BMbu3AAVuAe5qFqCRCcbxJbYISQnbc1A7fRSmZcdKUrIURufrSm1YMkq2a051zWltt%2FU6EjeRVWiQlbo5w%2BOniG2wzepcfVICjsPwisuadLRoUH0jiN48eIoujiCFPuFWlQO8AT1G%2FNee81Te0Xii4%2FizlF4kYwb26u9SgdRgGa5cm6O1gxRa2atYrdeW6UggmN%2B9LdsKcIJ0iLu35XqhUCOBx%2BdOx44v%2BQrluhYXalJKFq9PEmdh80cnBaSA8hSeojti4BCVRuAPVqpby%2FQOPFKPbJHYYhpdQ2lCdQiSTEUttvsenTstjL7rjqUqLe5I5ElQ%2BKbBiWm3ovjKqShSSXDpB3kgfpS8mRVo0YcMk7ZeuGXTDdsHEBpYGwk7cb%2FlWd62b%2BEnImFliTZa3Rbg8EqImPY0cMqfeg9wJ9l7DMNxN0PXdzbyI%2FCYH9D8VU8lL8RsMl%2Bi9MGsss2QS4fuy07TJgk8SOvWkZsr4XHs2Y2%2FXZbGGZlwu2bQnDmPPIASZOxFc6cpR7AlLeyYox28xBCdTzjSAN0p9MfWijJsTzTdBpjGmbRsB25QVTtKtUb%2FM1phjkvRJ4t9CLeYbS8ukMsrecBPqIERvuZq5QlXTKljcVZZmGhpLZW2Sy2IKion1COlFCD9GRtk%2By%2Fj1jZvoaLt1cuEwUhPvtua6HjycewZx1svrCsxpWlldxLQ29KufmK6Ky30YnGmWRhr7WJvIcZD77sQgAmPpTopsBypWwy8LHDnSi4Wby9A2tWPUQf8A9IocfHNXJUTE3J16IhijOZcYWGoQm2kBDSUgBG%2B2lKeT7nes7jkn0dCKxwVsZ4rknLGUrJeNZtsmcXxYpCrexU3qn3cO%2B3tyap44Yfz%2FANRn%2BZ5vxjpfZo14l4PnnP2bFYoEXl6D%2Bzb1AJTbtjYNMN%2FupA22j3rFknPLK0djFCGKP49Fg5RyjfeFODoxDHb%2B4v8AMt1uxYtpQA2OgWoCY6murhisUbk9nD8jyH5E6gqivZRmc%2FEvxozXj7%2F%2BD37KcNY%2FZIdSpSm0ngkJOxAkjfr0pWXyckumHHxcUNtWbNeGOD%2BIVlg9pcY3jv3vEH%2FUW%2FLSPLHRShEajz7VowTye2JnKDbaNt8tv4o9Zqt7h4uaD%2B0cB4n93bk%2B1dKMmwG4WHG7B9dwUWwZs3XV%2Bo%2FiUR3Iooyd9DY5aX2iXYvhrotmbe2ulM%2BWnSdJgqMbn2FX7BhJp2xthGXMHw%2B2Nzev3OIXTnqgKkgR1%2F3pcYUNn5U5OkQzMuLBaVW%2BGYOL1zUEpT5ulDXuojr7ChyptGzx8S7lICIukWeHujE3LcPlXqbt0yfgn%2FesuzVxTlUCOXlx94bcFim2tWTuoNDUsQP3lHYfAq7NMIJPb2AsPtHLxy4d1FFoCErWvYK9h7VRoc4k4XmTD7C2asnFWVpaW7YU5qIknj6UfOkIUG%2BjTX7Qf2hsPwLL%2BL4fgj4N26lxIdVwwI%2FEB1NIzeWoxo7P9H%2FpzyZEfl38VsrteJGf8SzTfC6fu3Hj%2FwCRWskAmPjpXAyzi3ykfYvE8GWOCii%2Bvs%2B5jzp4TZkw%2B3wW5vjhzhSHGi4VBsf5kpJiayQ8lLJcRnk%2BLePjNn6G%2FDDxqxBjAbG9xFdjcOusoSnfd1J5XE8DrXovE8jWz5L52CXyvRupkjxMscUwa2F423Z3aT5a0AkJCSNj7GuhjmmrPK%2BXhcW7Latc0sBhDbwUG1GAZkkdwe9aHkRz1H2iQN3Tl4jW0n7w2mCpIP4h7e9A6excp%2BiS4Xh1rdueeElBOwcSIWj2WOvzVxg2I%2BUtfLH3mxuEM3S0LnZLoHI9%2FetWFbMOeReeEXjqUgqShI%2Fe32PuK2HKzOiYOZhRb2xuELbcWhMOJKufetAEHopvNOd8Vt7lb9mkOW%2BynGXQSlQ9vf4qFyVkIxfFMJzUu3YYxNeC47AXaLcXBCh%2B7q4UOm%2B9QUm7sorPmBvZrZxAsW4sM8WKdd5ZxpF0j%2F8AEa7nqQKXNW9GhNtckaYP%2BI2O5IxBeI2CkOLSS0%2FbXKNTdwgn1NOJ6pM%2Fma57zuMqZsjilONlK%2BNGVsPzHla68U%2FC4LVldKvLxjDFK1XGX3%2BYUncqZPKV8dKvNhUvygFjycXwmc4cffuU3H3m2u7myu23PMZcZcKXG1DcKCgZBHMisduOjZOEWtm1%2Fh19sO3xvCmPDz7TOCs%2BIOWAAxb5hVapevrBO0eej%2F77Y7iHAO9afH8xr8Wjnz8TjLkv%2BAvm77O2EZd%2B6%2BJvgpnK%2FwApYJdy7Z41hd0t%2FDXSSPQ6tI8y3V0KXkkDqa0Swr%2BWN0Iy45yheR2v%2BUeKz5jtm3bYF4%2BeHFnjtm9CmMbw5tEupj8R0y273JBBNLWacf5rRrxRlONRfJL70%2F8Av9fqh7a%2BCmSczWq8U8M8etblBVrVakaXED%2FKWlbj6bVlz4MeR3FD%2FHlk%2FjJ%2F9zFvI%2BNYCot31koJTMqTv16gdayf2SXo08WuyVYY2oJQ2AVK3gRv8e1Pxw1Q35FXRLbJtyAtK0laeZ4%2FsUSTbEzl9Fu5YeQWmUq%2F8sjpx7UqcHZmc0jYbLVjIS4oLJMQANh71pSpETr8i1sOwouDZs6TsSRM0%2BEWLc2yTt5fKVNvtamXE8KSSCn4rRGH2BX2SpnDLTEFJTidokP%2FALt00kBX%2FwCuP3vmicbFyUh0rKbtnpuEIQ9bTs63uD7e1Z8kPY3Fk9MM2Nq62UED0gjkb0g0Emt2k%2FiWhQPUzUFcGOFM%2Bo6VI%2BtUTgzwNuSBpQB7HioRY2GLQqCtJO2red6CULdl%2FGSe2QkhMKAHv%2FSjQyTrsf8AkkRCTJP0NQW8gu3YuLhSm1Ec7moAq9nr%2BHGFQiDPxVNaodFrpAJ6zUkk6IIMfNVwRY3NtpJHlgAnvzSnCS9l2IrZBGlSUn5NKbaL5MQXbgydCNvfmoplxmxqWDJA0gHcxyaO7WhyQNebIKVT6uZpVFJMFOIlUcCaXzRfF1YSYZ1pSAJFEt9FJvoLsW%2FJLaQeOOKKkVJD4sgyAAJ%2FWqAhp2kYtsK1RsB0jr%2BdGtjEOxalRkjSefmi%2BPRTaFzbQgbx%2FfFEkqoUqvY0dbJBEJUY4qmvYS4g5bKjuEakxzQ817DtAtSNK4ACj%2FGgZZiUyZ0hZP0qiGWkwIKZmKhBBxpSldeeJgmoQ39ZcWCY3ETEV6uN2eXHiHQqBpIPuOaZaIOUqJJVMcCJomhkGLpVBO8%2B3ehCbTVIyCwCQVQn8qjdAxh9mBeEAEp9t4mpyQDQ1cWEpKhBIM80MqZak0NBdKJICpJ6z%2FCl2X8jMk3ZGxKD1nrUIsjH7b4kHWT9eKcoplTpseC4TBBM%2FG350EsbWhbxKtCqXwYhY379KpquxTjQp55BSCpMT06ULaKEnXgJkifmrTRAc4%2Boz6oHfvTqHukM3X0oBJVEfnQykC79Ax24QTsdQ7DpSuylGQLeWlRUkKCR1jpTFC%2Bxqi4%2BwM442gkrWSdWw5pQMrYwduNSz5Z9Mce9RfskN6GarpLZMqk9IFQbF8exsu%2Bb1E89duRUL5Luhsq9KySFAIG%2F%2B1QFx5dGP39QggokfSrtjOKMFYgv%2FwDFA%2BDV8mA4b0YKxBI0nWnp15qm2MUV2IqxMbGZBnrH1qiuaWhM4inY60p6VCwbc4gnQoa9wOvWoQrXMOKlCFkKMRtvvS5S%2Bimm9I1vznj2kPhLukRMjrQLYEsTWu2aR%2BJ%2BdRasXQ82IBBOqZoMkl0uxmNemci%2FtCeJ6ls3QTcBOy%2BT%2BI%2FNcLyvKadGqLd0jj94m5rVeOXAJXBCjqUSTzXNn5Dnr0b1F10aQ5uvS688hLmmQYE1kmFGCKKxVZS4tKlBB295270MItvQyV1ohq7gpUoyFJmZJifitHxy%2BhHGhyzdoUVDUSoxtG29W8cvotutsk9hZOurSU6gmAI4rPPsL549WTfCsGHmpU4FuEkyByPpQBPKkXdl%2B1SEMpTKQB3E0yS1ovxdPZZuGtOzCVqWYEpGxJHas82q0dJMsfDW8Q8lCNKyNzqAkg0ibpaDx5XZYuB4DiVypvzWHFqgH1JgH3rHLBN7Y143J7LkwjLZtvKPkLWdOobxvPWmRXFUaowguiy8Iw4hOpxClpTASIEc0Y5ShHosVq9w3DWUobaWpcAkzuT7ChyRTMuScPYTts42%2BksspbtyRJ1LAg%2Fn7UEIcO0Z3OMdoaOYjavuhKrySf3Ukn9elao5U0GvKZZ2U0YTati4cYcuwE7JkhPMj9adjRU8s5FgW2Ou3q021tbMNtEiJBURvuCSaL5YXV7EcKLjyyHWWUBLOq5WNtKJmB0rVBNaLktFv4ThT5KLjGr9VoCqUMJALjg9wPw%2FWtMU6%2FI582m9Fm4fiiksC1w8KsLSIXpPrX%2F7K%2FkKPn6EuGyYZdwnEbshFqw1a2w%2FG4dgB9f51ox423aBeVLRNVYvZ4Q391wlTT98dlXZTKW%2F%2FQfzpmo6QhfJJ8noiycrXeYblwm9uluuHU48rdR%2Bh2FSWGMu0a15cYRG%2BNYJgmWGyxh1uziGNQT5i9w1t1P60nLCMF%2BKCjllmq3%2BJQ2asn3V1hS3rm8uHMRuApbj5VBDfYdgf4Vgnb3I2RaX4rog2UfDLBLVX%2BLXFim8trRQclU6S70gddv%2BK2eMkzNmyt%2Fi2XVlxnELm88hlq3YYUvUlbqytaiequ3SBWyLbejNLHwVWXNc4pbYCw3Y2NqMSuEqJUonSnURupUflFaHNLozrHKTt6Qeya7dv%2FfsZxNlCEo9DW0Jn2PWjjF9miSS0uwpcYTimJOrLQ8m3J9a1zKtv0FGFDOovY0xGzcZUy065psUJHmRsAB0270Lkl2acck9RIZiCnMQuCq1Bw%2FAWZJCB6rkxwVUjJl9I04opKpdgNVtaKJt%2FMbVqla1lUBA7CkB2RPMWbcMw1k4W3oZtZ0gIISXFRO%2F9ag7FFzemVTmHxMtMOwgPtQWgIZaSR61cAfTk1Dbg8OUpbNU89eLT9rZX7Tz%2FwB6xC4dAQEqKgg8jb2HSseTLTaPSeH%2FAEqN2aWeJjOM5tawtlblz96ui466ltJjTzKv79qyzZ6bweONXEri08Erq%2Fwv79Z4e46tbZSpSW4VrA5I%2FKs%2BTx7R3V%2FVEmuT2Wdk%2FwCz42%2FY2mIvWoTibRJDYEFzsDJ2kikQ8Sn%2BJlzf1tdJl6YVkLO1y3Z4jcYe82w2ny2Cw7CG08KR7H5FaYYZ9s5efzPH%2FwBza%2Fw6axvLiGmHcTuHrEoENvIWkJP%2BUqOxrbjbSuzy%2FwDUPjlbSNsMo4li7t0%2Fbu3RuEOaVtJIlKDxE9vitWOfLs83ljH1o2ayvh97bui5bUW2HUj9mTsg9a047uzheRkadF24LhK1KNwj9isnieD7VujCzDPK0WphVkyUJXcJIWPUUzx7itEMdGGeRJ3ZI28QbYbU206kkJOkg9YmK0RdKjPLMpLZUWO51u2rnXarbWB6HmSR%2B0T1AonO%2BhDnrWgBiuaPu7Vu4%2B6h%2FC3QQC5v6e09CP5UKt9Dcb5forjO13g4sLZAujag%2FwDjWs7cyN%2BKL8h6m30CcHzzcYo1Z4Hib1m5mBg6sIxBwx5ihwwpxO4ngEyN4oeddismNt9UUD4sZLY8VrXHsYyTbvYJ4g4erTjOXnlAOBX%2FAOI0dgpJ6GAKmTxoTV%2BxsM9UrOdNl4j528HM3uYtYMC2vUlVviGG3rX7DEGDstl9BG6Dx3B3FcyWWeJ8To%2F2sc0ewZ4t%2BGWWc75ZufG3wUbuHMolYTjuBKOu6ytcqkwrqq3Vvpc6cH2qcFPa7KwNwlwa0ax2OAB0BGlJ6jbc%2FMVy5%2BR%2F0nTWNekX%2FwCEOfc6eD%2BJLvsqYmU2FynTf4ZcJ82xxAcaXmiYO0jUIUO9Xi83ImkZc3hJvmls3PykfD7xVtX2sgIssm5xcSpy9yZibmvDsTV1VZOKP7NRknSIUOxivQwz89HOyQkn%2BRXmIeHCMJxpyzwW0v8AKmZ2zK8KujpdSodWHNg4n22VHSs2THUrQT8lzVT2SbCvEDF7VH%2BGZoslYilHoUXU6HW49%2Bu3Q1byxHY7q4dEhZw7AcbSb3BXkecZKm%2BFpP8A6zQJwfQSc2gQ%2FaXVo4ElDhb3STp4AqNxXSL%2BOX2WHkxp9TjSlJmSDJGwqNp6oVkxG3mUMLUdKkBa0nTt7x3q%2FHX%2FAFC4SfRsHg2DDym1aQTG4itOOIt5K7J5ZYGFpAUgmeY4NNLc7QbYwBB4RCh9atMC2FE4a7akLZUpIiFJjYiOtURPdibuH2KwpRbFm5uZSJT%2BXSs3FGiOVjb7m4z%2BJIUjY60mQaRQ5M9DPqSAk%2FE81LI5IzTb61KP4YM1T0XYSt2CFykEnj61E7ISC2RGiN4nirF5FSJFbskAKJJHPExQ6uhaDNvb6gCtIHx2qcUShZdmnSuR6R%2BlXxVk36Ad5h0hagFEnsBQq0w6mA1WccgKAM0DdexowdYKiDGknmN6lp9kEls6dUlRnvQOMaLi6GbzSSkg7AiY70PAYsmyMXKQoqnaN%2Fmk5X9DVN3VjJsa1pQdpImkDiRW7OqFEq0maetaQvIgywyNhuSO3Wjj2Kbo9dbQlQBAPcgfpTaRLMEAEgExuDxVKiSj9MMtNIAkkq%2BNookJkvs9dSCCUhSjsBvxUKoEOjZQIJ6VAlFiRSYmFJB4MUqaYfxoF3DIK1KEgHfYCooBJDTyoHMfSo4Ms%2BCCPTvA5oGiHpZ06hse09ahDeO3cIHtwa9VGVHmvjYWQpKoOoKPQ01b2C01pih2M7fSislnhe0HUU6iDEjp9KCcqJfsQU%2BCFEEkHoRzSm7C%2BRjZbhkjknkVQDY3L%2BmYDage%2FSrLUqMDchUAwmBt0qWMSUkJeepJmRE1QuSp0ZouFJIIM9dxVp0DaHTeIFJAUBHftR8y7HCb9G0lX06USkWhf75AHrETt3FW5IRKDswVdJMnXJ%2BarmicWNV3Y%2FzJHaTQOREmDXH1SSST7npUjBvY2P1QPcuSQQIA%2BeaNRSCbXrsF3F2ndIClfBoHP6K7BLzxJhxQT1jrQB8a%2FkD3LoJQSjSRyQe9QZFKtAxx%2FSoiSfrUB4LtjF29LaSQpM889KGUqLlPj0DHMS3JBB7TQ%2FIC8smMl4mvZQc37UXNAfI%2FsbOYo5BV5u496rminNjf%2FEeZXq4Hx2qPJ9F%2Fl7MTiUlRkGZ3O9VzL5%2FowVigEJBSnqPepzC%2BRgnEMXKG1nUD161cZ3aZFNtlR5lxvZ4hfp5AB3pcduh8Y3uzVfP2YSw08svAKHv%2FADoZy4ugHB8rs5peNmeUW9rerVcEqKTvH4iAff2rnZZtO0FB8f2cVPG3P7uIX9w2bkFqDKQJj%2FeuF5GZSlaNfjJXZohm%2FF13C3VFyQBCd4k%2FFZao3zzTfs1uzGtbjjqlAEgSSDxS5lY1LtlO4sgla3Z0A7fO3WpCVBuVKyE3TIOvQkkgcTMe%2FNaHml7Yhyk%2FZiy6Lb1OJTPJJnmixqcn2KeKUu2S7D8fQyhCUtxGraTv%2FOk5sLiwZYHF2ic4dmcIQZDSdolP980qvRUcz5VJ6J5g%2BbWkKASFatuORRKX2bOOriy18v5nUpxlQdXomZ4n2mrcU0OxzlfZszkzGbdTaFuoQHyNgTqJ%2BlIirdm5tx9myuXb21dSwhBQSUhRKREbUxr7ET870myf2GH3l0oJZKVSNpPEcc%2FyoFjTdsbDM37LIwnJWJ3TQUtbbKiJnUN59qb8SGNN%2B6JG34aPueaLx8lsEH0q3P8AKaJYl9EVIaX3hzZWjK1NoWsH8QiSB3ockFW0RpPVC%2BHZRsmR5xZVCQZB336f8UqLikXHBWkHbdnFri5bt7S3WwiANKB%2BW%2FzQuMn0jTLFJL%2F%2Bmx%2BT%2FD5%2B0baxHH328NtVALhYKnVnYwlH05o4eNBdmHJnjy4rb%2F4Lpw%2B9ZYUhvC7U2jYGnzl7uqHcHhP0rTFpOogrFbtvZO8vYNc4o%2Blttt5xSt1E7gnjf8q1QxuRmzTit2XhheXcKwRgO4w4VPgDS0n8RH04FbeKh32Zfkck0ha9xfEMUX91tmkWdmIAbbOyh%2Fq7mo5y9BKCjthnB8tqWUPXSUoZ5AJ5qkrdsVl8nVRD2J4mm0t1WGEpQ2tUBx1Ig%2FApjl6QvBh5O2Q9OFC6K374lVu0dSgJ9Z7HvNBRqllcXxQMu8uJzHci1ftFuBagkNJkDmQD7UDxpjJTaVozzFg2G2Ldtg1glu1w%2B22V5f7zp5Ij6CTVySSroQpXsNZYyYnDbFzHHiXHNWm1QQY1ERqPxTcMOO2KeSV6DNjgpdW2Hg04dWwG43P%2FADzTErloas1ItB%2Byt8MtbCySUlCQFrEdf7NbHjcVsRLI%2BVsCv3N5d%2Fsy8Le21glDSuY4CjSJSaY6WRVrshWY3XtTgU6vyBMpJjzPY%2B1DN7NeOaor3Hb9NpZ2pffQywAAhMgDUewpDjqx%2BObfRU%2BYs0ptUhVu6U24V5aSOXT%2FAEmlt0b8WK%2BzWRvEs2Zsx%2FFLcJNthbKI85excUeQnf3pMMzb2juLHDHBSj2Re%2FsL3FceQxa2t8cuYe0lPngSu6u1CdLaOpAmTxQScnL9HQg0kpXsiWL5HevcUwNOE4U03h7Wtb7i3PMeuFkeqVDaeBPHahlCzfi8rjFykyR2%2Fhyu3zYtb1tZrdZS22hGkeWyDHA6xP1Ioop9C35acdBzAfCrEMNxHMthcr821fcWGUtymdpGxiBtxVTg7pkl5kWr9k6yX4buW%2Bi%2BxC2U8kPEOIIgLQRtI7A1ePAlujF5Xn6paNhMH8PLS8sV4jgv3i2uElIdt1GA52McHbr1p0sSZxMnmepFqZcycXbdCLptpxBUJC2xMR1A5q1hVmTLmrSLZwLw6s7VxDlpbICCJ52BmfpT4Y16RysnkNOi88v4FoS2gtpSRsfTINaceP7ObmzOy0cPw9Nk2XkjSYETXQxpVZzcuZ9mOI37jS0eWvQe460Zmc2%2ByGXeJXlveJfSoltKpWO470yMbGQuvorHNdyhF%2B6Er8oLSHUEHgHtSZKwrSeyHO4tcX2WsdsHVBarcpfRtOkTBP12o4QZMlQ69lU5nzI3iuXRZKeSL%2B3bKgmT6xS5SoZqLs0zx%2FxIv8IcULLEnbB5ESlCjPzHFKlNXs0Rbl6Le8PfHjEfFJ1FtZ%2F9vI8ecKaWvDHrgFpvNFqkeq2dKTu6EgxMyN4kGn4c6egM%2Fj0tMG%2BILnh94w5UVnHE8p4pbMW7pssa8hY%2FxHK10CQpLqCJdtyRO%2FTii8iEZKp%2BzPj8uSd4d12ax4DaP%2BAucbLM2W8SxK6wu6aKErU0i5w7HrRX4mnQCApJG0ESk781zHBY3cTuYcizxqSSf%2BSdZv8ACLIea8BvfFvwhu3LbKwcH%2BMYS40Vv5euFCfUkSosE%2FhXx02irzYIZPyghGHyZY8nx5Gym7fLVnp0tY3hrggEJhaCfcyn%2BdYqS1o2vLqgzY5Xuw6pyzubJ5QUFJLLwKkxwQZkfNDQl5YvT2bF4N4g4riuH2uXvFrB7jMuEN7W%2BKgf%2FmGHxxpd5cSNtjuOhroYfMUVTMfkYk3%2BPRLscy0r%2FDrXFLt1Oc8rPbW%2BMWkfemB%2FleH7xA6Hf5rTNQmrQEFwdxdla3eVMTwXRi2CXZv8IKpTcMSCg9lpG6TA61iklHo6cPKjLUlROsBxBd4hDOMtqU9%2BHzkiSfnv1p0JJFySXRfeVMvW115D1upC0RBKDEb9RRKSejNkXZtPk%2FCltMtJGroJIpiSRhhLZsRgWGQhpJSCf0p0Y0VK3uicWtjoOjTsD0ogSS2%2BH6gCAYjaoQfrwoKb%2FCQTG8z%2BdQhHL%2FD%2FAC5ASBvz3pDVBK0R9TbrDssmJ%2Fd6GkqCDi2%2Bx2y3YrGq5S%2By7%2FnaMifdNVKMfaDpeh8jCHbhAVYv292Z2QVaVz%2F6mglCPoZzb6E02twyspeYdZWP8wiqSpBOaXYYtEJIEASN4NLSa7KhHVklYRqSZGkdTNMiFLGqsMshsJCYTPc1aTEuND5KErEemBwJqwoL2NXrfV0BUevaoNAVzZHchO%2FWBS%2FjIBXrUjYDrvtzQuBAQ8wQTAMTMdRVNNdkB7qDCuZ%2BKFlpEZv21JnhvrWbLvZpgxhapUpWyZBO3WkjUiU2zag22JJV15p0JWJk7CSQEzqUEifmK0RehfD7EnlBWw3TO3c1TlQSVDdEhYM%2BwoYvZYaDh0j1SekU0CUfZ4FEpUFHf3qChqQVahM9fkdqpD0JrSUhQgjeB7D%2BVRqyxoWitUgAE9utL4Mgm5awIMRM8TVW0LnOhuphSVBcE9xFXy%2Bylk%2Bxu5H4j6R79au0aIwb6NxGbgEABSk7816Q81JNqkFLa5KZG5Jjmii97EtV2P8A70iNiDFM5ogkt9reVESZImlydsJRi%2B%2Bxq4%2BmZb1FPvvVJATdOkNlvK43Cj%2BlUFGLatDVbokHUZ3monfQyMPsS%2B8pV6oj2irot0tiSrtU%2Fh1I5mo0V8i%2Bj5V6RpOjT87VRPlr0fJvDvqSCKvQLknujJN8kADSQfmqKtPvQqm9bCSoklU8H%2BVQuo%2FZiq6BO6lH2FQjURuu9MKSlQT%2FABoqXoW6Q2duweVkDYzPNW5sFSYLdviStKFJSO%2FFBXsOMLYNevvSQjnqR1NQir7Bjr5IIUomJ3qN0Mk%2F%2BoHOvjfSoAE9TzQSnvRanGgTcXpBMLM%2FO9SM%2FsK12Bbi9jUSVRxH9mpKSoCU01SAjmIBJJCwkgdaUDHj7BL2KwfxAxyNVQNziDXsY0kjVM99qgDnu0Nf8YG8L2955qFynaMF4wCoy4kj46fnUAEjjUAy7122q6LpkexPH0%2BU7Kidt%2Fegc6Dx422UnmrMyUodlxKRyIPAoJy1ZsSro0q8U85oQzdjzkJbAI53pDlewXjUtHIP7QXiI4n735d0oJTKUKH9BFc3LmSf5F40os5HeJGZF3V2%2BtLillSj6yTHP%2FNcnKo3aN0ZJ9GvmMYl5nmblSzvEc%2FT60puw%2BSWqKjx4hSnIXCY69%2B00uYD8mnVFY4k0vUWwkq7KJmPapFR9s0RkpLsiVwm4QpQKUKHBE%2Fh5rSoQelICUFQLUyVDTEEn07xV5Eo%2BymmJhh0KRLjkzMk1b8pVTiKnmldMNWBWFJBU5I9XPWs06e0SKjJ7JxhjpABUs6Y6yI%2BtKNWukWlglw6PJIWUCJ%2FEdqZBiJKSLwy1iztuUaFq1biaNUApTNkMtZjuCloea4PT0USJHb2oJaDjJvs2cyjj1ytCB5i2VKSE88T%2FOol%2BhywSas2BwXM5b8on1K2neRttRp2WpSj6smKcw39yoBkBnXIgflVmzDl%2ByV2mH3%2BIJSlx0BZO5Bg1ai%2FQayIsnA8g3N0guXZbtLAQXH1GEgz07n4q148X2DLMkias22EYOfLwJhCnSY%2B9ugFZ76RwOu%2FNOhhh9AwkpfyC2D22IYncgJCn3tRQVqMqMdZmsksKlKqLlxjov8AyzkcJQi5xIhgbEJPJPwK34%2FESMuXyF%2FpWy3rFbeHMpt8Gt1WyePNP4jWra0jEoW7Y5Yw128c1Oea6tROonk%2FWh4SexvNRJvhuDM2KUu3AJI3AIkj2puOCWxcst7HVwt5adgQCCAAOBTWtB%2FHH0NbbB1XDpSn1LP7x4%2F2oVD7AySaWux1c2jcptGpLDfWN3FdVVHBC4yrbC9rZDCbNy8Kf%2FnuohoEf%2BNJ5VHft9aZwpA5J8noA2GWVYniDaHEKQ2SFKUew60qOK3se5xUKQVzLiUXiMMsUluyYAbB79z9abk06XoTiS%2FkxXDWiynDjcHS48rVAH7s7TRwdNFOSdhK8vBcYs80pZ0oTJIG%2FHv1pk5tsbj%2FAI6Ig7mBlLy2LGFJCT6indZ%2FvrSZO2F8S9kDxS%2FurtYceUDbgkkH94Ut5BsVRRmcU4lj%2BO2bSUlrC2rfUSFEHXq2AHQRQN2dDBKMY37K3zJaXF1iKLO0Q640kEMgI%2FEs%2FiWe0ClTi2dLxmlH9hLAsp4w2yhFukoUpKgoKEpUY2J94BNBwa6HSzoUxnJGIGztMOskli2bYV5wZEKcUoEEA8yZ56UMsc30zRg8hex%2Fb5GYtBZ2LKUM3ttbNoLbKQW2UqIkf%2Bx0%2FwATUhjGPyO9loWXhwlD91j9yy69dKSV6SNnCPwiOIHenpUZp%2Bbf4oLYPlbErvErR26t2GGw95pWE7woDngUSSbEy8qlRc9rkiydtUsMWbba0kkp07r7gmi4HOn5slKwpheS1YYW221KLYEbnkT19xUUUvRnyeY5FjYdgTaikFtJMCTB4plWZpTfZZ2C4GEISgMqSDvJ%2FvinY4MyTyaJ5aWjVuAkpSdPbpXRiqVHKnkdjtS0KacQlwgHbmiB%2BR%2FZE8Qbc8twRqPQ701QL4IiOIqcXbqUn0voMEjtVuK7DjBFW5xDV5htg8lYRdBK0dgYO0e9U4%2BkRrorHB7h55OPIuEOJSbVaVq4mN9%2B9CosPJdKjTjMucn8OzCVNlUNiCnkKTMEH9aRmacg4x%2BzWXxUQGcRXcWi0GyuGw6kjgyeP5VhzQdnS8WcKqikLZ%2FEcOxG3xTCbq5s8SYdTcW7zKilbLiSClQI4I5ml45NO0OnGFaZ0GyfnTEc92l14u5Rs7dHinhtui2zngYSBb5qw%2BN7lKP84Eg9QZ711sOV5GcLPGUZWkY4%2Fl%2FBcKwdOccpWj%2BY%2FBfFzrvcJWs%2BZgtySNQSOW1gnbgECl%2BVCSfYEYye06ZF8voxnwgzDYZxyNf2%2BK5bumy3ocAWziFsr8VvcJ7bmR0O4rBNcHp2jp4o84fn2S7N3hjlvGrA%2BJ3hyzcf9qvuAX%2BFqJU%2Fl%2B5PLSu7RJJSuhzePyXOAePO1L45ECt8qleoBlBIEiU7k81hjha%2Fka8sIp0w1YYVe2aFeU7cNIjYaiI9qL40BcV6JxlrMWOZcdWbdDN3aOJAuLd1HoeR1BA6%2B9aceXiqQvI4PpEmvMOS0oZpyUt62bWIu7NZCi2eqVA7KSelP5Rl0Fiyap7%2FAPBMMs2WDZnkMMt4Xi4O7J2bd%2F8AU9D7GmpJ99gTyTh3tF35Vy%2B%2Fh1wULYLStQBHEUzhQiebkja%2FJljqaZKoWO8c0yCEF%2FYPYaUtpCd5njmmFUSxFkguDVqB5qFhu3txMJGw5qm36IFvKSGSUiTHNLc37IRfErYLQuQdW5mglvsLmyHPWwSVH9JpLgxqM0WYWAomBJM0AcYXszDDaQFbk9DHFDO6DjCmKm5fSgJL7qm5%2FCo6hVRmw2h3autEjS3pV196C2B8aD7DqCTJJTzEyQaonxofJfbQIJUAKuMqIoIeN3YCtjJ3G5o%2FkC4r0PWlhad9ldIqfIixRy3WoboTTEQFvYeFJWOg470Ep0QjV5ZKZBUE6Rwdv1pbbICPLSfxDYDYChbD%2BNdsB4rbDSv0bQR3pWVaHRa7AVm0PMSASADq4%2FSsoc2SJlAJCiJI23MzTYqhSY5WkpI0pAT3piLGzyCAeY6T1qmkQSQYUk7x2qyBdoHeUq56UcZa2Q8IhUGiUkVRgrgng9SO1EWNndgpYIP8RSpvZBFslaxxP6f80KjZB6UoKY37yelNdIjQNeCiVAbmOppTeyqQHuXJXoCRAA533pU5uxkYJ9m0tvfBAQAn08mN4r1XK%2Bjy3Nhdq8SYOtJ6TRL9ktPsfi4TCfWJPXvRyjSJxT6PC%2BiVHWnVPehonDfYkq5AmNM1Q5aGTl0J2BUf0qFtjZy8nYc%2B5oJQK4v0MjeKnUIjuelDKqEud6MF3jp9OvjmOlHwRXF%2FR797XuCtPaRRsL42Il9RJlZjnniqK4P7MDcqASkuDjaTUIoMUF2rgOIVttMb1C1B%2BxFy%2BC53SE9gBUK4r7Gv3wK1Cd%2B3YVLRf4iC7tYUI8sCOnSoFcf%2FAKgW7eBJGpUE9jxVoFxXdg96%2FBBSkkGORUoP5EMXbxySQoJHzNC6YpybGDt0qF6lk1VKi4xT7A9zeAAkSTO4IpTZUu6%2BiPXV7AI1T7dqi%2FYziqsi91iChrK3I2gVUpJAcb%2FiR%2B5xQggByI%2FhQfINeHQBfxaVEakp9%2B9R5EAsf2MF42QkgKT2qnkGxxRGi8cUJKndW0RMRSnnsL4Y%2BkD7jMqEBSvM3nmq5otYyB41m7S0vUpPfY7miQ2GOjW%2FO2eEtsPBTySACYKulLjl1TGrE5bOePjX4nptLe6S2pts6ZMnk%2B5%2F4rK5u6Ql5vjls45%2BNviSq9ffAc1yDsTsB7VxPJm3KmbLjNWjQjMGYEvvuKUpGpSjq3kz%2FKs4wr2%2BxALCylQGmBMwSapsuKdkFvrlDid43G5NKszZYvkRa8UCTqCQRxvsPiqLxZkqTRHlsplwuHR0EirT2HPyU3SGX3VAluEhXbp81cpN9gvKpaSo9FolJkkqI3561HKy%2Fgk%2FYXtsOQoKWsEmQoSRNDZF40r2yR2tkptIUAVJOxANWW%2FHmumTnB0oISlxZkyDJ4NHAFLInTLfwNMJSlRQfadqYh712Xtlu%2Bt7dLP7RoqieeDH9%2FnVIZNRSTi9l5YDmFv0No%2FaApgaSOfao9lx8mUf8GwWWMVaulNKCdMadid%2FyNUovoYvIk9UX9gD7b7yFJb8xUSmB194okr0NnKui6sMfs8BYTcYiWHb1adbdnq3A5lfUT2960wxOjFLJsNIzbfYvcoQ%2BoBoR5bTY0pQOwH86un0Wpp9lm5ey8%2FjbjSwgBJ3lXTvTccNDPlpF%2BYHh2E5daS0ny3Lsx6jB0nvNPUV9iZZZS9E3sLpV055rhSRsNjtFGogRu3ZOLFbayAFDbqKKMCpyomVq%2Fa2jeolIVtJ7UwQ8lsXcvkKhxbgM7pBP4jVl2ZtXLa1j1FZKeg3NQgTN8zasqYQ40p9UazO4H%2BURULHmHeUQq8uVEWre5H%2BY9qKC2DJCN3iQurmSpK1SAIj09v41U7bAprZIW%2FLwuydJAFypMqkg6R29uaasbS2DGduiGs4cq%2Bv2%2BUBZ1KHPpG5pMY2a%2FkSWw9bttXOKG5EkgnQJ2CRsIprxvtCGvaBbVgpeJvOSF6woHoeOtA27G4pa2Q3%2FDfLuPMCEkBUFUQIneaE0Kj5eEIDj5UkAICtiAeeKt4%2FonJkTucvpSttKGkqWfxKM7f70mUC07YwZyihd2XltJccIhMj8I9hQWaY5GlQfGWg0UOtoa0pTpKSnYD4FQL5QRiGVXLsh5x0t6VFZSkwdhtJ5jrFQfDMHcs5QQQ5d3CZWoyuQI2HFRA5%2FK0WIrCS%2BQ0pEM7QAeKbKNil5K7H1tg7bTilqSJBAjoBNXGKFy8mye4bh%2F7VOxDclQ35o%2BEn0ZpzRJrfDG3l6m2vUNpG4oo4pP2KeaK7JPY4MtBQSUpIIiN%2F1psMErtiZ%2BRGqRP7PDvKaQCOffrW%2BEHRglNt6MnmglKlFzeY3%2BKPi1sXxa2AnCUkbAHsIpkXYcJN9jK5dUpJ0r36yeaIvZCMRcQlSpSlAOyvelcwJTaKkzGlSsPeQZK0vEccAj%2BNNCk17KxxHEmcFy9jBdcBecbKdOnj4qMZGaZzozbeOqvrh0LC1FRned57fWuZkg1LY4hC0HMGDX%2BFKCXby3QXmBwdM7j86N7VBY5NOyAWWAuLuNKmlatRSQTH98Vli%2BzZFxe0XL4fO5hyRj2FZny88tjErZ2Rq4cRMKQtPCkKGxB2j4pkMnHZJ4%2BWjcltFhgaF%2BJGVcMN34e42oMY%2FghMpsLnhQA%2FdPKkntW75LVowuDT0RLHsqMZOWm%2BwtxGMeG2KDW1G%2FlTzt%2B6tPHvWCeK1%2BKNOJ3sVye7iOQ8dGL4M8jEcFuGy3cW53Zvbc8tuJ46%2FINVhfHroe4KcafaLJxzINhbm3x3LMv5ZvRrtyYKrdX7zS%2FdJkD2qs2FS%2FJvspS%2F0kFvcBVbpIU16SNiU0l%2BOvssCvWPlL2Cgr900mWNog7wi4u8NvTcMhOkwFIPCh1n2qYclMpx%2BixrHCmXHUYlhqW0NLXqdbndBnrXR5qhMsb9s2hyNcIvLS3YxCVuCAHTMp9ietOxNNUKljpWbNZUsiwllqFEcpI4NNSoVyT6LzwhEBIMQON6ssPmJMwTUsgUbGkIPII4oJyaLUbHx%2F8AGIG8QaW3ZXuiL4k8UBXpKh1mgm6Q340RV0BSoGhSuZjYmheTQSEkLhW5A7TSYtehkH6MXFp0plQBFW43oaNHHkiQVJI6xS2lHZBNt%2Fy1ApKUjnak80QJt3xSYC0mf40SZaQ%2FF2oQoESOKGUhkYfYs1dqCySokHfnmh%2BQNRT0SGyuQQn1fpzRxkBwRKm1JUkFKp7jtWlCjF1MhRn1fFC4pkAGIM6kEpk8xJoZRotKyHuICSZBJGxM80sbdaYHv0pWCnmaVklqgkBmrdDao081njTI2Em1BKwOANwfetEVZVbscqUDPpUFfNE4FtiCQTMAQaXJNAuaGwQtCgdvzoFBrsILtnYHVBP6USILFslMnb6URBm4DISJ5296iZBq%2Bk6JVM9qjdkEg2oRpIB%2FjVEFivSkpK5B2NW2yDFSp9WoD371RGBbtQSFwST70Lgh0nS0X7b4hsmdHSvSRdHk4unYYZvY3SoEzsQacnY1U9hFF8FRJBTPPX6VCJJdCv3xDggxHcbRULe9Ca7pIKiNhHFQkddA9y7BO2w454%2FWhnIHI32MlXYk%2BopA7UvkxKbEPvYJ3Khv0NVbYVt6PDdgmCZNSmA1R4m9RMhR%2FwB6NwYz49mP3wQBEn5o4qkNbE13g3EgifyqyUntjdy7STq1R0gGoDwQkbkQo%2BkjuTNQpwQku74IIBNSwkl9A929WSTO3zFQv%2FAxcuBKlKKlCOnSqbop77GS7lMakkz0kmgcrKcEhk5dGFEmd%2B0VJSTAnOxg7dSVeveYg9aWAB7q6SkHWozEd6hKIxd3YSlRUpUnY1CmRK%2BvJSSCT80mfZrxxS6IXiOJ%2BWI1aid9jJFI%2BRj0rIpcYsSk%2BsoHXvU5sqUPsCXONeUVnzCRE7GCKX81gqKI9cZkAKtDpEGDvue%2F8KnymhRRFMTzYEB1KbhQI7nj60p5aLUE%2BinMzZ5Uht1BuNeknYkdu9DPJZTTNOPEzxOLDL83Gr8QEHTBjbegn5KQcMlOmcrPGvxaWsXjCHipBJUqF7p9p61zs%2BZt2gJx5SpnMLxCzsLq9uJWtWoE%2B09qxyn9mjHhS6KDxLGVPOKU0tKVGN%2B5pTnY9QRHXcSUlJKiO8Tx7RQDGB3L9KlKEwUj8hVoz5oprYJNwfOIcIKCN4Jg%2FwC9NqNHNlJegc7q8wlKNkjYKmCPejcY8bDk4pcr2Ygba0JJREp7T89KCUoVoCOatoettArTOtKgJ5%2FSlUPXmSoMWr3lwoIJBGoHrURsx5G1vsMNvLKUpKUzII9x2ir0OJHY3LmlIS2joOZiaLlekKlDiTvC724JQkBKD%2BHbrRq%2FYBaWXnnDpL6iFcCDVkL6y9fstNty6hJBkDmonsppPsv%2FACbi91iD9tYYfbvXVwtYCdPJPsKcpWXFLpm1OFZgtsototWHGb3H4HmOJIItT%2FlB4K%2FfgUQzl6DlhjbeIkXFy6VaiDK9ySOZPehTb9EtUXzk1tu4dYKWwllInWRwnmm4o29oTK2qRe1tmyzw62bs8NOpwJ0qdAH6flWlySRccMpfyDWH4%2BXFhallSlCTJmfrSVKxsMaXRY%2BFYqt4I0mBp4PSnQsVlmkTRnMjdmC1qQXCAZnn5rRpCLsdW%2BYy8pd0p1fkJA1SdyZ4FTmiSwpLY6TmJdypISsIQfSOsCiTsqOuiTJxlWHokuA3yhIA%2FwDtT%2FOiHfIOsLuXLtxTrjpbt0ypxZP4R896gMp2hziGZkrSkNEItwNLKJ57qVQOaKjG9hrLzjVtbPY1fKVCT%2BzBMgn2703AqVic63SHeIZiRKG7lYLhh1zeTJ2ANXPIFjxfQsnGzZYZcXYTDryiyxP%2BUfiV%2FKpCTWw3C3Q6wXFLdxxxPmAueWTt8VUJtdgzx9BDDLtL900tRCAp0IE1FN2RC79k2hb6VAzr78fNF8iGRnQq%2FhrardtSGtRcMqJ6fWgk2wKGRwdC9BCCZ6jkUpxfYSlQ7ThDbQVCIXPp3qKH2FLMIuWOhK1rQUoJ67zVuKBWZWMWcH80uqW2dRBCNtgPjvQ8GaFksk%2BHYeEoQ2lkokyRH6UUY0VYbTZqBT6QNwqf5TRlD9qyBWCUEE7md6oD5SVWFsl0oQhCUpEb1ox42Jy5kt0T7D7BvyE%2BkmeJFbljSOZlyOTskNpaJSEwk7bf801RvoFQvoOIQENhJKhHvImrivVFcX0AbxSEBQBSF%2B%2FWi%2F2BeiGYheeQVSTq49qpyronyMiV5j7YJkhJB2%2FrUSadsNY2yH4njHmoUpolXAif4UTmhsYtEZxXFbGwwO%2FxC%2BdSliUlWriRt%2BdEiNXo0pzz4jW2It4upgkW6UFDYJAAHG9DKO7NLxwq2aQ49mJLt8paVKMgqOlUx%2Fc1izSTdstySGmWsSbZx20uyhWlSkoX1lJ5n86x8kpXEizJviW%2B3gdqziT7TKD5alaklO4g8fpVcXdo3x6VFn4Tg6QgEwSduNwJ4q1BLY%2Flqy3MiZgs8qXl5hmMW6rnKeIti1xFkb6UTAdT2UiZmm4ZKLtox%2BRj9oWv32PDrHMVyHmpaMQyTfEOsvgykIWfQ%2B2fgifinZJcejNGUfRFEW91kzMScJu1C%2By%2FcwplwbocQRIWkjrSJ4m%2Bh%2FzUr7NmMg26EWl3g7q1O4HeBKkH91t391Y7HoadijqmKlKT2hpi%2BV3WVXNvcsnzEEiANh%2Fe1Cse2HKbrZWWJYI2zpS2CVADcntQTwlRlYwawxCfLKkw2RSViSZrJ9gTX3N5twAqZUAFJPFGC20tF%2B5ctm2XWVoTLauADt8bUyMX2hPPezZvJV4AUsLPmtqiJO4NaFNiXiV2i67RYaP%2BgxBB53oI6dg0wobhOnUZMGOaZyV2SmFbW4kNqAPv7UueVoOC2FVPJ0EKOn4mg%2BT7GEUxR0AEpUCZiD0pctuy4unZEipSlfujfoaByotxfdCy2wEyDqJofk%2FQUIO7YGuLgJBSrn4mkPK%2FoYDHr0CQOTzPSkyl9hKNiCbtWqAoE9NqD5KH%2FwBuh6xeeoJ%2FCe%2FFT5WU8CQVTc%2BkbpI%2BZqPJ9FC6Lkzz89RFVzY2E6QcsrsJWlQMHj5qubBk7dkutr%2BQdW220HmtUZIXJWFDcIUmQR7z8UyxbiyPYpizNutKFArUpWnnj3NROi467I%2Bt1LiiobJJk%2B9KkMQNukACYHbilSSLBBCCozqHb5qowXZB222lek%2BkxsfmmqF7INXXA2tSSAYMGiUq0yBC3WhxJUQSCNh0q2rRDx1AkGAVcR1pbjRByyAQQNun1qiBZtCA3BVq45p0WQHvtBClgAKH8KVLsgzWAkpSo6kk8zVFxpHjulKvLglUTz%2BlXZcmm9Au9dKW1FIOwMd6GUkgEge86UNNgA%2B8f1pcp6CSt0Abt9KkLCFqnr1%2FWlpWOSotRnESCIWII7V6k8gFWMU0hJBO3aijIKM60EWsUBhJUZAPIpraHJp9DtvExq3WCBvAqNlOSQqvEkKjSrn%2BFDzQHyIbOX2oz5iY6b8VHGy2mxqq8SCSV7Hudqpw0C4UhJdylJJCpG1DtExrY3N4pX74B9qextL2J%2Fe3AZJCjzO1UL%2FI%2BVeLnZwDfqeajZVyMVXUylSwentQc2Vt9jVdymZ8xR6CavkVVbG6r1adkqE8Deo5oZGa9iKr1MEFwzRBjdV6PxagKXKX0LnJpjRd3EkqgA0Dk2A5N6YwcvDBlQJ%2BaqgVEZO3YKpkT81C6YPdvdwqSDzvRUqJr2wRcXkJVKp2n5oSteiMXl5qBlWwESDVMNX0RW9u5KxqVx%2BlInLZsUaWiv8AFrw%2FtFhX0BpMsoceyvsXxRLKVFUBQ4M8VnnNt7H%2FAB3sr3Esf0nZ0CEwPVwTSHJ2U8JX2JZrUgLCnYIPY1TypDYYWVbmDO4ZSpKHyFbwPrWeeZDVA1pzx4mLYbfKnfNAlJExG3vzS5%2BQqLeJ1ZoL4o%2BKDq03DX3xO2%2BjVwPkd6ySytgUjm34mZvuLxy6UV8zJB%2FDJ7dqF37JSNO8zXq3bh71lSQDHv8A70iT2OhVFTXuILDpha%2Bo%2FD%2FKhBnka6Vgt7EyrUDqSZ23mNquhCzTbutA84gZUC6dcnrtHuafBqP8kNeSLWxBzEFjS6VIUJM78dtqeoQkD8cJfxFUX61x61JVIOw5%2Bak%2FFS3Znngiuwmh4JbC9ajCZ5Hq%2BlZskYrp%2FwDyZ3BD5l6VHUCBMSRMGlyr0SKSdoeNLBKCDvx9aE6OBtq2SCzdaDiVzoIEyeR0%2FrUH80iSW1yy0UD8Z9hyTUTKmm%2FYct8aSHEBAAA3n9Io4ydilBkuwrGH9aVBxc8HSqmWUXbk5d3it%2Fb2dkh26uXFBCEp3M%2FFWim6NvbHNmFZAtDgmD3bdzmNTRF3eIPpYnltpXtuCrrwKtOg4Y1LsdYRm4qDbouFOAgSSfx%2B9SL2aZ8FC12Xzki7XiLzX3hYat4lSlduf5U%2BzM8n42i%2BlZ6bt7dNhhj5DCISVJJBcj%2BFVKX7Ajk%2ByQ4PmZTyEpdeTqV77AxUw2wlMt7AMaW8WHBITwVf7Vqxx3oDJmalRY6s4tWKUs2yw6%2BRzNOckkJlFyZnhuP3eKXCbdLgccKjqUTshI3JPYAUCyIF4GlZIXM1tOKRa2Vw4q0RsFDlxXVR%2BaNSvoZCL7snmGYszg9o3eXKgrEVo1stq4SOiiPrt%2FtRJ0VJphTDLt%2FE7hRU6THrcWT%2BEdd6vHJvsJuPok68aQ40thlxTeFMKhU7F5X9f4UyTAsxwo3GN4o0nWUtkyQOEpHagj2X2qLBvsRAWW9YTh1onWqOHFTCRRTlXRMWJEItXcQx3GbW3StZdfdGokRCf7%2FhQJ26LbpsI5ox8O4uu1s1H7lbgtNQBuAefqZocr9IikuwplS7eViLcuk621gA%2FHFMjBIqeQkqLp62QlaVBBD4UBPajsqOS9MneIXjqX7Zxta0svIS4COsjemSSq0KTY%2BRfpKgwSBA2E9RS0yubHCL0AiYO8men1qUWo3sdC8bVKSpCARHM0bbfZHifoXgONgBS44%2BadHHH%2FcFqjxLKW06JUZ67TRuKXYSyMfNXRSgkOGZ45pbivoi8h2PLe5M6Q8lJ6Ep2oljQfzsL2pbUfMWskjseB8UccaQLytbRMbB5pIQlKh353rVBpI5%2BWLe0SmzvGwgJCgDHemxSKjHewwxiKEFKlqCQdtt5piiltFqk7Hrl%2B2BrK1AdZn86sJZEQ7FcUQSqSmASKgPK2Vji%2BZGWwppbo8roeqaqkFwRTWZMzi1WpCXNRVuCFSCKktoqWlaIpdZ1Ywi1Xe3t62zbJBLhUeBHA96VBK9gKcm6RrL40eML2J5BfusNeVb4b%2FiGllKeVICd1H5Jg05hzlKK2jQ7HPE5ZwC8ccuT5jrmmTO9Inl060Z4OV2ij2s0v3d0mXQpAMACd9u9cqbbY1qc3RaGWL119aV%2BYEKB3KjsmgWts3%2BP4tG3KLptbODXanAXFsoKlA7GKH5JXo0206JfhuOJbaQ2y4kT%2B7EA%2FWnJug1KVD65xIOsqlcyCJGw7bGglGfoJzkHRc3HiJ4eYhgBPm5my6hV3ZLnUbixUYW17lBMj2rdgh8i%2FJ7OXng09Anw5xa7zAj%2FszG0rV5J14Y%2BTJQefLJ7HpUUZLTJJyNzfDiyura2Njco9IVp0n909xNCm2xkJXovPFMFF7bC4KZcCNC9uT0JrStINxfs1%2FzNgKGn1mAkbR7b1XaEynvRAv8PUXEt%2FtUiZHx7VnnjNMH7RMLGwcLLah5hPAgb0ql7NXPVMt3J7q1JSw6pPpV6dz%2BVW6qrM7g%2BzYDLKvKU0Y0zt7VIpeyKy6bHEClGlxWpB4HY0SyIseffgAka9XWiUkyBewxAgITrSoE%2FnSZzd16IHlXKdCt%2FUOBQ8kREVvnlrbSSYg7gGiDWNgJtxfmhJcPxVWgoN9MLag4yoknXxv0pMq9BkRxZen1BUR1rLkdBwjshrl2SVEb79TxSXJvs1RgZIuevJ5maqxlMyRfrB0lY26E1TZKdBe1xMgJIXAParsGSXsIpvlnWCQs%2FPFQFwQcs3luJSoKA378GoVwJDbX0HRqAPtxVp0XSCSsXSgKlYgbHf2o4z%2BwJJXor%2FGsVcuLi3bRJBXq23pzkvQDVkisF%2Ba0HFmABsJ4oaLELx9UFPmFCY3FBN6ImBXHFtt6hBk7nmpFog4w%2B6XocKgEDpNNjOiAy3W47eXqXFajrBEmo1eyEiYQUoSEEhUxxNMj0Q%2BdUs3DiSohCUgfJ70udlx2LhQTCvwjiktsN4%2FoIB9IZLkmQJHt7VcZgqDsZqc8xBc1JK9z8UZfBjAOk3KZKtIgETQ80AetrU48%2BoqJIEA1adkBeKkttqEiVED4qTSoiQNxBYat1KCiklMDfk0hDklZDn3tKvJlMTHFGp0ug6LGN0UgAAk8969KeOFm71aYGrYR1qEHbeJbKAUesdahBz%2FiUEBK9%2BsnioXF07M04l0Cj252pnyMZ8z%2BjL%2FEAYghQiCZo1JBckKC6B31HnvUtAxpezxVzAOlSdU7VUmqLc1Qmu5URsqenNXyTB%2BT9CirgEQFAHr7Gq5ILnESNwdXBEHgGh57YPyIam5UCFEkEe%2B1BJ27BlOxE3gMyR8DaqAobru4B9QVtULGqruN5I6CTxUGKYzdu9wAr08c8VAZOxsu9Mjkk9agIydvNQ2KT05ooui4uhi7eBEq1EntQggt2%2BmQCE9x2qnJIJRb2gLc35gglMxuAaU830Nhj%2B0R66vtUkKBJE7UiU2zVFL6IhfX6kKWgkqVG%2B9DyY1JMgmK3qghcmO8GkSnZFAqPMOKpSp4ORHuaTOQ%2BEvRS%2BP48WAvyyD054rO8m9hv9FE5lzp5JKVLlUnr%2BE%2F2aTKQ%2BGWu0a65t8QlNBxC1oUopg%2Brf8AjWbIpIKWVekal578QnXEXClPBeoFJPEfFIu2Kc2zSvPeaH7hTyw%2FMqgTt%2FCgctlRhZqVmq%2BceU%2Fq1PI696tTthSxNKygMdnzHUoCUq4HShl2UoWrKwvUrQohw6lmTAOxirgilPktEZvFQhUpAKgSBTYVdsG67AK3neFTyQDzzRZGpS5Iwye7Ril%2FdKSpw%2FwNMjnktINZmhxb3QQZSkAdh1ockpS7RTyNuwzbvFRQ4DJmRJgER%2FzWQFu2SS1uCJKgVK3OwqhU01sLsJSFlSTAVuB2PzVm7D5FR2gm0VBxGqR6TIkb1QWaUZLQ6%2B8qbCQndB4BMfrUZePJxjsWZv4WjduQSOpIqyf3KJfhF%2BXHmmm93FwnSJ3J7UULukJnmV2bM%2F8Ac9r4X4IrBrUoczpctg3TwVBw5sj%2FAMQI%2FfIIk8jcVrlNRVNGeUm3%2BgDgmcHLl5txT6go%2FwCZUg%2F1NZ1tGuGZVRsZkW4cxS5QVOxbghSldABzFFHtB80X474js2DIwnCbhSGBGtzbUo8R8U5yRILQcwXNzj6mgVEgiCBsD14pTV9BF6ZVxK4uUt3K3CkTuT12p%2BKLWzN8km9Fr%2F8AfTOFNBkPMtuxqSonmmyml7HqP%2FUYYdnW6vrlptsrdfWvQgAEqk%2F5R1pceUn9hW0izbzNpwGyOXLV5t7FHfVfOtEENxv5ST1A5Mcn4p8VxVCuTl2WBle9GFWTWYMbBUtcizt1mC8QPxR0QCfrRY8nHbA4tuo9kswjFcQzBiAX56nSo6lKI2THc8ACmKdsZLC12WfYYq0%2F%2FwDlOFOhNshIU%2FcTsY5JPbbamuSYqONof%2F4ww8GmLZKk2iQdKSYK%2B6j70FBql32WVlVxNtbXN6ACtQ8tszJk9qfhhexOTIktHuNXxYLWGIUlSworeI3CnO0%2BwoZ%2FSCxT3bClg6nL%2BHW92pSU4ve7ND95pqd1fWNqNJKP7Kk%2BUt9EQdcDt26pKgo6yd45n%2Fes9jKSdImmW1FF9Z%2BpM6okGKZyvQUsd6RLcRaWkNNkaVSVfWf6UcoehUY1pkwtXBd4TarC9TtuooVHIT0%2FjTErVA1xBwuih4uJWBueooGHJWg6l5DnlvEJAUIUOgNXF0CvxQ7bdb8wkqSk8bU8rmGmbpMK3ARAg1P2LErq%2BCQfKKQeQfarbtlOVAR3GktbLWEAiBuI%2FwBqoU6GIzM0kqCXYE9SOlRETfoN4fm1BUBrSJHfmnQlbokpOiS2%2BbmmFoStxMRFN4L7Fcn9EkbzawBrTdI6QOvzTIULld2P0ZxZKTLjao%2F1b09NJFpx9jq4zakskpckGE7GQTV8ipV6KzzNnpu3acBuEI2JJnpVxdouLfSNYM4%2BLCLZx1v76AmDB1xPtUJyf2UheeL9ky46rE8RbRbHdKlK%2FAfaqlJIFZZN62aYeL32n%2F8AFcUewa1uBa4YwsoQkObrP%2BY%2FNY5ZVejTjpK32BMX8ULd1tnw%2BuLta3WcG%2B9XKVCPKunCFxHsFJFMjmUtNiskp3aNec4OqD9th7SxoSAskHgnaKw58lPTKx4L2zPBsOelJKStA6xye4rFLKo9nT8fxV77LswC2VahKiADAO6ZEd6XDy8b7N3xJLs2AYxZK8u4G95wQuFDee%2B89R8U7%2B4r0Y5ZOL67C2DYmzdLQ0lxSiQCCYo1nv0MjlTLgwfC3byySpoAgJgCeaanoaqLH8OsDu8EzXhuJLQpVuT5T6E9W17LT8QZrR46cZcjH5b5RqJbln4PowzNN0ba30MofU4wuBJSTKf0NOcmjKlNr6Nt8u5XKrVi5UyU3AADkiZPeijJMkcdO7LGODL%2B5ut6CfTMRv8A3vRNDW2yjs5YC4VKU22VAiaGKpGdxfIqZrBXlPoPl%2BtJ2APSlPs1w7J3heEkJS0tsJUN%2BKyoetk9wfBW2H217bHYdBVhRik%2By4MGbQ2EoVKhzJG1QKUEywWXdSUSSlR6jtSLpiZWhU3KYKVrmevUUfP9Acn9BC0vNCkhSjzzRckNxPbDyr%2FSw4QRqquQzgrsGuvKcSgKAMxFGECnnA3daQEjgUiS2WgkHR5R07z8UDeguLRD8dcjWYSTBH696zZOtDItt0V%2B7cKDqgFQPY1jU2aowdCvnfh4iCBTwnaGr92POWlCfwiPk0qbGRbqwtZPjSJWUCdp5q4PRU69kiZdlJAEzt%2FzTBNWw3h146wtKFGUEQSTUKyQfoNpfABWgSqDI5%2FKjTj9GdMFXN%2Bn1gL1K6jbmrik9l%2F4AFsFXN2g26St0mEpnnen8NFNktwx9zUtl1ISQSFA9IoGWkB8WvFMP6EEr3%2FDPFJyxp2FChG1ukLu2WFqCmo1GSIB7UcFTLlGtkl%2B6lu3beQQGlCTB4mjr2AA8OQtWL3KTJTG%2B%2FJooPYDluiZoOktpUlIiSYpwLbQwQSVOuJSDKydW9BNasvmIurUt1lqdZKhz1FLQcJutC1%2BFeQUBZBJjaNxU0HyZgJQhS4JTwI6UqdlcmMACt1W%2BnfczH5UEVZRk0tDTTyy7K1LkSZ2pkVRS%2BgXiL2tDC9SYmdyKPQabXQCxK9LzSWiEjfYfFLlFdjY09kaISlRcWkgEiJM7%2B1LDjKifqdUASADzXreB5L40Ni%2FCE%2F5tjsatRQXBHn3pRBlShvVPiDJRPReKkQqP6VX4g1EyN5yCoA8HrNVUSqj9jhN6lMytREcVOJVC6byCQVgjqKriy3BoWbvoJlQT81HFlOLXZkL0KMhwE8VVMqz03UkHUSIgxvVIpMSVdEfiX14mi4MLi%2FobG70qhSgRxzU4lqP3oQXebJA1Jj3qOJKj9jZd2RACinaTvQk0v2NHLqCoBUDioCMXLtAB3MVCWMl34nVr23%2BlDN0FBJ9jJ3EkiR5iZifp7UvkxnFAt3EEhSpVAAmRU5sYo2Cbi%2FBBhX5nihbDjCgLdYiknSVweoHWlSVBrXRGLvEVkr8t4pHY8ChTCte0Rm7xRAWvUr1fpMUmd%2Bi1Fsr%2FGsVSlDiQv18iO1K5IcpMpHMGMBPmr8wkmRudh8%2B1JyP6Dx7ds1vzXmHSh0qcQEyZExArNJm6GFM1WzbnFtlT0LJMHn93fjpWWU3Yz%2B2j3Rq5m3ObLheK1lMermB%2BdJk%2FbE5cSS5KzWTM%2BY2brzwp4CCrgjahTSVEhOHs17zJiqblSmw6lRImFfxP0oYxscs0IlH482VIUUGfYCaJRoTnycuuin8atEFLoOpQmBO8UM17Bx7RWGIWyxJCNUcADkfNFGmVkbrRDb%2B3d1JGvSjlR7%2B1SUktGSUdbRGXGwhRUVEpIO1FF%2BkZmvQyL7YIBWEpiUgK%2FjT1gk9l8H7FWlygKAVB3B%2F5pag3KicQpaXBDYWp4oP%2Frx7k0WRKLrjb%2FyMi10SaxdSVtRpWnf1HaNt6rLhpcmqKyvVslrGlIQAdQidj%2FSsq6sDDOTWh75iQVeoSRJBn%2B4qjbHKkqSGjylJKpcGnvOw9qjf2LzZtUgS9iqR6USVEGTPH98VaRkTLqyZct5Iys74lY6y2q7W4pjBbZwbPOjl4j%2FKj9VVq8dxTd7BnCWqKyczneYhiL17c3arp55anXFEn1KMTO%2FuaZngpLkw1FpbLUyZeXmLXtpasqc1KUFKUnhKaRDFL0R62zaN%2FPDOXcORg2FvJD5SA64TCt%2Bm3PzVy0yY4uQhg%2BbnFuJUt5RkGTz%2FAH1od%2BzRGDi%2F0bDZKvXbpy1dW4pLE7EJ4%2FOiiiTzKJer%2FiLaYPZm1Q7%2B1iE6FA8dOZqRk0ysU9kYt8%2FLun1uO3UA7FM7H6UKXI0uUV2bEYBmtvJOXGMeuFtKzFfsqThjC1bstnm4InYncJHyaeoUtMSp8pVElmQ7%2B3uLI5vzA681hDKiEtk%2Bu%2Bdn8Cf4k9B80eFU7YUoW6LQwrNF%2FnTF0vKcaWVelKEkhDKBsAB0A%2F3pkv8A3Gq0PtYlst6wxha7hvK%2BXC084pJF1cFWlKU%2FvGeEoEbn%2BtPxJx0jLJb5Ev8A%2B6LO1S3guEvuG1bjznoANy5G5%2F8AXsPrUk66GwnL2SjCsSZWoHzVKG56wTQ8mXJRfZsXhV23gGV2sSdWlTyiRbhXHmEbn3AH6108bUY2c947lSBWXUs4jdvYribp%2FwANtgXX19V9hv1JrPCLbbGZpK%2BHsG3WPu47mFm7cUhDQOhpsEw2kD8PPSKCWRthxx8VtmTLkvOlKyElROxqmyQg0ya4LcBu5t1kgwpJHvvRQWxr1%2FksLHCU3zcqBASlRg%2B3NOk7ehY5y3fo8y8Yfc0odToEmQVdKkHTF5E%2FQ2uHw045qUUKCusRNCiOLHNpiQCCytyErVuT0NUtgb9jxOKaVeWpSgR1B%2FKaPkyh03i6dPpd0%2F5gRtVqb9hximB77MDrRUkLRxG3WjcolyivZB8UzCtKVr81CSOhI4pfyJMFKJCbjNZYeUVvayR0FH866SKbXoEjPjtqs%2FtdJ0yJMUxdWgJxbWjJzxRWEp1XELH%2Br9au2KakvSHVj4yMp1IcuAhKUg7qg02ORCeXIwc8b2WFKUu9SADJOrp%2FOnLPD2C41oOYZ45Wd5rtziDRSoSDqkg%2FnTIyT0hST9lZeKXiqqxs3bxl8OIBhQ1nkxTUpLsbSStN2aBeIPjaytu6unb5DQSCCSvYDmZmlz8mMezPK5dGlWdvtBYlfN3KG7p1q2IhsayZJHP8K5ebyrbo0YIOPRBcg4tcZgxa9zbmNxa8vYU2Lu4OqPNWDDbIPVS1bR2k1m5SezUkm7fZYfh7jjmN5izXmfFHVm8eYdWQASnUo7AewAA%2BlZ%2F7maZojjfXRO8K1YtdC5uf%2FwBUx%2BAdBP8AWh%2FuJM0LHGPZeWC4O35bTaRrJEyTA44mn%2FJ%2F1DlmRKhautpDYK1pKTsP4VHxkVLLfslyG3FZWaShSwpFwUcTO001YF2irt9j%2FLDb7F4255ilgGTp4BoOdaQWSqN0%2FDpn76whsaiSNUd%2FrW3BFNdbMsp10bc5CyWX32lOtFRmZjgVvhD7E5pv7NuMNyW08LK5WyouBtKTx0EUppp2FCSXZYVjl1u1CQEEyI3of2VJr0Gf8ECm1pCNoO1Oi7QEnSsrfHspBwLhuR1EdKGb2KU2%2BitTkhVs4p1LYgmfiljloUay6EuKlC526bUqaro0BqwwxKHyklSzO0DmgLi6ZNLS3A0p2SNutKm9jtMkCVqBAJSFdQKG%2FstjV9zUvdcGYAFRy1QuUHegs3cKUhBCoggGaqn2XCNdhRKnHWwIJB3APUVN9Bj3yToaBSSBsD3psL9gqcfsB3W12VidJI3pU2EkEw4ry9JkHmlxl9jokQx9wguFSwffiPal5arQ2EX2VhdPKC1blI1AzHFc9mxSXoytLoQpZchQO096lv7LGqnFfe%2FLKkqJ2Jmh7fZT0ia4dbKX5YSFKHftWuGF%2BzNObJEGi2Bzq5B5opQoD5GepuA2DoKgrpIHNAOhMe216rS%2BFqGoAiPemQQnJV6BzpWhlTvlLknbY%2FnTFH6AVegxgAAxOwWo6QpaQCOm9MimDNBd5tbWL3YBlSnSAD1qTWy10RvHFkXS2kaRP4lDge1LnAtMjtuoOXbbKFQP3pMbe9BFNMJ37LLw%2B9F4wUhTRtm0%2BWj3PU%2FFNnJA0McIWXLu9cUgJ9UJ2Mc1Ix3YCi07DCn1p89aiePT7inBhS3Zb%2B7NkuFXp1fWquxbhvQEaS4q%2BbKSREmkyVMJUtDjE1oQ0gqXKgYkdTVBJP0IMsuutJOuUztI%2FEapogOJU00QlWtW%2Bo8SaXKD9Fxq9gy6e%2B72rTZXoVqkgn%2BNA4v2Ni16Ad9cLUq3Q2Uk7KJ6D5qJ%2FQ2UU0DcQ1tsFYdQs9SRuJq237F2kC0Fa1hxxWtI4EEVGmDkmq%2FEnJWo%2FiJJ435r10nR5tIQKzMcRxHBpTlYl5Gxu4soPQCe9DQtIQU6QTCvVE89KhZ55yoJJMfPFQhmm4EBUwOh71CWKi4KVE6lcfnVpktin3ogHSUxyd6tSYSmzMXe%2Bywe29XzZfySPRfHcAjngHkVObJ8j9CKroqIhQAHvQ8mDyf2N3LkyJPpHG9Sym2xuu8RJAIG%2FBJqi4q3Q1VeRJkkDcb1ApY36B7t%2FMiQB3oeaJwYNev0gHStJPBJ7zQyn9FrH9g53ElBUhUD9KzzsYDX8SICiFhW8GN96DkxscYKuMVIBJERyeZqcmOjioEXGJTq0qg7T7fFTl%2BynFgK7xIkkKckD3pbzV%2By1CyMX2KQklK9B0zE%2FwAaVLJZfxkGxPHCkL%2FaggQdz1oOSCSpaKzxzHdGohwJI22MAUmcvZqjgsoXNuZEaXCq4QlfEAzvFZ5SQxYq0au51zMhaXUFwEDUPSSAZ6fnWaU2acb9Gn%2Bc8xuvB4rUkncKUCdo7VnlfY6CtmsWZcRW46suXAUFJJ%2FFq27fNVzKztONPspPGrp4ElSQDEbCSKDtnPn4rasqXF7pa1kq1KE7A9Y7USVdAwxNaK%2FxO41pdUoACRAncUWx848VTZX%2BJpStKykJUoncbxQ5FqilUZ0V7ilsooWohOqOkbUDCRBMQtF6ZSkJVyd4mrjvsw5sj5caIRfaQFz6SN%2BeRxBrRjxSbtIS8Le2RO4WtkhJkImACqK1rx1L2XKCrRiLhSCk7kkif9P60mHit20KYRt7ouNepZgnYkdfeghLi97Li6JXhzxToIUnzZM9APmnTyOekF2rZN7RaVoSpG6o3I2HzFY2mnTBQ4XcDy1KSQDyJIpknKWjX%2F7aWwPevkNKSVJVzIkT8wKSotu0AoY3qFhzImTzmzH3U3T4wzLdk0q8xO9KoTbW6eT7qP4QOpNOxwbf5CM0XFfjtkV8TvEhzOGOlds39xwK2aFrh1oDCGLdOyRH%2BYjcnqZrqLFFdIqKcVb9kQwFy5xDEGbVmXnFKACQDzTP0Gsi9m1FlfsZHwhltKgcXcTueqAaT5ElWwVJN36ANpmm6u33PMfccKlAzM%2F8VxZ3Zug8cVovXIrb%2BKPtKeK1Mj6gd%2F4VrwYOW2Z8mTdR6L%2Bu88WeXrFu2YdQl1KdJE7x0rpOSiqRm9kCcz9dXTpeXcArJJAJ6dorn5ct9o2xxIunwsxPDrv%2FABDNeZnlIydhely5BVBvnyT5ds3HKlbE9kyaTFPstQSdJFh5czlf%2BKeb8RzFjN2zh%2BDW6POu30elqyt0iAhI6bQlKRyaZjdsvJKtIss%2BJ15nnG8Lw3ArNVvgVvFvh9ogmEJ%2FzHus%2FiJ9%2Fan8eWogY4cVf2bLZbzGu3LeTcrvN3GLuIKb66CtLbKI9QKuAkcknajjhlFCnDJyt9ExX4gYfhlqvLeWbpN%2FbKSE3uIRBv1gzA7NA8JJ3iT0o8mRVSLV3skGD5lUuVqcSuQCJO0z1FCOUn7RsN4bNuZjxZlvzi1YNpLly6T6WGxzP8AKdgxuUiZHrReOYcypxy%2BYw2xSpq2SUsW7SB%2BBPAMe8TNaZxldehcE47YlmzMrWG2dvlLDn0Opbhd0tKv%2FACOgcbcxScmT0hcINyc2iO4JjWvFGipwFJI3Inkb0EWl7GylZKLG%2FC3FmVhY9vmKvkgUvosHC7paS0pSog9Ovx70cJInCRaONX4faauB6lFoAnrPY01ulYSh9keZvV2yUQsJWF6pE89NqidlSVOiRXdybppq7TBcUAF%2Bx6mo0UC03SkgwFFM7HVE1SVIpq1Qp98NylTQWC6kSmTyKsU40MUYotC3Ur1J6RxVoKMl0CcSxErDyWioLSdSZPPtQtsOSsrLFMXKy42pbh7gHcUpvZXBFfYnihQSUqlQMqg8VRcVRBr7FHQtxPp0hJUDPHxTY5WuhjlcSrMczPdWbK9LitYJKUdPeaVLyJC54n6KZxnxJv7YrIWsEEgknpParhmTVsS8bfZWWKeM162lzTcrOx31Ec96tZ4i5%2BOquiINeP8Af2V%2FbOi4KkCITqgrMx%2BVOw%2BVb%2FEzT8eKLLxz7Qduu%2BbscYfQcDu20oDvRpUCJ%2BDW9eTfbGrDBqkaZeNt7jVviT9oFrTZRrbUkkpdBGx9way58ifQ%2FD4rv8TXO1%2FxPG7%2BzsbZJffcIbQJjciBNYptR7JK09lxvY0zaYfZ5LwxSXsOtXNdw62I%2B93MQVE9Up3SB%2FWrUn0jViaW%2FZZ%2BTUOMpcQ2SgOpCSAZ%2FSkZcskzRJ8u0bI5SsyCwj0nYBO0AK%2Bv8aXHK2KjjitmwWDNNpS2ohLhjcDaD%2FWhnodGNqyVG0aWhPkthCweu3Wrx2tlqNhW3S5bYNetpLf%2FAJAvSUwO0jt%2FvW%2FH5HpisuJvocYM%2Blbza1sLSdQ9Q455%2BKbkr0Z5wkjefwbskXLlsXEBRMAR1pvjTSYiclGfFnSvw5y8kN2xW0J4Fb%2FkQj4Fdo2Ys8JQ0yiEoHWKt7Q9BFuy1rRpTPTj9KWov2QOKsUpaUkthO1MiqRAQ%2FgzdwowhIRHEcUuVsFR2BrjLISlwBoD6TFC0w2yH3%2BXUBag2jSZ3pU2%2FY8F%2FwCCJbWVkAK6nTQEMF2i7dQ1bpn2pM%2BxmN%2BhR1ICQEgg9dqEOTpWCnFqLgJSSZmoiRdqyRWgCkysgp%2BKjl6Km2lokbFqtyxLyXFQ2ooKT77j6U7HGwY5N7C6UB%2B0ZKiTAmOxo%2BLL%2FG7Ar7KFQdJO2%2B0Utq1YY2UopUQRJ4FZJdkv0RLHkkvOIJKhG5oGrNMW0htieCst5VaeaaQp83G7qRuZGwntRPx%2FZWLIr2V2zZqbeSZGhA1GTO9YVjfs3c16MsOtC%2FfqXMjUetHihcqBnOlst3C7DQwlRSkT7cCtzWqRmnK0hC9WELKQlEjbbrSJt0SMH2AH1LK2EjqQSPrQKDGNBgEjEAWUyzo80hXWtUYJCp9i6bn73dC11wogAjt8CmCuWzNkvm6ZQhBHlLG4MCZqBksvm30XnmrCdJM6upnrS59kaIFimp198NjWguRI4I9oqpkjG9Ay1tXXbtNqhSUKUYMnjvSo43djMj9EyeAskt2rBCUoA3HWmcbE27FLAuNpeUg6gVGSKjVBWOFLX5zVuVANqgKAExvR45fZCXJUhNuttKIJPpV1A7R%2FOiEv9Am2BNw8sCdyAT1oJRZcY%2BwBjl05rQFQIPpSfmlmnH2Ov8QSxbfeX1LS0gaQe3vUAfYHfv0W7SHGtThjVE81NeyiL4riIU3brcacWVeoJjeaKTVBw7Gdu4paS44lSSTKp%2FdNZXJN6H3oc3rzd3CGlJDKQmZP4jUBasb36W0OtoaAUNInemSmmDwQd80ESVE%2Fzr0rZ5K2ILekwPjnr2qihBRmTKkjnczUINlrKolU79elQg1W5pCp4iZn3qEMBcJCUpGtZGwKjzUIZJugOYUQdt6hDI3QUN9hvv7VCHi7pAkEgRvv1qEG4vN9lSKhDBV7sSFKUZqBRg2IOX5lI1d59qpug1hoZLvwZGojeq5oJcuvQwdxHSnQVAUE8iCdg1%2FEYMajp5jmKTLIUgW5fwN1Eqjaeu%2FalSl9jPjBTuJahAVBHSd6umU4A5%2FE16FytAjcEmglKtDUCnr5KdytazJgGg5sZCQEucTgqhaQniR3pcpjCNXeLpTKkqAk8kTFKlKy6ZB8Wx5DZI1HURtvzSpZEil%2BivMVx%2FSlag6UxAImkSzv0aI4kyls0ZtbQl0h4KSD%2BEk7n5pc%2FIfs0wSXbNaM2Z2SoOpDiEr0ykk%2FiB52pLy36NNRW2a05wzelwhKLgtu%2Fverp%2FSllRx%2B0jXXMGNpLjiioLIGwCtjSpvY2KpFMYxdFxZVqBMRuYpE5FuK%2Bir8aebCSEpbWNxMTNXCKexM8jj0iq8XSFylJAVM%2BkRtWhKjFJyk7IBiTTmlZW2VEbAz%2FGpyRHhn20QS8aV%2BEqUDpO0cn3qpK%2BgGmuyIX1qVLOpMEjb54pZc3Jv8SI3tqsrdRoVA5260yEq2MxrdyILiWGpRqV6QZ6Vth5rporJLZAb9pDKj6yqf9O3%2B1DiTm7swSx2RpawJkbgbjtFOhGPKm%2F8AkT0EbR0KSY0lQjiaHJ48o%2Fx2iExsHEazBKupANKxRnF6dDccWya21y22ygpVpTvInYH2pWblN32Z5wldnq71CtipxSFDUJ4%2FOkNNA8WMLe2vMYvbfDrC3eu7t5XltIQncqJ7VqwxbXZrxul2TnxCx3Dco5aR4Z5ddbffUpL2N3rapF2%2F0ZSeraN%2FkkmmuGVehTm27NbtCH3SpyVEwNp4jpvV455E%2ByW3o2S8Oct2WWMEfzljBQleki2QRvq710saX%2Bsy%2BTLm1CJXuNZiuMcxO4u1OOaSo6ZJMfFJnFNNPRqhCo0WJkTC3cVeb8xJDCYlUxPesUvHamndopRS6Nm%2F8dtMqYYQ3pYfCJlKjz70Usrj%2Bgl%2Byn8UzjcX9wq5eeKpJI3ml%2F3MpdI0ReL62GMlsYpnfMGG5cwpwG%2BuF6ApX4GUDdTiz0QkAkn2rLUk9lqTm6Wi38wZmGZMbwLwr8OVvXOWbB1TDCzCTfPn%2FwAl06rj1GYJ4SKZHJ%2FpfReTx%2BPsmGI51DCrbwqyK%2B5d4c06FX9%2B3t%2FiN2NiRH%2F2kmAnvM1ojhT0pCYwauTZe%2BSMXubBx7KeUnWX8eSyXMWxR1em3wtrbWXHuEJEkE9TsN6ZHBKPT0Y5ynJ9k4uPGLBsNw%2B5ydkS4cVhC4GIYotOl7F1z%2BaGB0R15NKnm3SZt8eTSpsM5dzsNLDCXDBA9RVsY6UKafRotGwmScwO4zd2uH2aHLi6dcDaUIMqUT%2FGnQtuipSrbN1svZltsHeayThL6Xn2f22KXIVst4bhsEH8KZj3NbsUXHVi%2Fm5FoJzG3ljB38wXoUq%2BfWWrMHlM8r%2BB0NaJJxVtkT5viVY3mdV1cF515RUv1Kk77nv%2FADrk5G1L9Gxx46ZN8vYrqv7VSSQFLSmCd%2BelPxq9mbLGPotW1dLVytvWdYURE9D%2FABpnESo07J%2FYXUDYkkkGT1olBDXkbVFirvFPYUDrSFI2PYD3p6riLsAt3f7QeuDJkTSk6ZCT4ViA80tLUFMObbj8J6H4o%2BIE7HT7IaUUQnYdDz70F0xVsD3ClN6VNrkjcdN6NNehihF%2BxreLN0w5cBAFwmNfQn3o12GopAK5eCm%2FMKlIe51KPWm6Bkn6K5xxhxSVOshWgncDkKnikzS%2BiQT9lXYqtQCtYUkgTI%2FkKzJpvQZXuJXpMqM6QIgk8R1qp6QUFspbNeJNKFwlK4MwkA8%2B5PaksfZrDnHGW2w6tLm4EneCf6VljyfsODjWzWzM2ZFKW4lDnl%2BqfxcHihk5R%2FEXNXoqi7zD5brbinFKQlQ3T0E7mqjlknaEPx17CDeZ%2FwDuC2xDD1vaijUpieSK6sMnJbKeBJWglgua3cfsRlXHbguXzH7K0W6oS4n%2FACT7dKbetBxjL0eM2H%2BEN3SbFamsTXLYIEKZTwYPM%2B%2FSl%2FCr2DLHOx9guFuICRoUog7wKDJJR2uyPGvZdmV2HW3kH1JbjYjY1gyZ3ZtxYG1vo2gymyltphS1BSidz0jsI%2BtEny6LnBIvHB37dLbRhSnI22605YZS7FxYddvvurKYC3QZgjkmetMxeI09MvmEsExe2vWnrZ0epW5nj4rUsa%2F1ATzpdlkYDgSnlMlAngwDsU%2Bw%2FWtMYov5EzerwPwZ1D7KimBA5GxoY46dozZvFh%2FI6h%2BH9qENW%2BoDaI23rbBt9inBUXkfLSjTpSDzFPrVCJOlYTsLYKUg7D3qGaWV%2Bg1c2qW2QVBU7fWoB8kvsbsWpU4QSVJ6VA8T%2FIyxG3Si3WUgahtNU39mmV%2BiEKt0Kc1FKio7isLf2al1YneYS2loq0pK52g1RaS6SILiNmWgoFIBBpU0x0YV2CXW06JG%2B8UAQNDKi8JSInf3qV7BcESW1sylCRrOjrvtV8S4xSeiRWDSlIebSVAqhcE7Einxil0ZpJ2F2GlBkltRgK0nfjr%2FADq2mW6QNvLctrdjShPQUL10MxOwDcNKHMjaeazSgmxyZHcRYR95WQpLhgbjvS3EdGVoLOpL2ULplY2buEK1dTNaW9Uhb7II1hxct1rPpKzHyKRKCaHJ0xzh2FJbegIEkxQxwpbLlK2WI4U2tlKoCdNNbAogTl60%2B6oIIVuPis730MjPVexpcOAOgK4G8USX0TjILtgotkPpU6QhJOw2joKe1QtvdDWwWUrUsBYdJnjgntSpPZbh%2FqJBZaUNOqfUQNcnfk%2FPWpB7KcvQcxjEFOobNunUhSRqV%2FlpjQuMvshbiksPPJkLcSgrAjYUpqmNS1aPcBsUtXD1%2B%2BVLWQfKCjEe9GtbZU5WqQ7U8A68tagVHYSdkilTklsuMXQ%2BsHkNtqaA1pBkkVFvotx9hSxBcuErcSCCCU77imRhRMjtaJKW3Qwt8yGQSIO31%2BKYJi17AwvEoISyU9tXc96ByoNMiN%2BTdYkW3FlTLQkk9VfFIm23odBWgZjGJtvt%2FwCHMuJbBI1EdPaqm%2FQDiu0NLxDlpaoudSw2pBkGi4OiXZHBdOXSlXVwQtCQQkRFJsjQRYStxsqWFIBkwN%2BntRQgntkYm%2B8y4yw02AkJ3IA3VV%2Fj0XbWxk%2BQtYXrhW201TTQUYt7DweQRMjV27GvUcGeV4MxVcHUI2SRv7%2F71ax%2FYXx%2FY3XcapUeYmr4It40hHzJJJIPSgdC216Gzih6%2BYIihKGnmepO8x3PPxUboZjSYkp48JUFD2pUcgccabERc7JCjvPM7Cm3RcscV0JruwdpIjfvFLlkXoHgN1XYIICgepngmq%2BUnxp7SG5ulDVqUCDxHQ1PkDjCSGbl5voURE7SelBOf2FjQxcvtMgr%2BI6VSkmNQOfxASfVsAODQTTBlC%2BgG%2FiakpUQtITxzxS2qKjjd7BD%2BKpJnX6vel%2FMO4fYLuMVSCT5gChI370Lm2Th9AV%2FFzBk%2B535pLmycGCncbbVIDxKieADNLeVBxgrAl7iKlKKvN0JHvvSnNjvjIzf4mkFUOQRtJM0LbY6EPsrvGcY0JKpSkhJmVRS8i1YccG7KOzTmkteb5S9WxJgmeKxvIw2lHs1rzbnZtSHQq4QDJg87%2Fy4qSlYXBONo1NznnolxahcKKwIEH8IHaKGyo5aVNmu%2BNZ1U%2B5CXEqAMzP5j43oJz4j8eZ9SK6xXNaXC4FrRqjYhW1Jdvo0LZErzGEvyfNkEQY7%2B1Bxa7RKIpf4mgpWPNaG8EmNh3qOfpFP9shuIPtOKOl1pyNgZmjgn7FPJHpdkFxBSlFOtSNJOwP7x70foyyyZL7ITfKCysCADJI%2FSRTY9A5MrkqkRS7bklJImJ%2FWlyjQOMid7ag6ioerrB3%2FAL3oRiIZibEhaFkFe0wJmrMvkRk%2BitMTYJKttRj8qOPRibrohV4g%2BYpQCQB2%2BO1dbxZKrF5JNK0rMLdxKFpUNOmJkzWqfRWLIpdkntLkHSlStE%2FkDWWWOV8oD4TcXaJNb3aVhCZXr5G%2FPt7Vjeacbiw4Zq9D0rW8NKBCdM8fh%2BaZHHGO50DGKTtlrMPDwyyqnFHElvO%2BJsqTaifVh1qr98jo4vp2BnrVSjW4Azgm7XRrxcrU%2B6sur1OKEqIH73c0PGb2UovtdFkeHmRXMZu27%2B71M4e1ClLUImOlavFxvl%2BfRG0tN0yQeIeaGsQcawqxLaLG3SUICf34PNaMklJtLoPx%2FFW5EJwLDFXd42RqGrnaCK5E3Uqm9AzVM2OwlVvgNkpZcbDoEz79N61wywivxRK%2Biusw5pexO5JSsqbUYEk7j5rDnbb2RwYBbcWrSVOaQOo3AH9iqx55RehcZu6NiV3S%2FCnw6bw1ClMeIeaGgXER%2B0w3CyZSk9Qt4wSP8oA61s%2BNtXM045tdIJ4TZYnkfAxl3BUlXiJjTKfvrgEOYXZq%2FwDsydg4sQVH91O200z%2ByTjrQ3HJydslOW7W0wHDL422K2%2BD4c3CMWzC6jUhpcGbe0Ty8%2BY4TxO5Ak0eLxlBWD5E27Inj3jML%2FCxk3J1u%2FlvIzTnmqZWrVcYk7%2F%2BNduD8S%2ByB6UcDfes%2BXzF0jNDHfXY4wLN5RClvSDEGaycrfQ74JJ0XxlnOTiilCHdQJ6kSTPEUadF4rT2b8ZLzAz4WZWssauSlrPGJNAWDKyAqytlTL5%2F1GIT9TRRyNDE1OXZtV9mhBx%2B4xnGLx0Ks20lbzio4O%2B5PJrpf05OUm5dFf1JqEUoi3iN4iPY3j76mXGmsPZ%2FZMNJV%2BAD2435oPKyNsPxIpRtg7CcbD5aT5qAoyCon9PzrJRqmuT2XLlm6S6bZa1FZERPpg%2F2Kdicl2xM8cfs2Gsni8Le70oCXEbkb6YH%2B1aVJe2ZnV6JhaOcL8xUzt6Yq1K%2BgoQsnVjeeZZvNlZgjTEz8UyMmkVKk6A3nrauFJJJSPf6UAuV%2BiRWrp8xClAKA3AnYe9MUmyk77J3aPN3lopKVJD6I26qTTA4w%2BgXdNr1KSpSDAMxAj5qFuEvQFWpTOp1tQ1DbbqPipZQHxBfloU81ukieJCT7VcY2HCKZC3rpFypz8AuOFAwAsc%2FnRvEhnwfsqvNOHu24XcsqStkkyT%2B7t1AqnFJaKlipWULjmIpt1FwhKlfhBiIrn5HsPHJVs12zdjLel1uUIEcSSVDnpQMqWRLRqTm3GkvKeK3RpERGwG9CuSj0Q1wzLizXmuNpeT1jT0P9f61ikpdtEetlUYpiDqnUkqUQQRsYgVIZK7RmlmT0NMIxt%2BzxNh1PmHSsGBysHkflXRx5Y0NxKK7J1irDi328Wt0ww6A6ggzE7j6inRywXsufkqPWy48p4oxmSyt7bEj92xtGzb%2FAP8AjCNgr396z5sq6TLWZSLNwOxCnC282GlpggpmFT396Q26phxk07RcGA4W8UhIRCAmBtsfigUVY2WeTVMtzAbB1pKCqIEQAJiiMOXLv8S6sv2LzymgG1eYAF8be25rXgf2BFZH7J3c5WxB5kBppRJBJiee1b416NWOEq2NMHyhiNtiLC%2FKfS2CCr0yPberULszfBJtm12S8EU620HEqbEjaNiaYkaHFxjZvN4WYIm2FusIWggjYj%2B9qjZl4vs33ygoNMNEqQDxtWroGUaLTtnA7p3P9aNTdg%2FsmuHoKUNr3VvNOizJKMrtBe6Hm6dIOwk%2B1Mm6KbfsStmQlOrUSJkikjMWNp3YwxdX7NaSAP76UE3o0UQu2cSFlZUVR3Gw9qzYw%2BTWmGHgHGZSNJ9xTavQ6LrZBswWpSFKAI9uZ3rJli10Ni7RFVNoUCmPT0AFJL5IY%2BUS6lASYKuDtVEf2mTa3wsi2CjqCo4mtsY3FCXJvslOXcNS66PNTJgp3PQ7zTIR2Km6Y%2FuLA2y3kwQ0pW2%2B9O4IFysC4m0l599DQShKACZ3IFZppj8WiMXjSUhSSfQTEg0hfsfxFHrO2Ys8Wf8AKbEMoUgnoaCUUgIxdkdw1S7zLGZUKJOh1lSdud6FTAkpCFk0EtBCoDkAqJH4R2HvVGhtmNu2U3XmKCEDeJNRjI9DLMl2%2Bi0LaFaXVDYE8fNIy3QVWyDYYha7kkSUzB7%2FADSsSG6QbcQpdylCFAq4M8CtKVAyy0Hbt5LNii3U6CRBJiJ9quc2ZrbdjK1S0WXHnSULIlAB%2FEZ%2FlS6bGuUnoctvrKHLVkJUpWxIP4R3q4LYUotbYWfbebYZQ44FtBGoK%2FlTJAckyNYVZO31zd3Tq1JtwSDP7w7Vncd2FKSSpBG9u2WAEMKQpYTG%2FwC5vRXqgIpdojNw8%2FdSLZ3SgH1riBHtSG2xqlRIbB4MsIt2m3HHVQBq6d59qdD8SOb6DzLxQ%2BVFSFFAAJBgAUfNghMY0XG1s%2BbDJGlSlcEe1FzRCOO4oyyt15IAZRsiFTq%2BlVy%2Bi0%2Foi9ziMs3NwQC4oxuYMdNqTKaCi9%2FRFLS4S9dSQsL1azOwNJWRNj82O49k%2FwAeKVYVhJC2jq1JITvIra9oykJvGy2WykaRPHSssoUrLbbPba4dWpaApSY%2FeB3NSD9DHFJdGd4pWnzVklUhBM7VU1WhcY2LBYcbW4W0HSPSRUc70HwZ4t4pJBkjnbpXqebPLfIz0O9CnbmBzQyl7DjyasTJ5O4STQKaZJYWlaGy1lP%2Bo8TNEhLGzjw4BIB5qDIY1LsZOvSfxEq5j3qNmiOJLoZrfSJ7cDfeh%2BUJyobl%2BFEFQO397Ul5LdEtPQ1euFBKlapI355qicF9A1y8IEAlO%2Bw70mUaYT%2FQ2N%2BJUdQjed5qtv0UrrYPevyCVJ9PvMxRcfssEv34lMmR7UDk0tEBlxiKVJVpWU87%2B1L%2BVloit%2Fi%2FlqMKGkCSDxQylex0Ir2Re5x5IJJWRG4jiaVKSaocpJdAW5zEAQCsIVPGqlpr2KA68eS6VBC1JQB1PX%2BlJnmrSII%2F4zpVpK0kDY%2Bqs0s9dDNLoZP4sDq1KBTEQP5Up5mw09EXxDFmUhSnHEkgGN%2BaF5Gxiiyn8y444A8lLqQSDEkifk9qt5HRtgtUzWTO2YilLiEqUtMySk%2Fp8VnlJ%2FQTRpjn%2FNzzYuCtQJAI0j8R9zWZc%2Fk5PoGebRp9mvObiluKLkNpJ%2FegK%2BK0cjJL8u2UpieeVeYtCVNiUwNRHftVRhsuM%2BK0Qq4ze556v2wRIM77Rz1pqBlml9ibWaNYCtYVJMyetXRUYyltHisVKkBMyhI9cCeeKl0DkxTa0gc8%2BtyfL9RAB%2FDECkB48Mq2gVfPSk%2BY2NBMzMxQ8LZrUklUloh995ZLiRuSOBtTmnRjk7eyMXSwgaRvA78A96Gi8YAviHUpWDqBMx7%2B9CMIZftGXCUhQHQq%2FhRJL2JzcqpFc4wkpCnNSlDoCOfan4cd%2BjAoS9or%2B%2BSkqWEgNnrtBHvXQ8fDTtgtU6GHqTKRKieTO1bXFdiHi3aCtm4Un1JUpJ3Eq5NJkr0OsO21wkHVqSYHQ7j4rnZopOvZGi6PDbCbJ929zTjrSRl3DGw68hZP%2FwAlyfQ3HXUefarhl4%2BglKiB5pzFiOZsav8AF8QuFuPvOlRB4QOgSOgAgADiryuMnck0WoGGAZfdxjEWmkNjTIClRwKZgju4NhxVbRfuaMbw7LWXGcu4Qkt3ZRodWk7KPyKfmyOK2KUE3bKB8jzHi8skuE%2Fi5P8AfNc2Wbl2P5EpwV8WLqnAAsxyOlHDx4z6YtwbdsL4hmC4vkqt0ykfi3229qrJijH%2BIMlTtEcOtxv9qkIIGxH8aTe9BTztpRLc8JsvYZe4td5ozHbqucq4OhN5dtHb70qf2bHytUT%2FAKQa142v9Whk2tNF2ZWy7j%2BOY1c%2BJma7BzEs1Yk4peD2DiSpLCJhL7qejaNghHUxsYpuTya1Fi5TXQ%2Bzpc5X8MLa5bzliNziGabgl93CWHR99vCoE6rlwT91ZJIOn%2FyKHRO1VDPcugIJ9I1Hzl4i49nO9YuL1dvY4awnyrOwtm%2FKt7Jv%2FK2gGB3KvxK6k1pnJNbQ74qIxb4zctSlIU4CPxKn1b1hnhg3%2BOhco%2Fon2EY8pCk7lQAkRvA7n60E8NKkxcm%2BkbqeB9nhtnar8Ss82r68rWDiRbWp9JxS8glLKZ5SNlLO8J9yKkYJfyBeSV8Vplr2%2Be8Tz3mO4xbE1h%2FErh2NKRCEp4ShAGyUjgDsKXxuXFG7DjUVZ09ypjzfhl4V2eBWbk45foD94ondtPIQR07mu9ixRx43%2BzDmlznsod3Mzl%2FiC31rKlauSNpNcm77OndpV0WZl3FQpSNNwoCQPY%2B9KmndlOSXbNhcp30r%2FaqbWYAO06v72rVidEcrVI2iyhet3LC7JxOoq9TZ446VqSQgnKIYIlMxMCefmo1RAxh96lLi2oUkKiN4E9zUBc0gm%2B4p1BeASHB%2BIyYqFc0PrK7QtQIIAjvAq2hsWk9kntMR%2B7qQ4yVSkbbcjtRYpbsNzXoL3qg8yLthR0qHH%2BU9RW0T8zvZHnnzDiXBJA26xWWbJ816Iu%2FijYU5bqJKDETtBoY5Giyt8w3P3R1xWlTZT171Fkd2XGbj0VniOcFMF9lxSXEhJ1lQ4T296kszemFKSaoofN%2BI4RizLirG4Yt7udXlKMJUfY9%2FY1SxXthQdLZprnnGLm2Fw24HG9yCoqII%2FPil5IpbezLNmqObcYAS4UKWoAEwDvM9ayf3UUuMUTHJ2UDjGJoX5v49zsB09qzvO3o2O3plfXN4Cpzy1qJJI52ApfZmywoQauj5qT5hSOUySfr81ExLLby7dN3lm7hj6kFQBU0N59wP40XNhwSemWllSxUm5bglKgQBBPqM7VUpNvRpi4pUjc%2FImWVXy2XrloLKgmdt%2Ff8AlTLkXjhK9s2Vw7I6HGU6GVNq2OnTsT0pqk2OePdpluZd8NlO3CbdVuZkQRPJroRx3EzSUbs2myt4Q%2BY02Rbq9IkK0kz7x9adjwpF4%2FstWy8LS42UhlepI08bRTXGJfyscteGX3ZOs26CnggVaS9FrMyfZdyqLVTIQ1MKEmI96S%2Byubbp9G1WQbFDSGU6NEbRFaeacaFR26ZsXht4m3DDSQobDccc1IrY3I%2FRbOArU84lRnkwQa0UInGy3LVCW2NUEkJ2HenRerM80%2FR6tX7GCPVyf6VZjbb7E23QnSkp1E7fSoOxIZX6PNSpCifpwKGSs0kRU193eUJJB3A7UpqhvNDzWfKCVcg6piqJ8iB2K2%2FmWwWU%2BomQfagnG%2Bi1K%2BiF3Fm5bOrK0hKp1AcRWd4q7CHmHYULl9DhQZkbdO9HjxlNk5ZtW1KSzpAHG29boxoSm0SK0DdutakohIHQdYqlNF82Ari4U8t5xfmNLSokJP7worRUnbsDWbL1%2FizDLYUoOGF7cJ6%2FpSuN9FptKxPELK3H%2BMi1bJSySE6t1JE80qcXZohltWRS9fWjBr8o1raKUpUI5PakTdIrbYOy%2BAjAcfaW4lLywgoE8kGaHG0n2MyK1oxtGVItvXKniSpXWpFLiMYqhlS%2FMeUk%2Fd0GFE9%2BlJX0HGXohmY1AtrdiJ2T%2FvQ5FaGpr2C8HZLdq6%2FCigHdRP4jSseOrGSnTo%2BtXTc3%2BpAlsH1HtTlkbdCa0FrtZuyLZptxZUYmfw1JRZECn31NuJbQRCdhHU0tpphUGMKQ6G1vqRqCv1o1MCUqFsbxBV0xbYW0VtuFZKggcDtNDJ2BD7FtZwYNtvaXXPLGluPwnuauKQ6EFLsBhpN2p9a29CpPX8RqTiRwUdIchKLazM6QOYPE0sDluhK1uNPmOF1K1x6ek1YTdOmeM40tCHEXK0JQslJBGxqWXPEnsIhC7tRZbKZCdpo3voDm%2B0DsXdRh9gu39DqioSodPiqyzpFwm3LZXzZWVF11Ky0T6RO6vjtWNNt2aTBDiPvGgJPmHmeAJokU%2BicOBsYbYOh0LIXBSa1RdCLAeKrlDZQCmJ%2BtD5EqQeJW9CeHgm3LgCgoiOOlZ19hZIpPZ8FN3E2zgVJO23BqIpxrYftLbU0i3SpIWpQSPenRiuyllYALoSTun616I8xKKivyES6SklOyZjmoAm10Yeef3iBt%2BVQL5pL9jdb0kk6VJ%2BYqDOfL%2BSGbj2kxqgkQKg1SSBjj8H1GAOPekPsOxg9cRMqA3680D0C42wc5dpTuFAAdZik39lxjQ2eviQmDE%2FWpQQGuL5KtXr1DrtFMlkSC4MHLv4klQIAPXakvM5dBKH2DrjEUaCoqEQdzvQSm%2FbLcV7I9cYoUGA4FTEbdPelN1snxoBXGLLAJC5UO%2FP1oXMbHGRLEcUhC4WANwrf%2B9qVLNQfxorrEcaOrUh0JcmZPA%2FWkvJZPhfaIw9mNSHFGVkzEk%2Fz%2BtZpZUuxbjWht%2Fj2pIS44kdIJ3oPkT6HRxo9Vj5JlDmpAUdhvSvmi%2FY6Kg%2BxovMZQVjz9bg3oXJVodGEa0RDFsxtBtfmPAz06fSlyyMfw%2Bik815lSULCLkHTA3gx%2Fe%2F51HkVbDWuzVrOmax5j%2FwC3j0mJ69uKVHLbpF5Ko0rz7mVDhuAp8pI3JiNRPxWnRmyZodSNP83YzqeebbuPTJUQDwOwq6MrjH0yksXxoIU4svwgbCNjUsFJkIvMbOpILoTG2ocn%2B5FKcmGofZ5bY24hIWlWoEQoiNv72qOTLUadolNhjwcQgLUFGdzO%2FwCVBkx8ls0xzu9khaxRt0CVpUkqA9opbxyUfs1QnGStM9urkrTp1IRtGw6UGObvaJPGpKkyM3Po8w6xAO0bjjbf3p3yI5s4U6ZGrvzAtRUQU7yAOauKfskUvQCeIUo6laSDwOFVbLpkYvEytyNJJmTzUIrIJi7RWFJOgAjjtToTaXYrLKiur9lsLdWiSSIMdafHNNdGCbT22R16YJ9IVO2%2FNdHxZykvyAPbR4KlKlgLkkEdKbL7IH7LW6oNIUhxw7JETJrLLKl0iJl55zfGV8EwXILTyBdtoF3iRBnXcqH4T%2F6iB%2BdKzW9pBWyCYNhi8VummELWCTAAnn2pMcc5bQTjIvhjCmspYZ5hGvEHBBkQRTorJFfSCxwk3RXdwly%2BfL7oWdR3nnmsE5NvbDfiyvsbnDQg6EFRn249qBlfA%2FtCwsjsSSBBhEda1483FaRUk12Ji3CdSQoLJGxO29Ly%2BQ2ZpTbFksu%2BapBMqOwA3P096TsKEZt9aOmPhv8AZ7tMv%2BGOCZn8RMQwzLGUEgYpdKv%2FAEIvXlCUSB6nEITHpAJUowI5ro4PEVXMbObrhHs158WPtKMtOXmE%2BEbeIYWwtei4zBdAC%2FvDEQ0kbW7cAQB6gOooc2eK%2FGKFcVdyNKrq4ubh565uX3nnXHCtbi1Falknck8k%2B55rJPLqkXS%2BxooaiSpWlsdKCM5LoKEmuhFKVeYClxKFTBIHTpvQvI7snLey6PCnJj%2BcsaLLz6MOwK1T95xC9d%2FBasJ3Uo9z2HUn3pkVKWwcrSRdWavEZrMuI22GYHbuYbkrDE%2FdsKtVTKUSJcX%2FAPpFn1E%2B8cAVc8lqiRnvkuzar7M2Bi%2BxJ%2FNGKp1YNhyA8oLMJccB9KfeTTcMknbKy5JpUjafOWa7q6S47cOlZOo6Uq%2FSKfl8nkvx6M%2BCEkvz7K4wvHCuAoEEzueg7VlTaNalXRdOUsWUCkhzUOREQe9U03tgGzmT8UU0plWtRnTzv%2BVbMfRswtUbT5ZxJw%2BSVKCCIUAkbnmtGLI%2FZJzTLeRdK8oXRUndUOJSZ3jpWicrEqSEDiY82UqiDE0tFOK7DzeLAobfQ4gmQSP61CuKCtu%2B28hTluQNpWgDdPx%2FWoHYZtLyBq1GY7zNWWG7PF0NHQ%2B4FW6jCgroeh%2BaZjyV2KlFIG4u4thRU2vUyR%2BIfvA9Z7UM2Lboq7FrxaSspUqBG8yR8ihD5srzMuKuO24BcK4SAfegTk%2BkXFtlD5hxlOh5AdWCmQraR%2BXWhywl7NCirpmt2bsXcabeLbpQqZIHWBWPJN1QjLFJ6Nas4Zovbu1XbXLpfQmdOoypv68kfNDDM4gU%2FRqfmm7fUuFOJCI2EQT7GieaFdbDUJJ7RTGIreKzKynn3A%2BlJeVteh8cv2Rlx9Sl6FSsRMzQqddBya9mTJX5pgjUeBzVqTuzPkgi1cq2zq3mXG5S6CCACd%2BlRysGEUvZtRkfDlXD9opctjWCTHO3%2B1THFvs1w4ro6HeFOEIWGWngFtrAUD2UOBFasWLl2xuTMvSNzsGywF27UtqcIHX90GuhHFXaFQm%2BzZvIeUGb1iyccSPOBAIjeK6GNIyN09m4GVMostWzIbZHc7R9a1LCmrGRdaRP7bKDGlQDS1A9%2BtL40QG4jlZKGnDoCT0kCglFPsCbroi1vghbfISQZMkAb%2FlWWUA0y48vWYtmmVAQYkGKpSUSlp2TOzfUbptKComY70UJBN2bJ5KskuNoRcqKXCn9mTv6q1Rla2LlKizQ4UABaSmNgO%2FvWiKpUZpZUtsQeKkpDaklJIKgZiR3qzJJW9DVCyHQUxAB%2FOoNg3HsXeEo1QI4qDo5Ewbc2KnmVuD8Q39qpwvYwDvJW2hlaUkg7TEQaU4NFqvYTZs0XGHXF0t3QpspSAf3j2q4KwVk2RfF7ULUlSYUTt7UM9djvkQRw20U1bpUjRMR%2FYpmNprQEpBO2HlysglermjBCdw8tlkKQn1BBPFJyRpNkATboVctXR1OtoTqVPCqEkotBjD2UM3dzfslsN%2BUoj2UeBWiKSQPJ%2FxIG0u7exh2zeWpKloUgEj8Rj9ayTuzbHULJTl3BsKcwvEr3FjqYaJUpKtkmBxRwxR%2F1AeRm6USt7Fm3vzjj7LXktpRrQgdEk1knBXotcuNg5xwSAlQ0fh%2BKXydGhnt15lra29skwtf7RRjpUrQNEVxezXiK7ezShYIIUTHA7mkyi%2FQ7FKhpjTlvh%2BHtWzS0uoCYgDlXWaJvj0XJpu2R%2FDkuMpkJBWscf5aXGVO0XyRPMOwkoavMQxBwC1Q1rOlUH2T8mnxTkrFSyq6QIZsrYW67p9YDij%2Bzk9PcUuVVY1yrTFlXjbDQGoBkbzPP0oVXsDkmMbS7Qp1dyhAQudpPA%2BaJxXofGFjK6fefuDrd1KUocnf85q1RJpJ6F2Ltu21hZJUNoAED%2BtDJoptNfsQuMQWpp1KQkg%2FhnoKVKVClB3YGL61pUywCtw8mYj60Lkno0KLu2eWqGtTYBU6pJ9aiJHvFHFJdBvaph44m4yq4QggJOwIPFWsy%2BhPBkZxVwu6EFaigbkA8mlzyWMx60CVXBbUFehaUj8J3rM5apDfiZ8z5fnLuAhLbp7Hp%2BdHF2gJaCgu1rtnWFKOkK1JANOhJ3TBm6QNxC5U4U24BkgSewpeeXovHra9hKzWWbZaSmEbQT3%2FAK0SlxRU7bR4yoi5Km3NIO%2B%2FegsLi%2FZJ8MtvMdbcDiUuJMgd6bjYMppEKcemPQD29XSvSHk3NvTES76SIgD33qFxjCtvYitcbAgHnnarJJRXTGi3REggA80hqmHF%2FSGTj0jVEECdjS5Og0rBjzx2kKKY6UpSYax%2FsCu3JVOnfeOk0emrYcY0CnbgJMFR7%2FFC5JdFjBy%2BQkAApSgzvzvS5SsJQYLurwxJUIIg9opEpMfGNkZvMS8vUZQocbb0PLWwJQlYEucZ32XCudjEfSruxfBsjV3ikqgqQV8gk0De7NPxsAXWL%2BqFulYgajqpOSSQxEMxLGdlFI1ng9ZrCNhjbZW%2BKYwQomEqM%2FhBNDKaSNCxKtkHvswkQA6ARIgdaxSnF9grDb0BHsyup0DUidxueBRxlEdHAvYyczcPMSVujmDB%2Fvbeq4xC%2BCIEvs6jT5aHGyQop1KP5U1RfVFxwpOyvMY8QEp1pU%2BEkCCJkA9waTOe6Y3SKJzTnpLibpCyoyBCZjUOpmlzja6JNp9GsmdM6AC4Ae1KgzB4%2BOlXFKCtIGKpGqmbsyrdacSSlYKZ1dqvEm%2F5CM0a9GtuYcZ8xCtlFcH1dQf5itKjZz5ZXXEpvFLxalqWsgL4ieOtLUd7C%2BZJEJv8QKVAgxI4PT2oZRFS8tdUNbfEfw9VAyek1TiwMWVuW%2BiVYdipcZBWpSlaid%2BYqjapL0SexxBUJUlS45A5qElmcdIPm%2FVoKVKHMbxv8VevonzSejBV2k6iPUBsfaf50uUEyY5NMGXC23gkIUFK3P06A%2B9OjOioqiP3LKlJPpCh0ExHxS2%2FQVkbeQ75jinUpCTv80%2BbhxSXZTaa0yH4tZKWfNAKdM7DeaWkc6Sp02VziNm7%2B1UlCwOsiJrpeK0gHXoi71stBKQgxtzvXQUxc4KXYxSy62AmEBQ7ipaYKxL7Zanhphza8bGL3qEmxsGzevAjYlP4E%2FVRH5UqeO1odFISxJ%2B5xrGLzELhxbl0%2B6pwkmdRJ43rHN5V30W1XRsV4ZZSbsGU4zfNj0JK0hZHqPbtS8PktLZPkfseZhcVi944S2oNat44HtTPm5qkNjma%2FiDrfLykkFDbs9J4q1Uo2g5eU2tj9GXiooStDhUN999utYcidmVAp%2FAg26tlCXEn2EkVbjPjvoOmE8KyJjOZL1rDcEw96%2BvlAmGx6Up6qUTslIG5UYpbiyLG2bqfZx8APD6xxsZ28Q%2Fu%2BasMw1wvKbWoixW42CopB2L4BA1RCZ23rRgwSf5UMcaXFdlHfaa8b80eMucL1bjzjOXbZakWNskaGm29gIbHpAAAAAGwAosnlyviy3Div2aqvYUpajDZXvJ%2BfmsZn4SuwPdYeoKJDUbzGmQmoHUkroHLwx0LWNKfYAbRTYSj0X8iq%2FYTy7k7GcwYzh%2BFYXZruL19YbbSD1PExx%2FKtWPFB6iguUeL%2BzYvN2IYdlnArbwqyU81dWqXPNxvEGzviNyP%2FtpP%2FwCCggx%2FmMmmZMUIR2ZMcW3bZE8u4TdvXDVu20tx1ZCQnTzPSsMY8mOaOnOAWSMo5Iy9k%2B1U2u6dAv7xSSN1EbJJ7iTtXXXjpY%2BJgeXexti12u5X5ZUpSAFfTaudKDN0Z6PMLbdTpOkhPEdh8996XQcpJrouDKLDrbqDGwO8mZHb54ooyoX%2FAINo8nOFQaCgdKQDB2jitULqw5Js2ZyveaEhO8pGxJ2A9zTYqycW%2By1rPE1pZLZhSiPRB2mnk%2BMbrxA%2Ber8eokyJiP60uS3YLi0P8NxhS7gW6lFKFfvcAGilkTVFEgTirts%2Bhad1JO%2FQEe%2FeiCgiXs39vdoU4hX3d3qgcH3FWpMcZeeShUdBt1io3fYMkn2ELO9Spv7ndOJNoTsSN257CmQVqhbcURbHsHWyFrZQVtTIA3HTr1FF8Hpkjli3VFT4vYPKQ8hTawkpmOhNOWNLSNK8hLVFDZnwF2LhSkO7E9IG52%2BaRPJQEvI30a45wwZ4ocV5CyYg6dx2FcjOuTtCpzbZq1mvC3GlPFxClklUbwY5pfxSGY1J%2Fo16zNg7zggJWUncJI%2FSg4ly5J0yn8QwZ8LcCkqSd09IIqIelSIo5g7qFFISsAbmNuvTvTFla3SLcqCeE4A8%2FcSpLjYmd%2Bn9xVzzOWqAnK4uzY%2FJOUXVrQvy3HANwJnnv3pSTboXCEfZuz4c5BL6rZ11CwgQpJBncdxWiMX0aI4Ub75Cya6ybG4QgthMagRyJ3%2FlWrBB9oXOSa%2FE3Iy7l9LiELUyrSQCJHNdGCbjUgYtrVGzXh%2Fl8sKUSDqJmeZPzWjCnHozTfRtFgNqlDLUgCQNo5rVDoP5EWTh9gFMzpEfE0boW5W9DLFLBOhyW4MbbUqcER37IEMN8p8ulJB1TIrLlgqGp2TC1bCWQEJVq6GkdBp07JRlXDHX7tTqtXlJI1E7QaqF2UbMZas1rZQVKUEdIEEfFbcUHdisktUTV0BQABV5oTB2rVRhyNN0zG9SLm2ti4mAJRtsagKyNdDGwSptSi6khtIgKP73%2B9Qt5WxUKJXp4TPfioT5JLrYRaUHLchJlJ67xUHLKRlSEruiwUkgL5idjUDXIO3FohrDVIUISXgodJH9zUKinewC9aeehYCYSDMCqasYEba1Qmx2QEuAAc7VEq6Bd2Mra1W7cakyWEqlW8ChjFouU%2FsxxW8SfNYZT5gKdMxsJ96ufRaG%2BH%2F%2BB9hSQ2FI2pcIItu2PVt6MHKm%2FS86qRv260c1oUtyIut0m7s7sk623QoAifYie1Z330a31RLcUbZfw64wy0Cgl1XmOaeYP7ta%2BK4maMalyKr%2B8tWLmK2ljLzq2lNqWn8KPaua003Zta5IjdhZKuFtMrBkrAkHYe9KhF%2Bw3NIN3bLLuKKQXPMSmGwdvSkdh3pnG2UsiYAxV5iyTdG1LhKiZX2TQyaXQUZX0VtcPuXzqVupV5KZIA4msz2zXKNBrDkqcure1UPLQfUTHIimJIW3RN8YubeywawYbVrXculazH4UDYDemXS2IcG3ZBbm6StaSP2oTxvt80uC0aaa0wc%2FcB4hIKAepq2iC1u0t5XlgiYJ9opcdslCYQpKgUgK30j5q3Ah8yi1tvVcFTqt4SeJpSgol23oEXt0dCktgaesdBSpNeg5Y%2FoGF98gJbSUA7q96EZYaw1JZaU4sqbM%2Fh6n61cGkJyqxu9c%2Ba64mBBn%2BNOpd0H8i%2BgbdXQRuoo1xsO9IytItNt6QE85bj6kISEJJkGefzrKnase06HOtKVsoCwUjrRJgJfY5Q6W%2FVpEzAM8UfyMnFexVv8AbPJUoRxseKFd2U0vQXeWjyUs6YUkTIPWmOdei4xsGMXCkPGJJSO8VFO9UFNtLokVnePW7aXlLI1nad42p0ZUZWmRRKiTvMHnnb616U8qNnCqDCjM%2FwBioQbLdPclMAn2oZ3Wi4tXsbKdRqgkTHU0hxNcHoHvOwFEEAx3iaGa0HSewM%2B4QoqClJHUClpMHmBX3wCQF%2BrkjtUm0mWrYDuLrZRWv0AertWWUvsY4tbAj962JMoUQdp70PNDXJr%2BJH7vECkriSJ3JMfpVOaDSaIrd4irTPmJBnaaWx%2B%2F9iKXeLFKvxkAngTuP51XJASlRGr7GyBqnVAAG38qW5%2BxsERO5xqZHmlJ4kHmkzafsakiJ4jjifIWQ8NRmNW078%2FNZZy%2Bi0v2VtieLrQNWudJI3PT%2BzWPNt3Y6DitWQHEMVRo0B1WsmQAdx7T2rnzVj1JPog95jmkqShSiYkmePYEik%2FJxdhcbIfiWazbh0F%2FWN9UVuh5PIOMV2ys8Uz393Qpb11qcmAOke%2FvRPPK9AZotdFF5q8UnrZL6k3CU6huSv8AAP8AitMHa2ZMrpGv2YPFpxwKAxDWmNyV7kd6tpejK5NrbKax%2FwAQEXOtaLkKcIIokrRFOS6KhxnNIK3Nb5KlEyNXFEIyZ5vsrDFcXbc85DikLJExNU2ktPYccakrIHfuoUowUhJExOwntTFmi%2F5EfjIh16jU6EKHmAcAfxq4ODdsXLx0ttiDduvWkK9G25n8VTM4PaEvJSpBlla0ogOKQNiSP5VkYzFDlskds%2FpCEhQ3kcyBv%2FGob0F2lndbakhJVJE9OtQgsh9RUVDzCR06D%2B9qhGjBSnluDUQkyeeh79qgE5NGRR5ilIXKUwBz1jmr%2FQuOVpaQMdsvNUshKTCZ1E8H4q4t%2BjE7u2BbvCydZSmQdgOk0awSJ8LIviOXFq1KIUkEdBso%2FwAq14ouOmrBviyK3WV3zuWipIgGBzXQXQj548uNApWWrhCtJQ4FdjyRUNbgvosjCsEewvJ18Wm1ebevhskjfQgSf1qnKhMcaT2PMq5VS7fMl5B0JOr1cfNLz5FBbHtr2X26h1xhuzYSrykgRp61z6b0LhBsN4ZlVbymiULlW4BSSUmn4cfFWXKFeywLDIK3mkKaYWtO8yYoU3F%2FjSFWF%2F8A6brmWmlBatwCSPy%2FrWmE1N9%2F8BqqJLg3gc5iFovMWPuIwDKrR9d44kk3Cgf%2FABsp5cWfoB1NFOdL7BJPlnIpzviTuWMDs7jJ%2FhpbgXGJuNbP3SAdvOd5UtRGkJEATMbUzHkU%2BiSnXbJD4g4sHMMxfAcv2zVjg1kyLJlhn%2FxoQP3EjrG%2B%2FJJJp3IbjV7o01ucmvOvOLdQSVSqSOK5%2FkeK5PkgZR3YEeya%2BhRAaUU7Djr8Vz5Y6dNlWCrrJDxWSGzpB57VajErkwcvIz7lz93tbdxxcekEbqq3GNhQZfn%2FAGarwjyoizQhSPEDFGP260H14ZaK30j%2FAPSLHJ5A%2Ba04ZRS0VBOTKgscq3DVw2pduVAQniin48WuVlzhqvZtT4I%2BHDd1i7mO3jGqzsmy6pZ4J6J996Z4%2FjJO2HOf48UbNYVlu9xFy7xW4StS3nCoE9toiujoxyg7sUGUri5u3F%2BVqIO%2B3Pwe1BPHaGoPYfk51haFvJdRO4MfiNc9%2BK%2FSstFsZfy1%2B0aW23pI2lQ%2FX2oYeJO9ksvfAMGWC0ozx8x2rVHlHsP5JfZdeDWTyG2tRIVpiQef6dd6uV9xRPlb7JzbqfCkq9cpIJk7QPimLG2NhJtnj6HlL80oKfcdP77VEr0BlnHoHh5wlvfSqQZHX8qXLH9GdzX2S63dF4y05w6Ex6Twfz7VSk06YzrokNg8ttbUqkd%2BhFNUXdBfIyZWqC5CiSn96I2pscV%2BwJzTWwum2LpCQdKjuafDEkZISthzD7FXkLYuEKdt1dZko9wKdwY146doE41krzGi6yPNATAPfeqUWFUvsqnGskh1CwpCmgDEKB3323rJPxpS9hxT6NcM5ZDVoeISkoJlQCf72pa8Pd2PWL2alZw8P1KLjpSvTP4YiBWOaljdI0RbqmUTiXhpfXj7nl2ql6h%2BGJFZmr7DopvMXhpf2rhS%2FaaSonbTGkRzNC8EktIVNyXS0Qpvw2vLt5pphha5VuEp394ol402rQhZ5FwZZ8CsSVdNJNm6tQgnb93uB%2BdMXjyrS2SWRvs3A8PvBJVqy2q5sloJAUdSOB2%2BKdHw5V1spJvo2syRkIWDzRNuPKUd09x7U34muzRGcorZthlLL0qQkIKAAAEjeadjmhSy7ujaPKuCDyGU%2BTOnYkHmtsJX0M%2BZNGwGWcIDTbRCEpMmR7TxWrErWzJOTLdsGAhtGpM8cHpTUq6E5YOXRY2GoHkJBiOTAq7MnGmK3dqX2yAE6j1PAqmrHY5O%2BwInBHbpDiGxpcSJ6b%2B1IaZ0LS0PbHCXlJcSUaXEDTsJg0DjegrrssvLGX1OqaQB6JC3AD%2BJXaBRQxpdC8mSi98MtPuzSGSUgpGrad60JUZXnTF7Zhy4ubjQrUkKgTvwKOMbYrjyemO12K2mXQZVuCJpyx62E4I8btQm1X%2BKDI%2FhvS5oHIl6I%2FeuBlKvWrzFbAzyKW3XY3CtCwuw3YtlMwQEgDlX9KgUscWYYSjVcPOFIUomQBxUszPFJEhxRTirBCwEpJJPqPG9W9IZGDfZD1OXesaXGUJj%2FKTVGocs3DxZUgvJIB3IQd6hS7HllsXDc61AgFKANh81aRnySk3%2BIOxBxbrpWlsIQn0pHbelSluh8b9j5u1SbZsuNKacUNE9xM0wIH4o%2Bwi5btW3CWm0hEcQeppc3qgVGnYFSzLzgWUJQrieAaWO5poJum6asXFB2HVbFQO4%2BKtN9AxVsi9jg5N24%2BpXlW%2Bk6ipXShcadsZLLSpETVcWr16%2B3bveRbo1SontNZpz3objhrYPt8QtmDdPrUPSkx7mhhNJ2W8drRX19evYg8pouBKJJ0jjnv2pGTbs0QjGK2j5y1bYZSPMKlKkRH61aikE5tsI4X93HnuXLq0AAaatqypjXFb43bnlsJAZSNKe1XYFtAshTaQHTqjcjpUoZF2YtKbcVCd%2FruT8UMpUEIqeeN0EN629J6TBpSb9DIQtOxy7ci3KEp2WVc8iaKeVIpY21aAWLXqEBQDvmOxuAeDWXJkTCipAdL63GUgkp6z3Halxn9jLHLb5bUhIVqVEnaajmiNtiyr1yFyQnear5BfF%2FY0bfWVbqBEyR3qPK32XwQxu3A66VIPAiY%2FQUpqx2N1o%2B81DTZgjzlDY%2FwCWolRJTd6BjlzDmmNEnrVjJJ1odMu6ynSpMjvUENBlp8NhOokkjY1AowbEbq9BCUpWQZPO0VLG8aM7QghTqlSk7TG5NWnRUlaoJKuNCQ6CSkDcE8UXNgfGCgtKhIJ%2FPr7V608WJKWrSSDBB5qEjHYweKhJKUxuIHBpTlL6Njqga4sao2UNzA3mkO7AYwcfGo6iADtzvRW%2FobDoDuK%2FESkTFW%2BggFdqV6gQATwkcfWszSYakRi9u5C99567%2FrWWUWx8ZrtIjF3dL1Ajmd4FLaHEav70oSSNSVHbbmqbojIRiOKDSd3CkHtxP%2FFB8gp5KVkJxDEFysqBHUkdBWd5KdGhURm5v1bjWpW5M80pqT2Nir0iJ3V06fxKKD39%2FilST9hcGRTELkgAFOiJgaeTHf8ArS5rRUlWmQDF79YQoeaYMmJnYmuZPx5ethQxtlaYnip1KAUTsoGVHcRWb45LvRohicdsrTHMdQlvSCtCOEjgEUqeCb6NMIvopbMeblBLgQlRMmAD6h%2FWtODE6oZNcVsojNOcvLDinHypIBJkxEH9a3wxUhObMmjWXN2d1OKfDbqldlSdJ%2BK0RjowZM%2Bqia941mlxC1SVFZnfVMb8Vb0ZHbdle3eZbkqUSudRP720R7fNBy9IueRJUgFc48644slaBqHpPINSKtaMDk2Bn8U1BIEhX4edx8UPZFJroGi68xRTChIMkHb8qZwVbY1eRL7E1gqAAUjTEGTuB2JodoRKUm97HrDBJTqABgwCeaAKKsdC2W4ApKVGOpIj4qD8fOIQYC21NojRvxMzvUNWObauQebSIAJKQQTP8BVok48o6HzVuTunUlRA%2FCOR8VBK8atNjxnDFPLkIEzydtv5USgOUq6DLWCkuCEEEzCT12ouKAbHCMvKKVISmFEQTOw%2BlWku0U3tCreV1r%2FZKaE%2FhHQfNbl5b6fRWXO10Om8kLeIQbcKWofh5%2FWm%2FIpfx7M0srZ6vw4ccUQLbSgjb%2FVTOaS2IlBuXIFL8NHkOKWu3CZA0gK4oX5MFqynGV2m0ginI9wq1Yty3pSj8PvNNSTMufHJv2%2F9wjhmRHmVjS0RAkKk0E%2BL0zTixtLZamD5JccCELZXA9RXpEj60j4kOUq6Lmy%2Fkn1pQpkqb%2FEPTzV48E3%2BkMWaVUXZgXh09cm2atbRxbqh%2BBIkmryeK0UsLLesvCbCcBbtr3M7aLq%2FjzG8OZVJJ%2F8A0qv3R%2FpG%2FwAVMHjtPYOSHEjeP5UxTNVzbh1sBkJDVvbNp0tspmAlCBsBvHv%2BtPfjRYuTpWWRe%2BHqsmZGucJsWW0XjhBfdAjU%2BRBE9kDYe9Gsaxw5JWVGVmvaPDC4fw%2B%2FHlLKtYJkfineaz5eTVpDvmkQ268J3h5eqzBUNiSJj%2Feg4yjHk3QDk32DT4TOOlZ%2B6HT%2FAJwOPasMabtlAK78JXUJhVuopKjqMQT7VpwYHKV%2BiFi5G8HLLL9nceIOP2Sbhq3Pl4ZbOgabm63IJB%2FcR%2BI9yAK6DwQv%2BKLTor7F%2FDvEscxO8xbEVXGIX77hddWo7qUdzv27dqXk8SL6SGPL9IUt%2FCZQLafuxK1J%2FCBzvSv7Rp2v%2Fv8AyLTbZtHlfwzXgGV7LB7e1Lb91DjxCRtzA%2FX9KbLBNqipRZsjhHhe6qwsrQWyApLaVJSn%2B4g11MfhyaM8Vz7JHb%2BDup1c22okSCRAJoJ4GtexsIKKpCr3hv5S20Jtkoj6yYgj4pMoMOiQWGQfu5QA0Ek%2Fl%2BXWqUWQsTC8oKb0BLe4GxI%2BgpsYMDnsnmH5bUgpT5OpXQHfbr9aasQTkS60y64tIb0BBEbQYP8AWj4InyV2Lqym86kQwkNzBSdxP9eateOqszuab2A7jKbzThWGlap2HQ0LwJgyURFnA7luXG0SrfcE89opfwNdotTfp2HsOsH0QXGwFDjV%2Bs0TixkZy%2BixMLsHHC2Y0iZHt7VOLClLRYGHYaAEjRAO56T7UccbFxpEttMGQrTKQSZExtTeDC%2BZBn%2FB0JBKEJWmPw%2F0ovyC%2BREZxfLFtcJWUJIdP7p71T%2FaLUreig81ZNSnznS2hIIj1fvVmkv0b8bNY825IS4i4PkpcR7Cs08CeypZESzw%2FwDAFnHcEOILttTq08aZgzztRYPBjVtA1F9MBZo%2BysL15Ta7Vs6gY23TvzPetX9tGtCp66ZB8q%2FZUdtcUIuMOUlYcKtQTtyPalRwSTsRbs3Fy59mXDot1pwxkrSIKtA39q1yxphJ%2Biev%2BBzdoktGyQ2IIACYIoPhGKTQ3PhWrD%2FKU0wWjqJG0QDSZYUM5X2yXYHlh63eZ02gSoKgx%2FfFKeNUC5pGwGV8NU04ElsgbEU3FrQuT%2BkXbhtspptJ0kAb%2FFa4RoEk1iVPKlCZE779KMTlk0WRhzOi3R0A5NFGNiEmwqlhTnqIUG%2BDPX4qnrQyOFmNpBxawCUEaXQoJHUDpSZK3SNMddk5w%2BwQi4dddZDiFOKWExyZn9KFqg5yT6Jjl9aHLp9xlCWrZK4Urpq6gUUFsVKLosxLzFvh5ebQVqUTv1rSmkujLS%2F3Pcva7hZbWEpM6lEVWPstrjtBZSkhbyUEOIG89afKVhxtga%2BuvLaUhIBGkqmKTkKkrdEZuWUOLQ7JASkDfgmkyjY%2FHDiqMgoFCtI3HpAA4q0i%2FYTwNCVPBsIRoI2Kj17mjirYOV26CeKONOtG1lTam0kzHG9HNroRzaeyvrt9TZDDH7Rcxz071nc6NULaskdow1bYag61l0kc8k%2B1GBbvQqy%2BUJuUlsklJ3qBV7Gt21AS0uRq0uR2qmgkORdwz5ikF1Akgk8dKsVOXpEDxC98%2B5Ib0FM6lGeD29qRLs0QxutirguPuIukFDa1HQNW8jv7UEnSsOldCq79C2Q22VqBQARHBFSE%2FZbVOiO4jiqltJtEnytX4lRvHalzmHjxrtkCYaCbxxJlxkg%2Fh4HzSPjG5JV0CcZWplXlpSEtqJJB7UMlsvC77I6hCfPW4UhCPxK35%2BKoY5%2Bj26eLpKirSTsPiqZUGYtJIQlKvUenvUVsbZk475YI0pPWrYCdsGOPm6XtKgDBNA5UGo%2FQ0u7ptv8AZNJAj94daCUrGY20O7Y6EpcJJJ3M1cQpcfYJu7pCytYkEz13rJmlToqF9%2BgAAtT37QAt87%2FvUhr6Hc9DsrSSriBwBxVUwBo68405OowRPzUr7IIOXS0aSdxMx2q9EEEXTgSoRtB%2BtUP0%2BjNNyGmwVaULO6UgVCnjbGCny6snUFK45H6VClAZuPHWQRAEn4qDoxFmHdKkbHfiTzUBnjCj16EAJ1BS43PaoDGDGKHVuKCYAQDJM81A5Kgwl5SEiCAk%2Fh2596qStAmL2IpLaUqO56EVSRdMxauAgiZGwkE17I8MOZRvBPq356VCDN4gaj6lD371C%2BT6BLyjpG8KnjvSJXex6WgPcKEq9Sp4qgogx50IVuTH8fmlzkgoPYEuF6jJI3PTiKTN6DaIhiCilSgJT2HtSEx8MbZErxwqKpWTMxvxSpPZoiqI4%2BpSxEzJ%2FsUJJX6IxiLCnSpMrUeelBOP0Kp9EJvLA7wSF7k1kpjYYnLsj7lkXEJCUxIJ70Li%2B6NfFxXRHL2wcA2kzG9JkpewllrsheI2amwsJTpWe24oGnQ6DUnfZU%2BOMpQXQPSNUhM8n%2BzSJKtmhOmUxjr60KdcSsJG8np2g1gyQU%2F5aHlD5kxdQS7JCXlIKeYn%2BlFgwP8AwMg0lbNesxY3Pn6lrPIntWmuP4oyZZ276Nc8z44%2B8XvXsJPFPgn7M%2BVRa2a%2B5ixN1SnQBpjeCdz701vRzHStoqLFrxxKngV6kcd4pMpWZlld2QS6ug2Fai5p6c70ePE5OkXkUX%2FF7A7926kA6FDqQTyPcCteDCvbAUb6Gbd2C42VFR0CYiRVZMTi%2FwAS%2Fhb6HKbklaXdQAkdd%2BdgI6Vnn48u2C8fph1pSnUq1gKJ54pW%2BgcadtBqzCQII2Jggjke1SgnaYVZZRAlAMncTwKEZHO12EWbZKkJJbOo7Anp7%2FNXTNC8mPTQRaZKFQApUEAnsJqJDYyjWiWWmHKcXAIjuegpsVoF0TXC8C1lttZ1kkHj671dgLROGMqOumQypQA4Jnc1EjPktsNW2TyXE60L0mSYHtxVkhaeyUYZkgPQVMawRG4%2FKaJQb6CzEzsMgwqFtp0pn0xMJjn3NMjGS90ZyY2fhwHi35dqoI4G2xrQstLbLscXHhW4EAfcndYTuVJFVB43IpsHr8NSjSp61C4J2KZAHzWv4F2myWZs%2BHoWfTajUDIGmY3qpYYLtkJrhGQtLqZYUhvkkp4%2Bk8VmjihF1F7IXbl3I%2BFJ0KufOKon0o5j3mDWuDd%2FkQvDCsLbtmg1gtomwSvSPMUJcWI3JV0%2BBRuaRIr6JIxlND5T5jYcKiSpSwZP1oYS5Mtp9slmXcgNW92MXXZNOtWqfNQDuCs%2Fh%2Bd961fGVVnuYsoquW7G1daccWlsuLJEhaiST%2FE%2FlQcXVAqKXRFrLIDAU%2BwppMODtAJqmq7CBb%2Fhm2HQ35K1CTE9Pn%2BtBKKktkMB4YIc1J8lBVPUciKT%2FZ42aYYE%2FY7w3wWaxfEWmBb%2BXaTqdKk8IHJmmYfHcdIqWFJdiuZvDpGLPs29pbJawe2R5Vs2EbATuYP7xma0PFJehDVA618HUFCUKtwRO223H7xolhkyg%2FgHgpbrxEOuWhLCDqJG0DsKJYPslFn4d4Z%2FesUKw2ttokJgDbSKuGKnYDV6Rshl3w4QllgG2gQmdug4n3rYm%2FTF42lpEncyEhpCgGfVMbcH2q%2Fj9vsH5q0yGXGR0uXLj3keWoTBjikzxl%2FO%2FQTtMknUkrtiTzKht%2FtVxwk%2Bde0Sy2yWlCZSz6BABimfGRzh6DFvk%2FToISv8UykVTxsW2rJhh%2BT2nFNQlcbEdSKuOJgyrtEwZyH5jX%2FgMnnuafHH9gjS88OXlJIDKSngiP4UXxohB7rILlq6qWVhHTrFFkg6KUl6ERlNJ9IQEn43pHxoK2E7TLq7bSQAAffrS5Y2HjWyYYfhqkkyACkVcXSpkkpXolNth59P4hpIjfkUYtkkas0FsjQB3FEot9BcX2Dr7CgtPpBPuBU4jcdrsrHMGBl4FK2ySPYGkSxM0fKo7KHzBkdx55xtKHEBSoAAnc1nlB30Z8uXl0bheE3h6bTA2bb7srSG0zBMTW7DjVUVhyey2FeGdlf27hVZhLraSBArTxaVFyyxb2ivbXw%2Ft7fGWmvu6kI3BnqZ59qFxsxxzSc99GxWAZEtgwharQISRqBPX3oVjR0nOmqHGLZFt3kLWGUgkzAoZY%2FonyMrzGcmMNoKFNBS0mJ00mUELeZEUwvJyVOOq0KSQd%2F9jSlhX2Csre0T%2FDcBSw80hLSlGRuKasUV0H8n2Wfb4C462tGkggTHejSvoGfGrWx%2FaYGq3Skr23%2FOpVCG37JpZMKKJAkdTUuuiJtdB9FqCyPLSVSJnoKoOE3a2eYFgLr%2BN2bwVrS25q3P4hQKG7NGSaWmWfitoLS0vHGlBEgJA7SYNTIBinbo9srW0tbRi0YdIgCd5k9SfeiTXomTK46H%2BJ4iSzasNEolYQDx8xVuSsVipuyZZeKg06%2B2SAEmPypkGMnFJ7C7QV93lYEr2IAphFoAYuG23FAkgRv%2BVLmyQVuwYlCFNpUIUNPfmkzv0aBO91MMoLYbQTxFKba7LitiuGFds2X1qg7mKdB2rQjP%2Bhnil%2F5gdWP2alIjY8UM2yYYW%2FyAtm1qumgtQ1ncfSlrbNU9dEicdQghtxIhPbenixtdPqR5aEiDGpRjpQyk0QHYrijYZSpJBeUnSZ7Up5QoxbegCvGdNotgOFR07x%2FCq%2BUL4op2RFp9a3pC0nfiaU8jDqw7ieJu3qmbdC9LaExCep7VTyemFwo%2BYeKWnkAoDhSSArkxVfIumU0%2ByE3F7%2B2KFKC3Tz7Gs2R%2FQ6CpDFu7ZaU9qWkvRB%2F5qcmDN30RPE7oPPPrJ9PAqWHDoEocRoCUgyeZ7%2FNQszQykrCytSoPaKhEh5cXLKW0I9GuPwg7D61LI4oAXV1CvKbUFHYknpQSmHGL9DeClPpgEkbz%2FKlyl7HNNDdlKC8StaVJBjnn5oe9jVksfXNy0yBqWAkHf2q7oqcN9EXuLtLi1lgmPcb1izU2MS2DXbolW%2BkHgTQxYUmvQi5c6UepUxvT7BSsY%2FfCpSdJJjoaRJjox9GaHEiVEkyN%2B5qi3ChPzkgKKlEI5JJ%2FSqbrYUKQwNyHSqQYnb2FVyQbkhdDo0lMqB6mf4UQoT1JUZJMHeewoXJDcb0LhYQTB9uNqD5GGZPPl0J%2FDA%2FuSaCWV9EPGHA1%2FmmYA7UKyspq%2BzO6uyQAFwOT0ollKSRgFFaQdStj2o%2BbCFkPpSkKBJB3B617P5EeGlg%2FYQYugQYMnbnrV8kKcGZuLBKgQe%2FxVpotQlegLdOwTECD%2BtIk7NKUn2BbhxQ6EneaCTorgyP3T2gACEhRge9JY%2BC9AJ68QoKKyrbbY80mUvQxtJkdu3isrjVHSgsuMk%2BiN3IO5SSV8bdaTLsLYMU3KzB3G89zVDY2%2BxmqzKyVqBKdpq7DBV1hWtJA1Hqnb9aovmwMvBDpACdKgJJ7iguX0EpkevMDOhRASogcARQStklJMgeMYDAcGgITuRO%2F980DS%2Bg4v6KSzLgjqg6PLSF8aU8fSs%2BWKQ5ZpLo1xzVYLQbj1nyxsAnpMb1keNM0LPKrNbcz4cs%2BetSCVDee0TBM0LVMt%2BVXcjWrM9tcF11CUqbTOqIJMnoe1HxV2Ycme%2BjXvMGC3SHlyhwidyOOOlEZUrdlTY3l99wqBbSNt0Rz7VfG9CJZfRU%2BLYJdrKyWXEFWw9JrQsKUW0xCIBiOG3FutWttSiBIniaySiuweCuyMvWLroUkNpJI422rZ4%2BKVW%2F%2FAJGRcvYi3g948oAlxQ5MCnZXr6YclJKw03gLqSFQ7Ch6ieo%2BKwPl6ZI5ZLbCbeFvCEoClmOJpuPp82NcoSfIJW1k4k%2FhUYEEE0mbitJCJJ3Ybs7RxZbhtQAJ3NIopIkNnhbzqmk6DI6A8%2B9N46odjpdkrscHuFKSVIIiZBHB9qvjQ5TRO8OwfVpASTPzpP1FEnspyfotLLeXVBxJDQSCY09Ke8vIqOWXsv3BMqF9KT5SW2jABA5%2BlA%2FHa7GK%2FZM2MgLIKwwYEAbbCgUGvRG2iVYbkDyVJ8xsek6tk7TRcn0Y8mZy7LFw%2FJw1NPFoJGncg7H6fpVpSQssHDsnpWITbkTAjY%2FWKdCN9jsdB9GSmvwqYUSE7yIn%2BdM4N%2FxGzhy3EVT4bBalvi2SQQdiJAneIpvx5EuzI1sYK8OVIKii2ShCt4APNDkwzl2QcWuRFylWhSZE7jZNXjxOvy7ISzB8mFkltSFEiZ2O30%2FhToKV0y7LLwjLYZbS2pIV6okj8IPFa1j1tFNk4scBSIKUBICYEjpVxgolckix7XBz%2Fh1haJQhCnV%2BYsFO%2Bnpt2pgqeRpXQliOVW1OF0NwoRuBxtVuLGOa9AVzK34EKbKnDzHWgr7E5MroN2%2BUC4w35jCS4O4Bn2rR8SStDcbtbFxkhXmBZY9YOwSOargE8iWrJOMpN4bZG0Q2rz34U9MmB29qJJLoJZDFnIbToQoMo0QIBSJ%2F2ou%2BhcsgQayC15WptlMzEHfejeNinnD1jkgMtLKWFB1RjjihcWD87JDheRk%2BelRaOoGOJn2oowTWwZ5pPou7BMqILTZ07QNX5Vq4IJQSCN7ldIYXpQkT1jdNFoqfRD3MrDWSpkgcEzJoVBCaDFnk9tyP2S%2Be1WkkMUE1ZIGcm61EadMERtxV0ifGx81k8EhCQopnjt9KiSFO0yWYPlNtotJCCkat6tIFyldUW3hmU23G0gtBJ6yOKekg1Fd2FnslNlEJbXE7bb1AXKmQjF8hpV5iwzvwqRVOLfRUF7K3vskBpatLYR3Imd6VKLTpjVJrQNXlnyxC0qJA%2BKFkcmfDB0soBDZHuNpoHAKKvQ%2Faw8gEABRiSeanBBfGgtb4asjdJVPf%2Fait%2Bg0gpZZfduy4ggJSATvwat2WkMbjJaVqVqbieu9U06EOd6ZGLXw%2FbdxhkKYVoK4%2BtCsdg5GktG8WQPDdhrDWl%2BWkK0ARGwrS9OiYYL47ol4yOLd1wIbKlEGYG1ExvFLRW%2BO%2BHV03iDS0NpDeqSQnc0PFMTLA27LB%2FwANSjDsMsQhTam0QQf3R70k0Rk0qaHFxhaVMwG07DoOahZXeMZfadJgHUTzEfSqaTBcUwBh%2BWFJu1NhIkzVcEWlXRI7XKq2HmleWSUntxU4IjVkpYwzynnFFv0xsTUUaJGNaGF22VOttNgAARA%2BakmgcjXoOWmG3KrVOkkmYKY6UplQx32SRu0FnbftVoCvmABVATVOoj7BHWvviC0SQlSVakzz2qDIRbauw9it264hKFtRqWdj196VOXo2J10hrZvJbUpaiACqOKqMq7BaTEn7hhV9atKdR6JKhvM1HJN2WoatIsfBrjSw6DLYUkQCNzT4TM2Z%2B7D5SrQ1ClA7QR0FH8gt5GyNY6tTYUUetRUAd6TOex2BWDW3gk6XB6gPSJ5pJoaFVOtulPmKSuN96hQzvni3bQ0YIkAe%2FwA0y9WRV7I9brevFaVmRPq%2F01nU23TGSikSC1tkNvqePqSE7E9KfJUC5WDxdf8AyHSZEHmetC3YUYrsTvX1BpbqjCgnj2oW0uy5R%2BiCYrii%2FIDgcCFDYJHMUmU1ZePTI%2BH3FpBTIVuSkH%2BNV837GuN%2BxW3Ck6lB0SdpPP5VTYPTC6NFs2HHFpUojjimUltlTk2wJc4orzkrLiW1cJSk7RSJ5begoRT%2FAMkWfuAHnFBSion1b8b0PNj6BL10fNUpJ3PJPX6UuTpFWBLl%2BVkfhV7CqjOw%2BOrE21BKQte6j0HWjAMlXSiqEwlI2FU2QZuPEqUhIUXD9KrkhkYOxmpSUpJJmDO6uKU%2BxsexNd0IUhKQXe%2FalzehsoXsXtyhttTioSkdCeaPH0V8a7ZFcQvXLh7YEbmKy5uVhxVaQOcvC2ConXvtuaSv2N4IYfeNRLipk7pnpRtKrI3Whq68pUFKQgzA36UtsrmYpcWU6dQQnr0qq3YUZ2x0BEJnp2%2FWnKBazbpg%2B6uFFXlhaQB79Kzzk%2Bg4xtWJNuEkaVGTMxJIq1BF8VQ7SCEkaivoqeauUqAFZDQJOlPahyOhsY0NDcqWfSrUO4H86ySbDPi6tK2zOrbf2PvSeTTIZh8GZ9UdBvFEp3og2U8VOQjiSd%2BtMTIPg6VJSNQHyeadGauyCCXTsmTCZPNexPEJWOkPpSCQTxI3qF8GLpuFKTKu3QnaoRxYxun0kgnfbpU%2FwFza7I7dvgwOQPfilvrYUZJ9AC7uhpJI1nckUputhojD9wCYSEkGazsOMPsFOvpISI3JkzvQuSRqUEtjVagogKGx70psIbFhMhQJnjnn4qJF6PtAJJ1BKdhHxRqALaWj3yEKBUo7jrGxoo417Ja%2BxByyQRrTx9KcsKqickM3rBlTRKkjeJ3%2FAFpOTHXROSIjimGNOJWlaNQBMdgO1KlibQHyFPZkyyF%2BY4lolJPA70iWBDYZG0aw52yk8t19SGlJc1GQJ2H%2FADWaWJLYcroo3G8guP2rulpxIAlW3Pekyx%2FQtopTFfDIrKh93U1IIV6T6RPJFW8DXsRLLxdMrDGPCFRebcYtFhokgCJFWsetjIST6K4x3wecU6sLtJQdgdEEnmKnxoJxTKUzB4SPIUtpbSigD%2FJsT7Ut60jFKOyicweGvlOKQi2ClHfYkmigr7YJDx4bPh0hy3UAOCRECjx%2BPB%2FxIF7Xw0deY88MLUk7DSmf1o1ik5cV0EpCh8NH1gkMuAjYQk0bhKDpbIpuzBXh66w0R93KlD1GUn85p%2BSba%2FNDZZ2%2BxJGRlgKecaKDEQBz7zXOyQjf4gTlF9Ie2eSbha5DT7pHUIkH%2BlA4oCyw8M8O7gFKfK0AckjeOwNRd0iieW%2Fh2stNBLOp8mCCBFa4%2BI2rLsk2FZAcYcbSttzRq6iRVS8VpWx%2BCNPZbuX8lOLdR%2BxBbG46A%2FNBHGkP4J7ZsXlfJaPICkMhxentsJ7U9O1RZc2F5DKGUlaEgyDBE7xsacnCtoFpeySMZCBUlzylp4Inkmlygn0LywT%2FAIh6yyehC5DalEdNO9SOJ%2FRnlCuyYYbl1pHlBttSSEwQRNaMeCyiXW%2BWgpGmAlRO4janR8fdpktkjaymjQEoSArTv0k1pjFr2UfKyapeolpSXY5j%2B96KkZkp2MEZLDGlS2HUJmAAOKlIuMpr0E2crguNrSwd9oHJA7%2B1WFLM12g3aZbX5aR5R0kkc7881bi0Lc2%2FRKsLyz5i7ZpSXHFFQA9MVcdO2BNJd9k3awdty6B8olKSAFHsOKcnYNhlzAg6pcJVpJPA%2FjVtP2O5IS%2F7aTq06FKAIiKr466K5oleGZZS6UoDQUk8DTTYJoGck1olNtlMNk3CmiNJhKVdDRoVQNucsnzFOLbME6lEjc0HxosXtcC8stnRKQZkp6UxRYXxt7JPaYGh0hspSkkAb%2B9Eot9k4MkbeWQ4hvQ2lGnid5o%2BCocg5h%2BVlIWlxxCNAmBEQe1ThH6Iyb2mFpZZTqRCfYbiakVSII3lm3pWNEgdR1oinJLQMaw5lSwEpJBnkcVBMZNEqw7BElKSlsGajCc2yT2%2BAtqSPTB67VBdBNrLSJKtJB%2BOKgSi30F7HAWkOBW6lUagyV2WNg%2BGtpUgQkpiKJRZn4flaLDYwJp1pJAV8xxWhRVEapgXFMrNqSoFsGTvtzUlD6C%2BRlc4hk5AdIU1q6%2FhpTxt7YLlZF8QyckkjyykbHiglD6Ci%2FshF9lxTKVlaQRMjb2pbVDbYFGFrQvTLaCZgkTVDIzVFh4Flpu5ZUS0V7TvtFFFWxb7LKwfJbSdg0Ugp681phFPsu2NMby21bIUFNk8kmOauUKRTYyyvlYXV4wpVuQNcg9QKU2kDx5dG3uBYc3h1ihJCUwkAbcmjpFwTiqQ4%2FZeZ6kiTuT2qm%2FoNSYNxZdr5b5JUoNiCT3pE5BRn9kNbZaumk3EaAJ22k0tzQDe7Q3vG2WrUkvaXSSdB6RVfIFzZFHbdp9SNWtKegHT3oxq2JLaZsSHzAVOlPXVNVZdEmRY6bVtbikF5W6gNgPgVOSKdDHE3mLS18x5SUqUSlKZ%2FF9JqnNFJp9EXs1LWLm9dDaWAqEkzz7dzWfmgsWEmOGgrYdefcWZAMf6feiQcpqPZHcVxh3E7g2aCu1s2yVKAHO200mbsJJdj3Abz7vdMMhKlFW8EwRvVJ0ETTGrl1TbICFQDO3vQyb9DIICOOBssk%2FhTCiB2oeaDpCmEp%2B9YwHHBqSTInr2oLuVoKT%2FAALdtE%2Ft0tq5J3g8Vui9HOeKm5BtxanLgMAEJCSSR0qAcI1yZE8ROq6bYJUUlRJPb5pU%2BzRjil0MQ%2B2q5fWQFIJ9JI4FAHdiRdQHlQmUA8moVY3ubnzU6EAEkwKK9UWOrG0HlqB2JIO1CokM75xdvbLIUdJ2iajTXZa7Iu7dtjZaVCRt3NQarBd3fFNsW1IISraTwB3pEk0FGDZCHgq4WpSj%2BzBgUibTHrSPQpCIG8UXFMS3szUsoSXHJ0g9KZ8aq5AjNd4p0kuOEgcCqYcceiPXV1pUZEqmIJ6UqUk%2Bi%2FjYMdeSrU4sQANyTQoNQSArtyCvmB7bA1VoOho4pJWSNZJ4I3%2FOpaLrR8HShQWr1n3qnNESMH71vkNkKjjtQud6Da2MDcpGtSZO21A1QxJvoFquCUqE%2BnsKFuuw%2FjPmXBq1OKAHX3oeUS%2FjXsTur0u%2BhCYSAevSrWRBKKQGfchsQZT1kxSWWgG66lEAhU7%2FAAaXOLfQxTY2QVLJKp08fSg4MGTd7MXAQCVkQenEH%2BlWoMLGK2qQUqUSooAn2oo497AfZ5dXiEJUQrc1blRePG27AiVhbgWo7k8R0rFyZtQ%2BaGklRHqPzJqcmC79Dxkp1JSlRKog9jVcmK3Z9dPIUPLSCT7UMshohqhuklIKZUlPek80QycXo1pQpUxvFWDFa2NNXqJJMHfv%2FYqWEKJKlGZJE7VCDsKCSCJ1DaDxRQkiCBUUkc8RNe2emeL41tnodBECNhHbrQc%2FsjlvR796Skq%2FabkEkTVqSIm2xm7cjhKoE8VaaGpAO6fIIVIInaaXNlURy8fOsEykEE89Kyyk%2BiEaullJTpUVQYj3oG6NFMHqdG%2B5B7j92ktqx6s8S6j1BKwSNpP9ahHKK7PApJIOpIEdDTVBIqcqMw4ABCiogf5uB%2FOjF03sz8wkpB0kc7HaoU0%2FZjqRpgErnbp%2FCrV9FGKloKtGlBjsaYotdC3MZXNsh1KyEICtj7UbBVshOJ2KNayAEtzIEbfH%2B9Z8mNt6GJSRVWO5XbvNSROrfpsOtIlhYyGSSeytHcno1utKbbCCNH4Z%2BopUYb2PyZdEZxfw2YcbLrLCdP4iY3T3p0cUWrsSsqrZBnfDpl1otltJAMDUD6k9IpcsS9MXHJXojOIeGDYWoBlClnmeQBRLAkrezVHfopnMngshxTpXbAJUTJEE%2FO31pnxR%2BhLwK%2BzXjHvBVYuVqbt0kaiAooBMTyazZ4cdoXLCr7AZ8GEKUhCrZSlgGVFMme0fFYowfLQuWNoM4X4G%2BY0vVbJCCmYAid%2Bprq440t9gC114CqA8xSQodtHb%2BlG2vZCNYj4MKS0WxbIW2NlKAIkVVJohB7rwgdUvQi1KiJAlHJ9x05oFhX0QL2HhMUICXLdISf3tEgEUXxRfohaOA%2BEyi20p1n0kmIH8ewoXgjdkLOsPCZDtqSLFbiREKNOjH0iDq38I1N3TYFnoEz2mT1FDkhfZLJrY%2BGRtVNoKAnTIBUmZEf3xWX%2B0ZoWZ%2FRdWWcmFLbbSGglUifTGmRx%2FOjXitKxcsjbstqzya2EMlTRdP4ST0%2BadDxvsuM%2F%2BoMHKWnSqEoTvGwEfX9KesUV6GfNFHjGWklJKkoUr3Gw%2BZo0q6ETypsO2%2BXAnShLaQrjSABO23WpJX2ASbD8AWt0JWwkdSOnFXGP0K%2BR%2BkS63y6tHSEneE79Jn5olBguc%2FocKwJSdkpI3gGeaL4wecxs5gLmoShRKe4ECh4Mb8jHDGBH0gwdJ6Abn%2BzRrC2FzTWwq3gQjU2PVO%2FFPeJrsqclRIcKwQNvF0oSITsOYNVLG6oyQkg6xgpQ4lWkkTwB%2FKaFYmtDeaDreBKUFLUjmYk1oTYkVawJtT6UFoqVIE1LZCa4VgMLQCVAHc8SaOD3sKKtkndwlLidKUkN9AOTTKX0G4Khg5gSSJGx7k8VBQNTgxQtRLRWBI3FR9ECtlYIaW2sNhOkyZ2oYtlqbXRPsPw0PBJSEpQrcqHWiDc6ZK7TDG0jUloGPb9KhfyIev2QQBCDPtUDojOJWzpT6QgIAg9z7UPuhM%2Bwdas61BIkSdyU9KIEm%2BHtJBSEhJE7CIio0SvRMbVhISkkoJ9qhcoNdkktbVBb2QkpO01C8b3oIt2KoEpPM7Gj5sKUPoPWTPkrSlQPtJ3maNPViZJrZYmGPehCFbAbEUxSYqTthS4YbeVKSJinFAe5wdtwzoSD71CAu7y%2B0tBkyqOorOQrjGsspJWkJMHuOaFxsPmyDLyqVuJKEkDrtU4ILmiycAwcNshBA1f3xVpjMeyzcOsQ2kAQFaZJijk72CkDccwxl1k6tPmKJAHf6UIMloeZewdi0SXVgJUkhMd6XMKH47RNHMVbSpNuhZ1Aer%2Far5osbuYgGQVrXpSN0ztNDLLRaT9EBxDHb2%2FK7VhKVNKAK1RBjtFZpTscscfY8tXS1YtJZWlSgN570Ilq3UQVizzuplQaGlQ1LcVwPirG%2FFSsjysZsEqdbDzan9wpRPpH1oOaAjhm%2FQAuL55V2lanQUtRoBGy1xsEgbnvVPIjRDGq6HbuPKbbbS5dr80mSnUJ%2BvakyzaHrCq0iP4tiD98tPlOmSYGmTpFA8ocMCXZ61e3N0tLSngGmiEoSg7T71IybdDpwSVosR66Uzhbgt0S7EnuT70%2Fk0YU97IuGHm2LVolWpa9bukiVj3NL9mhx%2Bglh7imMxWiliUaNk0PJ3QUsf42TbEMSaWlUhB0pkSf6UMsyRUegKwpdwhK1ER196Wg%2BLCmCOJ%2B%2FrJ1AIhQMc%2B1FDsk4vjRZGBXi724dechCQuB24rXCTMzjS2SNVwbdD76Va1qMAkUxsU8cWuNkMdcW%2B84pxSedtuaRKVj8UUlQ0DraFhJWFK3PO9UNUaBmI3QbZcCVajMAdZqnJLsFxGuHKKiFLWUqkxJqlJPQTx6tkzsVK0EmE9qbj7M76GuIJhpQUUgK2FXkJFkMuyGNJSrp13jekybXQ3mRi5uV3PoSFqSDvvNIlNvQcMn0NAFRpOrUT0I4pbxt%2Bw3NtUMnyhA0yQZkxuavg12DGLYOevSlOhJ1Eexprk3oL42BLi8KtQCkzO8CKSnLsNNp0yO3F2tKyNZG8b9fekTY2MbdA83CjIK9M%2FwpdkcGhkXtSyEmSDyOlQvgKKWlkGFavfioBwdjdVwkg6ilR6T1qGrHBDJbwIVCwN%2BZpbyfQbgvQzcfVoIS5pk9B0oZSbKUWuhkpwJmCrvQttjBo5cEAiSVaoCRVqVEG7l0WglUkqO0A8mqk2yDJx912FKUSPcUqXLogwdCtI1JAHTeq4MtM%2B81DQIBM8gahA6U2K0U7bG7jinFwpRUeRJ4%2BaGbaGwi12ZqfShKG0kAfHPvUvVkcECnyXHCQoqAEDaBNZpJP2MjF%2Bj5I0kCfV3pY8fMypRJMgdJ61CC6iG29iiSOJ35qUDwQ1SYJWoqk7cc0mUH6GRjaPQr07qJ2mlKH2VS9sTKyoAqUVDjY9KNr6K%2FwIpcHYgSABPSoQUTcK1BA%2FOo0QchwaApSh8VSVEGZd0SCVExz817BHi2m2NzcpCApJAO38auw3L9CC7k%2BgBQKgNqKLSLB7zwVKUlWobkk0KGR6Bb9wsSlJ1pjcDeAKCSj7K5ID3C1LC1AjTHpE7R70r%2FAANivQGuP2ilAgn0iAOlQN42DbhsJnyyVDnfqKRLsaDi7oWSdOncHv8ANHBgOFuxZDvGsp0iIPemCU0fBfqAVv0oXFE7F4KoCYmrSroJxpWYEp9RJVPEAwPimKf2RIVLhlO0CI7VfyIzP6PC5KdCkgnqUriBTEWtDK6t21AqIUREEkj1e1XQfL6ANzhTKwqEnVzPE1HFeyLI%2FRB7nBAXFBKCvqY2ilSxoZHKvZj%2FAIN6VAhUe9DJplylFkWusutof1KTI4mKuONdj8UVXYIu8CZUopLKgIgQN6Y2q7LlxsA32Vmrq3UlTCSuNOyd%2FwAvzrI%2B7FPJ9FU414e27iHdVq0V8z2MVUslAPlIhjWQm0uMtOsw5MbHgdxT1C1ZHil7ZYmF5GYDXlhhBSUgAATMVTxPtFLHHtscX3h6yhsLFunkD3O1F8afYzjD2Qm%2B8O2bkuJDJKvxekcDsKpwrozzjH0Rn%2F6YsqeOq3V5gHMdPcdaGKsBQb6JDbeF7BYWRbNhUySEgT%2BdH8YxYZBfDcgMsFCU2xQVbEaefrVPG%2FQEsUkyc2OUEtsaFMpkAko%2FyijjCi1S7DzORbe4AJt0j96QmSaIbGWP2hyjJLbbqUhkggTJFWIeyS4flVDbo8tCk8SYjftUBcU1TJja4DIgoSlI3jkn3E1Bbxtfx0GGcCSRDsj26H3ooxsr4vtii8vAOBKJSmJM9TR8EUsaXTFmsvqQtPpWUzvp3mpGNMH4l2TGwy6ChKk%2BhIPAimqRaVEiRgqAjgkAzMc0cZ%2Foqa0NnsIBUfTBjgCrcxfxjReGoIIKdSvg0lDk9iYsQn1JSoK5EJolJouWQfMWqVup9Ck9Nz%2FCmfIZaJjheGJOoFEDf92KJOyEoZwpBA0trKY2moQe%2FcEpTsJO0e1FwZaVuj1nDlEiQhRPGnrTFCuyNUSy0sFISAkQCQCQefarUUir9EiTZAtBITrMbyasgocNQtCiG0HpUICnsLCSToJ%2Bm4quKGRyUqGjdsW1aVpUTM%2FAqJV0X8iJnhCU6UpKQAOJFVONi2TWzZbIETqoih%2Fc26A2AlHpjffeagX4fRC8Qt1JU4AgKBJ4E1Tin2C3btgW3tlqUtKkhIExS6T6LirJbh1ur9moJ3Aj5quLsjj6JtY26VKBWI2P1pkVQx0o0yVWdsTpSlJCv4UQEUrolltYpCAmBIE7ioOozXaiQUAEg9elWmBKLYVsVKa9K5kjvtV82IyQZImnm1gAqhXTuaZGSYaSQ%2FEKkqHHJpilQKjQsW0LSqNyeBUcrKavVEYxHD0vKKhsQNp60IuqYJRg6DBAAJ9qhfNfQbtMPbaUhMaidhtUJGNsk9rbJaSpayAkbfAq71Q6tWwHd%2BULpSy4PKG4JHI9qVKROKktDrC0ouMTs0rEtagdtge%2F6UsbKLapEVx7GLe0v3XGtRCnClsI3Kt%2BlDLK1pC8cG1bB1xdXF6i3fKISJCEapB9zSmVOP5UM23ja2zqnpefVIUT0oJSo2cU6%2FRJ8Pt0pstayklbes9I3okgZzraIVm119tYtmXENWKEDdZJJPWKHJEPHJPsgVjhy7%2B5U4yQG4KgojZMHk%2F0pI1T9M8ubctNqbXcONuFXqWBBUOoHak5MlOg0l2Rq3Qzbu3D0q0CShCjJ3P61lbd2PUE0Lh51t9lrSGlKiIP4R81E2RwSWkHMOKbZ5YLeqVA7Hk%2FNbMb9CaJrZ3afJeTcbuHaNWw3pgqS2OXWyhSVqGowCB%2FKoCu0CBcKexu38psjT6YT1rLN3KzYv4kuxZ%2B3ZatwkEOGAsx17U%2BT%2FEFRsShFqygFZJjVE0mboqLp2EMMcaAcU4sgnfY7mqg7Km1dlg2BNjbsJCTrV6ua0roRVvQfdcU9bbCR096cnaF86ZHlILTavMUZg%2FFJcqGXuwCh5gKLilq6wTyDWeWbbHO2Qu8vlXV6Y%2FBJjtVc7Ir9hqwcW5cIJ1BIIAAPIpkI%2ByprRO7d1sJVvv0Na%2FkVUJI3f3bqnnFQoNjiT0pVB3GyK3zwdK4gTwZ4qmg1FDRKw2DpQAY4HBqJFqNDRxxOoqhCE%2B44qSetg8tkfv7hEqDe3czP99azScasKiNXN0Nxq9AG1VzS6Gwj7AF1e6VKTplJ4pU8qGqF7Brz0%2BtQn%2BVJcmxyikMlLLiyoBUcUISyKPZ8o%2BXGoEKjaBUKb9jR19CSZ%2FFzueaCU%2FQMIvoHuuqcmdvYcUpuzRBUNytMkbc8zUSt0Eeg6hIBSPio1XZBo64QdASo7%2FU1CDRx5KCQhKSo9TuBUIN2wFEgySe39atxdWyH1x5bTRWs87R0oXKiAF661LVMCeT3%2BKCWRF0xBL5JgJBPzS1P9hxgZB1CZUAoEiAO81Uso1IxLhXO65O5iKS3fZaiz5AQEmTtG%2B%2B%2Ffc1QUVQ1cuUlaUpBIjngioOcJfQ7bWQAIBBqA79jpCFLCUmCf8A2qUU3QjcgpUkdDsO9BKRBNQACExJH60DkyxB5ZQnSIO%2B%2B3BoSCJICSQFKJ4AO81CrMAopJgxHTqKq0EkxfWdCgkHbvQvIicWN1OE6ipYSP4f7V7WUmzxw1eKwV6VBKekb%2FxoWg1VA9TioUSUj%2FKBuKGV%2BgXXoH3LqkjVrcbSDwDEH4oW5DIDBxwCUFepIM%2F70uvsJxQMdWRqMknbeIqEUUgc84RJMHfg8%2FTtUCTa6GziidSgUHpztSZdjIy%2BwbpCitSSQRUV%2BguSMFpLcqSrQIgRuKNRQmz2XFEBHA%2FOooIvkxVBcTqKpVBI7TRRirBYqWXHQAVFAHUSafwQLl7QmUKhSYXsI7QKVONPQliJZdO8kwR9I7j8qcuhqmhRLaVKGpQ1TMR%2BKqk36BlN%2Bj59CFpXJB08mdzUTfsCrYHet0aihQI%2BDxRE4iCrZAPpV0333%2BaXOTXQTTBlxaocUdSFSeu29A5NqmMg6RGbm0S2XVApAiAOaz2WknbGKWEIARKSoJAkH%2BVXF07CTAWI4cPUEoQpBJn09O%2FvWiPGXovmyOHBGC624EqLnWdt%2FampoXlTZLcJwZCHQYE%2FhMnv1FWZo4vZJn8BQtspSUpXGx96g1P2Qp%2FBAh1aFIASJkEfw7VCJWK2uWrd0JW01G0aev1qv8lO0GW8sJUoI06EnYx0pfyqw%2FkYs%2FlptASpJUFEgiDwKYmmX8zRi3giCdaQSQZO3IqxbYescLSEKSpuQTO%2FIqFUGk4MytaCofAIqAqKHSsHQ3sIBiJ5moT%2FAHCLNiknUUhMiBO9U2RzQWtsO16kkSkxJFHGRUo3sL%2F4XJhKQk9wmacJlBmZwzSNPKuw3pqmhbhL2w7Y2YGlBSnUN%2FrRKSYFUG02CREgCYJEdaJOuiqGr%2BH61LWVARsCOtU0n2WDbjDig7p0nnfqPmh4oLmwY7aGAAFp%2FwAx5IpUlsZGQ5s7FZWCY1DiBQ2E%2FwBk%2BsLZISlEJER8%2FnT4LQiVXokSGgEpJKh%2FP6URRmplK94ntMVa0GmvXYqywNglIKB0H8abF62VJO9kusrcGBCQQeRUm6BoOt2qiqCQoxyBUi9EDDNkUt%2F5D0oiA28sJVKyCD1moQEKsZJGlAB2EUL72QL2Fq6CFK4mIoW16ZCX2DavMA1KgHoKYkSww%2BzCVoH5ioQjd5ZagoFMiealhxkkqaBIsE6lFAUmI371XCy3G%2FZKMKs1H1EieN%2BP%2BatR%2BiK1pMlTLYbc2AJKd%2FeromRkpw1sqcbKSDPMcRVC13olobQ2hJ1AT%2FGoPv7M2Ea3IbjcdBuKhUpa0e3iDbSSSDE%2FNQVK%2B2CVYmgaSD6hzv8AwoVJBVH7D9livnslsqSFpA37irUrAcVeg4tS2bdp1agQoakgc05KlZEDDcFx0ISEqWTETyavkIbsXeT5DqmVqhYEEdqGUyjy2eSu4CiUITMCrU0HAKZkvk2WD26m1lLzyiUgc7UVmhRtAy8XpwqxfWlCF%2BRobMTzuVUGRasGKadJgTBcbaS5evJ1izt2FhLhH%2FkXHI%2BKTjd9jEnfZUgxtnErt9SFeTbtuFKlEfh71lllNL8YkGEYiL54qbKk26VQlSj%2BIDqB0G1XjlfYucOIQt7tnFL1WnUGGzpmPxCiaTKeGSVomTRDjTzjCVOaUadJPG9WJlGbeyC5gl199TzSjoaElWwCjVNL2MgndCeEXrWCYReP3dsyoKRKfmlyjxVsbuTpFe4liruJpS2y0yha3JJPKUdaycrNsMLXsG3TQZdcXJKkIgd1GgmFyVDVNuu%2BvG31OrATyE9%2F6UCsLmiW4cGWAt5QcJ1jQCYmtEFsSg7apauHEkFKhO8neabaL9UFr24YQndYCQJnsYqpulYhXZEcHugrGg9rLqUK3HQVli7kbZKok4u1t3q9ZSgAKnrArU6aoUm0N7hZUCQqSQI9t6yzlZcErH1g7pU2CnUsEEyPfrVY6TLnFdFkWN6m7dbCtggbwa1Ra9CXjaegu9iQCC2lekA%2FpTEwHFkZvL5TilpQYgbAGayZJOw4QSIvcXOhsJUuDvUixq2wUyjUCogmT04ol2XkjXRMrBlDLKHCShXQHpWgQ9un0OvvaAvy0LCl8bVC6iBsbuEtoUgakr61J5X7AjG3ZFUrDhJMFMzIpcZNsezO4uEpTzCR3o5Sooj99iCSNCCCCRJnikyyETIjf3xOpOyQOJ3pM5eh8XojbtyvkK2jeelZskvsbGFgK4uCpSlKXqgD8W1ZpO2NWKmYruJhCSQTAJPSmQokmrpDxpaUpJVBWOB1p6SFSg2NH3FAFR3UdwCeKk0khuONPQJUpRJJ9ZrG2PEwFKUnZQMb7TV0wXJH0RqKpC%2B4%2FpTVFJ2RTXQ1dVqWgAlI%2FWKPsJMRedQEKDR2kSRwaztOyUDVkKWCdJ3iJ%2FWmQKlKuzxK1ObgpCd%2FepJqtlcrWhhe3bcFEKK4IAnYUjLJUNjBgFTgkEkkbxtzWG2%2Bx1iJdgiFp1du1Qo881JVqK9ZEmahOTQ6Q8FbAkcTUGRmNLi8AWG0qVxvQS%2FRpcdWkJNlaig6ieskb1I37ETk%2FsO27a1pQqDuYmfxCP4U1QbE8%2F2E9IYAUYkAxPI9qpxrstNvsEvulxalRCon5oJMeqR4FpSFKUqNulC5ksZFetS4UUxHxQMhgVjUBJBjcxQS6GY4%2B2eahrUv0knYkGsLb5djD114wpIUTO4356VC6ElFwwFBHzIr6DJ2eIlGjFYCknYdOv4RNUCMvKgqQUxv16ioQZvM%2BYC2pHpOxj938%2FmqbLQNftCyCAIn%2B%2F6UqTb9B%2FIC37ZWhRVuknYgiZqqZcZWDXWNIJUhRg9do9veqYYxdbcVCuvUzBNLlH2BNtIboZEqiREz%2FWjSKSZkLfWqSEgCrGDhq33QNGkq31EQKhVuxy3b6yYSCAdR9%2FiigrZY5FtpMhCjtEkfpTjONXmAQToQngERyJ5%2BKgvjL7El26iCrgGd5PqqDBBbaghOkI%2FDJEcn2qEG6wVlQlIJ%2FEB%2B8PakvLXZaYJuGSgSk8jiYH1ooT5dBcl9CDepKVHUeOu9Vk%2FYSpjRaUwrdCgRwBvSHMKULWiL4krQtRDalAiJB4NLBWNoChQaBUUkKJA36VB0V9oUZU2%2Bo%2Fs0JERv1q1JroPghdVilStYZSED92Njv2q%2Fkb2JcWGGGm0EEsoB5AnitUcl9i%2FjfsLtgqCkqSncTtzTCnChnc2iFLJCQN9uNzQKduhd%2FQ5tLbQQlI1Cd9qMu37H6WwkqQW0me4pboh4plLnIBKRE%2B%2FaiiU2kN%2FuxA%2FAY237URE0FLazBERAnt1qFh1mz06FKTt7dBVJi%2FjHZtUCISSOQAKPgwGmhVu3QVggbz%2BY70LVdlB%2BxswTKUgpnYnptToxQcZUHG7bZUBMRyOhogZOz77qATwFdD3%2FADqtlDphhKASUAucEjmoipRsJBlREn8MTWiPQqSSPfIhaUlBk%2F3vVgmD9u2QtJbTA2mNqjdKyJAhzDgpwgJ7kf8ANLeRjVjphaxwtOlOlEHbc9aXbfYbJazZpSAUg6e20TWgztehVLS0rGr0gDmoQQWRrOxCht8VCBC0SFEEEpPckCKgcZ0qJdYIIbjSkKnoaamnotyvRJrS2K1JIUFA8jrTVVAOJI02xSgSQBHEcUILdDVy21b6eNt%2BKgKnYw%2B4AjYEKq7DCTVkpIQAlI6nag4Igbw%2B00BRiCevejSaFzCSmUFMcmO%2FNXaB5sbrw9KkCRp37TtRJJ%2BhsNjNWFhS0wJBMbVHElkvw%2FB1NJTpb1iO1Gtei6Mbpjy1qHlpSocbUtu2QkuG2j7JaKkhBI1CTvBoBkIvsNrCWnAlUaJg781ExjimPrBsBwhIJXB252oVHdim4roeYohBtVFZKuh%2F2ogp5bVUVBiFx5V0pCQSdWwnms7F8WSnLil3NwoobLxZ5gSAek1IP2VJUrLDdQp7BbW4XGtDi2yDzM9q2qNqiRaa2RuzQ85f25CSG%2FMTx13qov0VxQ6v7lxeKXqgCoBRAHPWjkrJxQ8t7ZPmWzCnQpxIlSZ%2FCfek9Me4KtCObbhLxabQQUIbS00E8g8T880c3suKoB5oxJanbDD21aLS2t0hSCfW8qKVNtoD4yK5ixl%2FBco3bjdugXr2lpG3%2FjBPNBllwVh4Em9op%2FClOPON4a2FoaiXFjmeu%2F1rnRi3s6WTIuJN0Nfc7BTVsSpw7JIMfWtiic95eTt6JBlxryrEtrCw4RBI6k1aRWScpSuPROcDvAz95ZXPaabGHsuMZVbA%2BOrNy4bZLaStavUAelDOKChHdlf5sceYuMOwlKVhs7rT1HzWPyLeka8EkrAVvaJ%2B%2BKAQpKQI3HSkqDQ1ZBvesKvLxPl7pEQJ2FWoMW3okGGWjFq0%2BHmwsngT1p8Y%2FQt5DO6ZWVI9IaSPqBQNWglO3QvZoLaCQpZ9W0bfWgeP9hWI4s4Wbdxxwkdpqs71RapugBkdxV07iTgUAgLO5ismOO7NXlVUa9FkpdT5LgkBR237U6UkjKDGH13NwG0wUoPwFUk0ySW0StkaQkhIHQR196fGNCJO2SKxeKElUjVtq9qZGVAj%2FwA9ISudhxuatzBcbdgO6UhOpxMAidp4%2BKVPoIirlypTgSqN6StD06iFLAhTgko0pjc1qwu0KlKw24%2BQ2f2oKRxvBpu7AYzafIUpwFKTPWrFuLI%2FiLq33FIWo%2BqN5oZRsYtPQjo8tJSmSO1WlSKlN%2BwNduJCVBWpRmJnilTdhxrtkavnUoBJ3PvSJS9DlBdkSvLglK1HbbielZ5P0MhRH37n1FKhpHeeKyZVbNGOr0Dlq8xayiSeu%2FNUklpDRdr0EKUNjzJ%2FhTYR9sVOPsXW%2BUILkiY2B3j5o%2BVADJa9UuSSeTvxVcZS6HxjWhit4lelMEmd9XFX8NLYSMm9jpkExvBkxVmZHrzyGQYUCo8z8VC0m9IEOPFZ4TA7bVcXQ6Ca0xEmZUQOu8UEpULSTZgUHUISIgUqUrDUENHXfLSUNKJVB9RPFLm2MjG0AVOKJUkFI25HNZZTbGRlYzXyAnc%2Bx4oCRbY1UdJ1ISpIA3PQ1DRGOtiDayCIKTGxkbGoXpC67oMMqBILp2G86R3qFxxWwdbrLq%2FMCtSZ68GoOnkrSJHZM%2BYtCQEkEz7f7U%2FFj%2Bznyy2SRghJWRoKE8yRv2NaGopCbQweuFqcUlJGgc%2B%2F51mckaUmxgpWohSTvMUmbXo0OFJDFxS1LAUZTwRFJbsODb0Ni6EEKKZO4ECglJIYnvo8QSo%2Bkpg7bGT%2FAMUuWR%2Bh0V%2BhUu%2BUFKHIGxms7lfZdDNb2pAOomBJpcv0BJtaH4S5pgdCN%2FavoJ4VPexJsPKUoK1n5TztULdVoVDfrMQU8SDUAoXTbqWVALj6%2FWoVSG1zZBwKOnX%2FABJ%2BahYNdsCtpWkBSpmKvi%2FoODA71gtCVBafSd4pcoXsaC12ifTqJI34P6Upopsai1UFagopE7%2B9UV8iXs9S1AVIAPMDp%2FXeipl8kfBlwqARMEckcjrTIx0VyQSt7QakglS%2BumiSSFJiy7cJBCiD0EdasoGPsthetRlUiQP72qBUzMMl5mfSpXcVCmgfcsONpWUoAJiBFVyRErBUOakrXMj8qz0HSQ1uWytrVqUO%2FwDtUUULYHcAShSisrPHuRUcyr9A9S1EFwFYSEjkbzQ6ZojaRG8VeDZ9S%2FSepHFKsZGf2Qu4xBJQoBYITEnilubLnNPofYdcLVCtW8GByKZDYHJkh%2B87I9O8flRxivZbmwk3cIOjUsK33P8AtRaQmTbY%2BQ6lSQlIAJA3%2FOr%2BSumSF3sUWUqBIUCdoA%2FrVLJsJxRklwBJWVA7wB1%2BtNWVFcD5N5KgAQUDkneaU8myLEOW3plcEDg9Iq4TfoCeEIMoStUlXoJk%2FwAq0RnYn499hy0YC9JClKEyZMU6GOxscaDaWgFAakx%2FGreNLoHgoixbJPI1R2Oxpbv2LeXdIVYa9QSoq7EdvarjCwCU2bAQmYSBEEHfamrSIGkMjmYAG4FHj2wZS0YlgKJmSOCes06kK5Mds25jWCo79uPaqpE5MKJt9TYBTI6irKPvuwTKQSN99uahBNVkDO5USD7b1CHicPGoaiUjk7VXFFuT%2Bw5b2gQlI3CuhHWpxRLY9DYCSqZSBAM%2FpVlNiS20hsqB0xBj361dESvoCPOJDpTBJmZNIcn9jlFBGwVK0gE6P0pkHasjUfZOsPT6UhRCjM88U5NJAS41omlghLfuPn2q1MLG9UGVEJHpXvTCpY%2FoZLUtbgSlaSO3NUK40HLKyQsJKZ0zJ2q1JIFzCIsQANIB2iIiKLl9AvILtsJaBVBEDr1%2BlU5MFyb7EltlSwB%2BI7bVcf8ABQaYtdSATuBtPv3o5foggbQpuLfUoKSD1G9LSYxK%2BicWqWw2ofh25p1DVKkRnEAhx9c7p454qmi0vskTLxVY2LhJICS3v1g0MV3ZHJhNm2Rc2l7dKWpCmgDEfiJMVGkDJ%2FQbwq2KlApQvURA260tRsGH7GuZlNWIetlrWlxKZJ7z0q3GhqSKOxUuKdU%2BnUZIS0N5UayZIv0MinWy6ch4A7hWH3rdyVi9dCVKPRv2PvWjDjrYqe2H0YateHvah5hF4U7K2GwmmtOykgQlLDV2lHnain1HSOAKFRdluDWwWVtrZVcW8heokA%2FvdqPi%2FsEVwZpWpx597S4Va1RvP1pb7DlLqmAMTDlxfuvqdUWkmRCuo6VdN7QakvsAXj5F6%2FduqUvUZJUZoS2gDmPXilsw0VqFsCVlJPNBmTkgoaEMGwhti11BPlLcMqjgJ70EMNFzlZ5iCm2YQ0YQOFRyakuxUYLp7JRgIW0wlxyY3IFCLhV0wzZOLKnFE6ApWqI4ouTGqa6sbIuB%2FiTy1gFI2jiqbb7HSdR2Q3HXBdYy5dBWpKeByCazZW7G44qhgW3AlalJVKjuY4q2Un9BnC8NS80HVoUROncUUY%2FYvJlpBi8t220pbCB5g31RMU0z48jT2RS8uSlDaVCSpUbdaRla6N0PsPYdbobtmipZWOT3%2BKLFDWypdkMzksMtlpOqHOB2FZvJVMd47VjjJli3a4ap0JUlxa5WTWWNV%2Bx3kS3TDjjyocCFLStW0zUqy4pNGdg35S5Kgok71AmStDqZS3JJHtU5MztVpj9LyQNKVEJJHJ5rQWkZqeC5RrKSTyN6oPgvbBV68TqQCnj8qCd%2BifGCkCCVKJBJ4J7UPD2A%2FoWbcW2VHWUyeh5o8cvoqh4h51w6QshI7ma0x6IeuLW3KSSAd9j%2FABoiA1xRC0nconiZj%2BtApJe7KFXnShjSJUtWw9hFU5WrKp3sjdzqICzBSBBg9KVIe42lRC8TuhrMkgcT3rNJjMeP6Ile3aIUAYVHBHArNPI7NMcX2R5dyVLAAKyeTOwpPK2MUaPQ6gb6lSKOM2i4uxRChyolInb4q3Nipps9W8IJBB%2FvrQuV9hLH9gxboKikuJI%2BZ1fSjgnY2mYIWSsqBhW4jb%2BP1rS0geaTMlPFI216onnrQSjSM912D3XlrJClH3naaEnIQK5BIMmeDULe%2BzEuJ9QCzp61KTBg3Qku6BCkJ2I256Uqcfo0w6A10%2BBICwVcAf71iyz%2Bh70tAoukj1EzxyaSFS9GAdKDK1ap%2FSoWqj0NfvDZJ3Kgd%2FioG5N7PtSGgpwnaNgetQFNvQDffVdPSlZTvHpMUN0bY6jQVtdKRBj5Jo4KzLkbfoP276QkJSoFP6VuVemY2FF3ASytJVtzA6mk5pKq9hY%2BwQt9Y1JSJ3%2FKsxuhJpCS3AkHYqA%2Fe%2F4oG0G8l9iBOoEyk7mIpGSa9MNJehu7JgysoG%2FP50hv7DUl9HyVQrUhKiOPiluX0Gsh464dGoEhP0EnvS26CjK3SBy35K0rJER7%2FlVc4%2FYfBkhbeKjMESa9%2B8iXR8%2F4jiDI4UY55mrhLkymhVpEkj1D44q73RQ%2BQ0U7GBv3qyrR6tvSChUap234NRquyWhEMJWoAISCNj7%2B9FGTRaaMnbEafwSeu1NkkwpuwLc4UDBATMSDuBFJaXSAYGdw1XmDy5giZiYqcWEt6MW8NWFElKgOeKvgy2l9maLFSBpgSDAnr70Sh9iHN3ocCwKCDpGnkd4%2FpRpIuMmZrsyAfSdQM7CBUavQWwU9YhUgNpSZnqJ%2BRSpRaDTaEGLNKSvZQE%2FhA4%2BaqmA8mxN60KpUpBAmBOwFLeOlRUSP3lsUrJkxJmOaU1XYYOdaIbOxHHO8Cql0QBXTKUhQGmQqIpUe9lcbdgFaRJJBAPHSP60zijSiO40B93Vq0GPr%2BlBOP0QrJtLnmLUpop3iSNjSEm5bKJEy28EpKIUonb2p6iyMMJeJAS7r2AG46%2B1AaGrHrLji5CCdokAxUFyjSCaXAnTJ53JneoVxdCqnCVJRC5UOegqE4sau3RaKkqGlUb6ulQEHs3RL4iVDeP8ASKhA%2FaKUdMKVI%2FMU2AUZV6JTaMh30qABgzJ3psX6AaRJrcaUpUoNJ%2FDHuKYsiEvsc%2BbpVBKZ2EdatSsjY%2FTDiQRGwmR1qwKQ6tUFTgKQpA4IjmmRn9gSS9EwsmzAEnV89adFJgN0rJAltQA9MHg%2FFOM7Z6m3kyEkq45%2FjUIEGLQAiEz1%2BPmoQIJt9Cp0pPc9quiHrTKFrIH4uIjapTIOBZCfSnUfiqIKotUo3g6uAQOahBRSYnSEzPWoQHrdKTpJ2BkSNxQTl6GQj7EXn%2FSUk%2BkGk0PcdWAFFSnCQkAAzJqwA%2Fho08n36UcZ0WrJXa3WlaIPWIoozsVPHSsljN6lCQEqVM9%2BKYmBGVD8XBXBJUT80XNkthC0AUQrYfwFFGfojT7JthSQpsEhM8bDimIztMOizKlAhIWjpT0kglD7EbpoNpnSkq4qnFMGSpjG2YW6%2FKElfQVUVRRNLXDFpt0kgFMbyefij0MVVsRatCpwnQkpBjmoEpRDLlqptCUhAJ5BFUXyRFrxlZcXoQSCAapuickWDlzBBfYLaqdT%2BxbdcW4QoTpjpUxxvZUpJKz1i2SMJxBag5bWi3gAT1ANRMGU%2FokGAFgpLhJDaEyD%2FmI4%2Basicu%2FQHxhSblt1p5CSFEmSNz8UEotjYt90A8Jy6lV2b11tJZYRqaBAPrPU%2FwAapQDnZYVmprDMIeBCnFlXnKWtX4z%2FABpkdGeaYPvrx9zAbd5xLbJcWtxKUiBue1W6Lil6K0GIO2rqikQpQKSZ2E80qUqZqbtbFHb1HlpKSCo%2BkVXNgpwHtvcraZKW0bce%2FwDxTQHVg67uw02SoJUVLkg7R8VT6IopuiJqZN2p8I2CjBKuR8UgbKVKxs%2BA8%2Fb2bcfd0kFRHJ%2BahIu9hVGhZfVAQnYDaAPioSLtWCnrfzn0JIBQDJB4maCUfZHq2SBkJHloSUhIj4pRnRg5ceUToKTA2k1Cwep9SipRAKiJ261A1kaVA3y9ZM6SDwO9BKFmxPQ9VYqdSlsNCSREbUaE5MqomNhZNIslJVoQpCe3NOpNC0nKJGbtwm4KNQKEmVE9KSDjg2wALMXl4FIjSDM9qRLG27NsZUiUOMBhtrTqIHv706K0DKX%2FAElc5jV%2FiGJ26GknykbGsGeTkzThdbZJcMYU0yQQnygNh1Jip%2BKWwnb7BjzrguFNgS2OSOtZsjvobCLQq2%2BUuAAAnag5htMlNkpQR5i0pHajQifexYLd84aACJ4J4FPUr0CP9EAqOkDsOKsJybGa2lrcISoBPeasupDBwp8wtg7xBHeo4toF%2FsTUCFpbJ477zVRxtFBayZXp3SkT70%2BOkBKdMxuW1gqABUTP02oiQlY3attOpwgapgSOKgdCzrMIK3AggHbbmrLbtkSxEISl1IjfpWadehsHpFe4qEhJUSkHfYHisc36HYtECu3j5hbM69yCaU0n2alNMZKJCtIUmNwAkVXBFPIj0BXpkCOp1bn4oPj%2FAGW5qhJy40%2BiUgRsedqtYyRbe6GbtyXCAFkDoOKLggr%2BxslRJ6GjbMyQt5ygNtlAHk8fSomWNnXSSJMR7zVt2Sm%2BhLWSJCSSTtPb5oQqV7PFpITBgnud4%2BtQnFfYMu7stp0yT8Ck5p0hqxqwEbp11Sla1pGwAHWsDySZrjjjWxuXXCZKyqCetA0%2FZTwr0IvOpIkCYO29QmOFoF3t2tA0I57iqSNeHEkrYnarWhPq1AkaufzqwcmSPoUvHg4jQVKKQNzJ56VAMeZRe0C23EpXrAB6RNDx3Y2eVNj1F6FaWZAmDIHB%2BtEnXQMoOtbDdm84kpIUQobGDxRqbMzTQ5cu1GST5m360vJP2w4RMUuHTr5PJINVy%2Bg2xsp8qWBK4mNjBpUkMUGZpWZK9UpI6mgfH9DIqj555CQEpSJ9ztFIyuPoK0NC8Q2JB3MiszVl2hi9enRq%2FLqfypblT2NxQfLQPFyVAyEhJ3JVzRxkn0bXjJMxvcQdxqH8K93R86pBtjlHzP60F09CpdjtP4wOmkn61rKQQZA32H9ppsEKyGdyAHVwAKNixkndJJ3OoClZFoZjH6ePoP4UxdDBJQBW2CAR5nH1qNabFZXpA55KfMQNIjSenvVhy6MSBA2G%2BmfyFQGYyc5P%2FwC8iqvdCzNvcOzvB29qlEHCN0id%2FWasKPYPuQJZECCkk%2B%2B9QcIOJSEohIEqM7VAWtAYblU78%2F8A8ppWRsXB7Ad7uhQO43P8aWxwCX%2F4XD1HB%2BtHlWiAC6AhJjeTv%2BdYoIdBaf8A99gO4A8sGN4NLk%2FyY5JcSOYpvbEnc1LYsgN0BrGw%2FwDIkVRA7b%2F%2BJw9ZI%2FU1ckQYrJhW5%2FCKopPYaw0ny2jJnf8AgatjobWww9shRGxkD9KXN6HQR4en%2FusfpRLoGXYwu%2F8AzOjppNWZn2xK0A0MGN9%2F4UubNWGKcHZJbMDzWRAjTWjGZv8ASiWsAQgxvCP4UwoNW%2B7Sp32H86giXYk2SXNyTv8A1ocbYLC7JOjk8K%2FgK0plSWmSLDANa9u1WJJrYAamtv3R%2FGtWFaKl%2FFh1Oydtt%2F604QPLfdS539QqECjG6STuYVVrsgsyAUJkA07Jrogo0B57mw%2FATSbZAnA4gRP8qoggrbYcaqhAaonyRufxH%2F8Amon0i17Bj34x%2FwCxH6Vnn2OxdAy42CgONv4UIVg9sDW3tzz771Aodh%2B2J%2B7ub9f50qT%2FACQ5IKWZPmq3P4T%2FABrRDsQ9vZJ8P30k7nQf4CmmNdsOW%2F4mj1k1Ag7acCnxWgsT2yc4J%2F4lnrB3psESS2yZo%2FEP77UwEHYgB5ydhx%2FSoDk6M8KA84GBO1DB6Ek64s3o2gbe1FQzGtg23A0sGBMqqFZOwldkhsQSNqgMeyNI%2FCr4oJ9DJfyLRysB%2FwBucfvKo8AvINs0EjALVIJANzuO%2Bxpk1phPpC2DbYSqNoO1Z4PZoj%2FFgrFNnWI23P8AGj9hw6D%2BGgf4Y%2BYEyf4GrE2IXHqwy%2BCvUNufk0T6QubIzii1%2FdrMa1RpIiekUC%2FkNj%2FAg1z%2B4Ohc3%2FOkDo9IaAkzJJ5%2FjUKzJLokI%2FA2OmoCnx6EjO%2FA8tkRtJ%2FnS5suP8gayBLWw5IoCsr2DGEpN%2B9IB%2F5qDsAncbJAGw1cfWoG0Z22533g7TUKDCtgqO4qqQTirYJufwg9ZNKl2IS%2FOv2fHZK422%2FlVLsF9s9QBDGw%2FEkfqKXJ7Hy%2F%2FVZI2APvDew4P8a0LsvFFOKsJ3mzRjaZn3oZuui2ldEBvfxCgGPS0OcO2DUbbpNQwyf5BC8J0p3%2FAHKrIP8AHeyv0JSXrgkAmVfwFczJ%2FI6uRdBdn%2F8ApXD1hImhm9hx6ArxIbQQSCVb%2B%2B9LibK%2FBC1tvdpJ3Mdfmo0qL8hJR0TVAAaSAIEJ%2FjV4Gc2fYtZE%2BcNzWkEKL6fA%2FiKhcexukkJWQSDv%2FOoPGIA1JMCdJ%2FjT49CZ9s85LpO53%2FhVlR6YXAATsAN%2BlDexE%2BzB0mUb8g%2FwogsZ9A8xoQIkfxqBS6EsYJDLcGOf50E3orBuWyvMU3aBO5kfwFJl0bGitsT%2FAPIr3rHPsdHoi9xu%2B8TuaAsFtE6SZM7%2FAMqhAkoCOB1%2FjULXYCcJLrgJJG9QeNjuvfeoIk9s8k77n%2BxUKE3OFf8ApNQggrcb7wpMfmmoaeuhFJIKQDAqCsnYq8SG5BgxUJiVtkdxImHTJmRv9BWHI%2FyHw7GTf730%2FjQ0XN7G7f4SeskTQT6Gpja5%2Fd%2BlKHwSpgy8ADsAADWar2LjJ0ho0Tqe3Ow2%2FKrJ%2FpM77iOnm%2FyqEgD7fj%2F9UmoMPP8A7rnyP4UqT2Oxt8Q9bKVCvUr8KTz1irhsHN0P3d3FT3FXJIDCtnqyQmAYGgn61nh2Xj%2Fmxn%2F9xQ6UE%2Bxwszu43O%2B5oKRDJwmUmTOkfxNJfZBnc%2Bl1ATsJPHzVDElxbBdzu84DuJrPPtm7D%2FFgZKlBDgBIEfyoMe3s1y%2Fif%2F%2FZ" - }, - "response": { - "status": { - "http_version": "2", - "code": "200", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-disposition": "attachment; filename=json.json", - "content-encoding": "gzip", - "content-length": "147", - "content-type": "application\/json;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:31:53 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:31:53 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_8CrJQZ4GEo5C37k3DTxSgw==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:53 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786111297984366; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:53 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "200 OK", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "85581b6c6d277fa738d021d37568bbb0", - "x-frame-options": "SAMEORIGIN", - "x-rate-limit-limit": "415", - "x-rate-limit-remaining": "411", - "x-rate-limit-reset": "1587864355", - "x-response-time": "364", - "x-transaction": "00d00e5d0063da2c", - "x-tsa-request-body-time": "413", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - }, - "body": "{\"media_id\":1254206528162324480,\"media_id_string\":\"1254206528162324480\",\"size\":207808,\"expires_after_secs\":86400,\"image\":{\"image_type\":\"image\\\/jpeg\",\"w\":1024,\"h\":682}}" - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/api.twitter.com\/1.1\/statuses\/update.json", - "headers": { - "Host": "api.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"RetzJJ6LP2PkP3o6gDmdImSAqXo%3D\"", - "Expect": null - }, - "body": "media_ids=1254206528162324480&status=Hello%20World%201587861062" - }, - "response": { - "status": { - "http_version": "2", - "code": "200", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-disposition": "attachment; filename=json.json", - "content-encoding": "gzip", - "content-length": "1033", - "content-type": "application\/json;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:31:53 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:31:53 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_O75F2NbA9zJ103fgjkZXfA==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:53 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786111368767384; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:53 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "200 OK", - "strict-transport-security": "max-age=631138519", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "4beafab368e62bfadb87721f32433465", - "x-content-type-options": "nosniff", - "x-frame-options": "SAMEORIGIN", - "x-response-time": "168", - "x-transaction": "00b2574000ab3b9b", - "x-tsa-request-body-time": "0", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "0" - }, - "body": "{\"created_at\":\"Sun Apr 26 00:31:53 +0000 2020\",\"id\":1254206531073126405,\"id_str\":\"1254206531073126405\",\"text\":\"Hello World 1587861062 https:\\\/\\\/t.co\\\/k34Vy1Gru6\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[],\"media\":[{\"id\":1254206528162324480,\"id_str\":\"1254206528162324480\",\"indices\":[23,46],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfWMToXYAAK1Mx.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfWMToXYAAK1Mx.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/k34Vy1Gru6\",\"display_url\":\"pic.twitter.com\\\/k34Vy1Gru6\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/oauthlibtest\\\/status\\\/1254206531073126405\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"small\":{\"w\":680,\"h\":453,\"resize\":\"fit\"},\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"medium\":{\"w\":1024,\"h\":682,\"resize\":\"fit\"},\"large\":{\"w\":1024,\"h\":682,\"resize\":\"fit\"}}}]},\"extended_entities\":{\"media\":[{\"id\":1254206528162324480,\"id_str\":\"1254206528162324480\",\"indices\":[23,46],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfWMToXYAAK1Mx.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfWMToXYAAK1Mx.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/k34Vy1Gru6\",\"display_url\":\"pic.twitter.com\\\/k34Vy1Gru6\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/oauthlibtest\\\/status\\\/1254206531073126405\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"small\":{\"w\":680,\"h\":453,\"resize\":\"fit\"},\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"medium\":{\"w\":1024,\"h\":682,\"resize\":\"fit\"},\"large\":{\"w\":1024,\"h\":682,\"resize\":\"fit\"}}}]},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/twitteroauth.com\\\" rel=\\\"nofollow\\\"\\u003eTwitterOAuth dev\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":93915746,\"id_str\":\"93915746\",\"name\":\"OAuth Library Test\",\"screen_name\":\"oauthlibtest\",\"location\":\"\",\"description\":\"\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":58,\"friends_count\":2,\"listed_count\":6,\"created_at\":\"Tue Dec 01 18:37:44 +0000 2009\",\"favourites_count\":0,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":5,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/sticky\\\/default_profile_images\\\/default_profile_normal.png\",\"profile_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/sticky\\\/default_profile_images\\\/default_profile_normal.png\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":true,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":0,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"en\"}" - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/api.twitter.com\/1.1\/statuses\/destroy\/1254206531073126405.json", - "headers": { - "Host": "api.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"PSh1t4hehkC7u%2BSavz%2F1XjDqNsQ%3D\"", - "Expect": null - } - }, - "response": { - "status": { - "http_version": "2", - "code": "200", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-disposition": "attachment; filename=json.json", - "content-encoding": "gzip", - "content-length": "1032", - "content-type": "application\/json;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:31:54 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:31:54 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_3oUt7yEiIkrIdZm93KffgQ==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:54 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786111425865025; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:54 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "200 OK", - "strict-transport-security": "max-age=631138519", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "d611a34cdef1b62e60997f8804b13121", - "x-content-type-options": "nosniff", - "x-frame-options": "SAMEORIGIN", - "x-response-time": "32", - "x-transaction": "0095262200cd1570", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "0" - }, - "body": "{\"created_at\":\"Sun Apr 26 00:31:53 +0000 2020\",\"id\":1254206531073126405,\"id_str\":\"1254206531073126405\",\"text\":\"Hello World 1587861062 https:\\\/\\\/t.co\\\/k34Vy1Gru6\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[],\"media\":[{\"id\":1254206528162324480,\"id_str\":\"1254206528162324480\",\"indices\":[23,46],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfWMToXYAAK1Mx.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfWMToXYAAK1Mx.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/k34Vy1Gru6\",\"display_url\":\"pic.twitter.com\\\/k34Vy1Gru6\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/oauthlibtest\\\/status\\\/1254206531073126405\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"large\":{\"w\":1024,\"h\":682,\"resize\":\"fit\"},\"medium\":{\"w\":1024,\"h\":682,\"resize\":\"fit\"},\"small\":{\"w\":680,\"h\":453,\"resize\":\"fit\"}}}]},\"extended_entities\":{\"media\":[{\"id\":1254206528162324480,\"id_str\":\"1254206528162324480\",\"indices\":[23,46],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfWMToXYAAK1Mx.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/media\\\/EWfWMToXYAAK1Mx.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/k34Vy1Gru6\",\"display_url\":\"pic.twitter.com\\\/k34Vy1Gru6\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/oauthlibtest\\\/status\\\/1254206531073126405\\\/photo\\\/1\",\"type\":\"photo\",\"sizes\":{\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"large\":{\"w\":1024,\"h\":682,\"resize\":\"fit\"},\"medium\":{\"w\":1024,\"h\":682,\"resize\":\"fit\"},\"small\":{\"w\":680,\"h\":453,\"resize\":\"fit\"}}}]},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/twitteroauth.com\\\" rel=\\\"nofollow\\\"\\u003eTwitterOAuth dev\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":93915746,\"id_str\":\"93915746\",\"name\":\"OAuth Library Test\",\"screen_name\":\"oauthlibtest\",\"location\":\"\",\"description\":\"\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":58,\"friends_count\":2,\"listed_count\":6,\"created_at\":\"Tue Dec 01 18:37:44 +0000 2009\",\"favourites_count\":0,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":6,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/sticky\\\/default_profile_images\\\/default_profile_normal.png\",\"profile_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/sticky\\\/default_profile_images\\\/default_profile_normal.png\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":true,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":0,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"en\"}" - } -}] \ No newline at end of file diff --git a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testPostStatusesUpdateWithMediaChunked.json b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testPostStatusesUpdateWithMediaChunked.json deleted file mode 100644 index ce538a2d0..000000000 --- a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testPostStatusesUpdateWithMediaChunked.json +++ /dev/null @@ -1,2392 +0,0 @@ -[{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"cOKZmxZ5f3bxiwWU%2B1cJ9hWpUL4%3D\"", - "Expect": null - }, - "body": "command=INIT&media_type=video%2Fmp4&total_bytes=383631" - }, - "response": { - "status": { - "http_version": "2", - "code": "202", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-disposition": "attachment; filename=json.json", - "content-encoding": "gzip", - "content-length": "101", - "content-type": "application\/json;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:31:54 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:31:54 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_0CYjFmw6Rjdl\/xKmqvzf4g==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:54 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786111466374311; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:54 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "202 Accepted", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "448b96791c0d13223e24f9c1edc4a7fa", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "200", - "x-rate-limit-remaining": "198", - "x-rate-limit-reset": "1587864355", - "x-response-time": "28", - "x-transaction": "009da55c002c6fca", - "x-tsa-request-body-time": "1", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - }, - "body": "{\"media_id\":1254206535166763008,\"media_id_string\":\"1254206535166763008\",\"expires_after_secs\":86399}" - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"oyitDhdsPZg4%2Forbkwz9l5Wa5qk%3D\"", - "Expect": null - }, - "body": "command=APPEND&media_data=AAAAHGZ0eXBtcDQyAAAAAG1wNDJpc29tYXZjMQAAAIRmcmVlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFy%2BhtZGF0AAACCQYF%2F%2F8F3EXpvebZSLeWLNgg2SPu73gyNjQgLSBjb3JlIDc5IC0gSC4yNjQvTVBFRy00IEFWQyBjb2RlYyAtIENvcHlsZWZ0IDIwMDMtMjAwOSAtIGh0dHA6Ly93d3cudmlkZW9sYW4ub3JnL3gyNjQuaHRtbCAtIG9wdGlvbnM6IGNhYmFjPTAgcmVmPTIgZGVibG9jaz0xOjA6MCBhbmFseXNlPTB4MToweDExMSBtZT11bWggc3VibWU9NiBwc3k9MSBwc3lfcmQ9MS4wOjAuMCBtaXhlZF9yZWY9MSBtZV9yYW5nZT0xNiBjaHJvbWFfbWU9MSB0cmVsbGlzPTAgOHg4ZGN0PTAgY3FtPTAgZGVhZHpvbmU9MjEsMTEgY2hyb21hX3FwX29mZnNldD0tMiB0aHJlYWRzPTYgbnI9MCBkZWNpbWF0ZT0xIG1iYWZmPTAgY29uc3RyYWluZWRfaW50cmE9MCBiZnJhbWVzPTAgd3ByZWRwPTAga2V5aW50PTMwMCBrZXlpbnRfbWluPTMwIHNjZW5lY3V0PTQwIHJjX2xvb2thaGVhZD00MCByYz1jcmYgbWJ0cmVlPTEgY3JmPTIwLjAgcWNvbXA9MC42MCBxcG1pbj0xMCBxcG1heD01MSBxcHN0ZXA9NCBpcF9yYXRpbz0xLjQwIGFxPTE6MS4wMACAAABUFmWIgBAACuIiwOmAAIm7IcAAQEY4AAgIReaj%2Bj8XjXl%2BufIQUSkL2DI81%2FF5iCMp%2B3nyEGKffKfxT%2FKfOQYp9A8xPuRZeIEgn7z4rafHWN%2F%2F%2F5D4eBkq89D4h73iBofHeq8Q8%2BKNKhmBrHJX9Z8V%2F%2Fz%2F82%2F1X1EYGs5Lk%2BE90aVHwooPxeX1%2Bli8vX%2B2fLmefFB3mwHTwFJ0%2BzFpk5InjESSuTI%2BKZVJ1tF6rzV8%2Bvp8RoVI1a9vz%2BUWuv28%2BK%2BtY1S4v9sMuABEfqvdP%2F%2FgBXbvFptAw8AMI%2FEjYcAZtvUD3r%2BHBUPIvxbE6AwUZTVwsk4DOOBOkFTPeHQFnlYyBCilbNAZlDoLhf%2F8GKl%2FHgFVT554BPvr%2BgXkKMH%2F3GuD3oNuWYSji3I7CvKeMVnniZU%2F%2F%2F6KqsOk4Cg4l%2FDWADKo3IS3N%2BLwZUToUZgiYfPrhABHawIAERi8MvgKMYAavHAL2gBZx%2FMUAAEWAnwCrywtHbx4sx9HMZUO0C4zamgTyv%2B96z%2Ftzw6M3Fp7Inb4GEBhQPAQwXCeQsBLcBLXg%2FesJ3AosDQSQZL6Avb6wJbxzHS8UGCR%2FKzyQsVAXZKQvF5TtP%2Fl%2BJd2hu%2BPhgAFWUxIQiRwiN0DUQtYZb6AO44GRmDJhfDsfwMdYRWYSyr0WtO%2FvidN0TuxG4rwYPRcT%2FxOlORJNiJ7RLvEFMZgs0JnTt%2FPhxldEYDo6JIMUOY3E1C%2F1Fuor1Nr8%2BJ8zRa2P28%2BqZHxJyNOqX51tErvFq7en58V9OrtOSKOU%2BK5FPiCAS%2FPJ8AkBdBcEAdran579L0A%2Fq0YJMAOvbJ%2FrDVJbhQSvQOAAfMpY5CAii4BAJAJ4IvNM65Bw6sPvfBgGlEIZipkBOXvAYRMNxZkjTWV9m35ANLMFLNR5j%2FAxFSbmUA5IOZobPwbq6nYbI%2B4Sf756D%2BjDpCfQ7arsGAgZA4AIAqTLajig47kxnlsrlodJOMlhIh%2BesaFtU8eRw%2BGTcPmEEOxqAsaEhWHGAQicBPNxlR6ff5D6ZgLlAwoWEm6ZPu5vQZU%2BkW0vhAK3hAUxpYg9tKg4KiIaUttEtQV2yQFRjpQ%2FQ8SMUkIPwAG1rBvwAxrYctgRef38UYffeX%2BVv%2Biypmyr9vKlQBvfTKIBjTfXOb%2BuZ%2B4HBji8CyoahAXEsMBQVpZ2MAgj%2BmAYImcZaTLZTAYlk4CYM1wQ8biFyu32oZRPdxNVrRcp7Q64BRZTmAI5NHf5avYUJn3L5oI%2F%2FAtJfPmQYDGFTowVshiz6RXCuLhdLxBAAmZwgCOnh7l3MLBXh7KmVj1CSMniZAVEKYXgS39xvXG2rvEIYmpACdY4ba2QUQPtMu7N%2BC1zhp1g62UoaZ8z3d2G4GWZt95KUNLMOgebcNCLH5SrqfyoHjQMAAoxkEAAXejnHDPRSriM%2BTyZy2ugdBNghBtzH1i%2BfhZLRtqqF2jVxN3yYarkbnVm1MXVX5WvM22lSE8NHzAwmjYcSqI%2FP%2Fuz03P9Ofs0FH70y%2F%2F%2BbLTmc8Y%2F8NKlAN0z7Hfg%2B%2FaxnrKmUFV6WPnb74DbVSxekaPcTj%2FM6%2F3Dg8uiOYQIlJDCdFW%2FgBCCxIGD38ghre8u3OAbAjA4vFQYMYdFgGPga2PkQmUQ%2FKJUVx4lRD2jSRXr786l7f%2F%2FwR75yifvF4UUC0%2Fz6fRpLbD14nZkaIwOjGZRkbrzLX58XadRf8%2FkiOou06q0%2BvKz4nhVk62JVjd5dn8u41RW9F%2FErc6a4f6HXAcdTT2fvAxWcPjLPvCABEa4IAnMKGJyQhOYAIqfy%2FHEQBsxQAMgef9%2FG%2BHQLBWsDnIDAMc9Rya7WdFijXFoiQlI6Vyw%2Fcv4nVxauMoRarJmX44%2FDrfGSwxMttPBWlcB5lplzIWLA1%2FgzMM9H8yqdr5sIxbZD2fGroV1vbWSrlUulBvXeqpU6z3rFfDUeGC7ARyB6aJVo5y%2FITlmTKbOPc1VAFTCTb12jIw7JjGzk8F3WnH5tVSapxX5Q7%2FP%2FjzbIrvEYlSrWa6MOADHAmAAgymfEzoSAAEcPymDwJ1FewlAApG1xJwzNjCph4n5hWA1HHLn631n8IiOXYH31Qy%2Fvb1W%2F54YeNDHHQdpJqjxSIs31egAEniOTSjjkxOXR7sjAACAD%2FP9P6z3%2Bu%2BVGlVoqmwu4lRXq1CionnSVYkmMUvGUAkl2B8uMTYDo6NIWaJyZ6dTZ0b1p%2FidTzRuvtP8Ti%2FTrYvU%2F6dbRO90%2BKypErYi913%2BJU%2FadVeVXKor%2BX%2F2LFS%2BnHUFag94epF5SqJgbtPIR76PRVmAAIAE%2BbbBpJ1tpl31WBQABAOBIABESBEy7PwlGw9YhZ18%2Bg1KqV2VL%2Fe4QCDJMCAg%2FHiVMwT7CAARpXzWg22KgELWH6ch6x6BWRdJwgJSFCATFJGC4FFNs79NAErH2c84ay%2FS8u4nfolRRxROK8olS4VcvK6iVp0NV4%2F7eJxD86IwHTwKT0TiZBLonXpVU6i7E6qmTUUzqscnJXp1sWTKsT5XuJV%2FS86%2BiSS%2FUpLByc8A4DunABpD7k%2BEpfemgXfciYdIbEnIPP6ZFSvml7ePEmZJg8ShMzSi%2FT84c8dD6RuQHzVROQpQH3cBiEwxDsCoxxCqXYtGlALnKEEzLxrFS4ACOGAERe4A79xR5e%2FeO5Im9QyCUhtwM3%2FnMdyfadqZRnVEJKG8wUZuMAAQB%2BAE0X9Jz2jkb%2B9FZxNUgYAAhyhgOSuzBHeLj4dwc3QRY%2BE7O%2BJ0806iAe86iB7k%2BX9KrlUVjcV1a%2FjVftP8b5v6xPAZRq19vicKK54nFcadQoq8RgdMAmXG4lRT9aqdQuFk86q0Sop9E4vNKqn1efyn3aJxXFPrmJ1xy1EOBVFOM%2F%2F8F6HXj%2FM%2FYdEYCCNFDXe%2BAcgrYoKZjU92zLAKv8Uy%2F7clWOmkrcvHvlFS%2FjzsfsIC7T8xb03xnfrBvaf%2BJRrn%2FlRcXWZlalxFFHfAAjEtWGGZxQnMzAsADjhwEnLDLwKCYq7fY9HWGxzXRfTACaOECOW4zBb%2F37tfZgvsoiuJI%2BvsIoikZFIHcHEAimL6dTgFY2NtKsWAB2uFUB5WAAS8VKXOmXsWKZ6gt2Qy6ZGAM3bIaF%2FvGFZmJJ7eDI42oN7HCfDnKiccUWzIpJ8E%2Fo3dun8u5cVlWUkQ8Tu8uKxKitiN3Lv9kJ3%2BBO9yKwHTwCkHd2XxOL%2FIvNy3ovErKk6i%2FXimJVfSqp%2F05NIj79KsWpsXT%2BXL%2BOfs1zFBDwSPYhI%2FrAKLCY%2FANyWQqAue%2BAN9qADOAxeOXM0srcAwEZXyRg3NKCAANgCCioQEKsiNGgAZjGOmN%2BB7KBBqQ3YC2M4AXc3s9SFlYDRoD8JjANRg5JES1wBILFu%2FASc6SmzvyyAHYL8GM2plfiQECHTD1jD8M3RogBt2LdicXYxqDFwoB0ndpqLNEPq0zYXUTVgggKJ8EkKANPwxn%2FzHs%2F0Z3GDrvDFbeXz8C0dwd94jLSqBmPvMMZOUo0xfUd3NejPUBRgdKd0Slj0Rf4jDHCTrdAzK00Od%2FoYfIIuFqw7EAqHH0UaQhb%2F3hY5mBVo9gGIY2QYBfIxht76KLBItubfsQY%2BQfGxvrAPCcQFLXMqfChBagkV2nD2%2Fg6YdoXOPXLjIFrU6EKk84CoA4fgGETe78G5JbDfq7z9XIwzVaPZY5kf77mC2B4hZ5xDR7L8wfe6iKsUI4SW23dcI01GQYjc%2BDUVHAFgrNAWC4EYkjZLWAzG2aReD68RxFuwtaYz%2FBaORn%2Fxieh9fVE25qAXx6mQ3110MsMV877uEpAYB6ZCTlivPWnEYSH94VBnGJp2VSA6OBqaKK8AK%2F0NUMpARwNASXqBbOEJtsBOEHTpvCuflmmPcBfMJYIg1ROuBKAaS%2BCcPzN1iH7eTEARBPs9AHa%2F4ueBg5dAeOBu42mKQDkMEA4BIAcIjeMOEIyy1UniUcEesCMZCsF8gVxDpuDIweiAlaX4OMDwWI%2FJEgfsFLsDYPRwFypuvAD%2FlGSsAAn8meGYS6v0e%2FBInzzUBsC3bbYAsPd4GA6A4KsBR7zHhb4ygLV7sQEgvZ6ZB9M%2BonShRLlx0TisjwJ85KSKxP6VXKSKxJLulVxO7EaohxfXicV3RKlzlQjAdHQknon9EraJVXlxcSq9eKZ8X61cT8J5z5MeP%2Bmrwgav2eAD6zOBCPSrdDtOZgAQCYhwMu4AhUgZwZCPjgWm6P9LuLiSkCHGy%2FC%2Fp7QAcmOwjFdJ42NBl66%2FvyWfGlKOfmzvsHKdiLcqQIYVhSD13levdhIPZUxwY8P%2F4JAAEAJgMDAA9iQTIIbcqYUTfBGBFHdZskZEwEQHWuTLgQ%2FH0%2BCb5qe%2Fu96qE0knwqqp6H8BfNQHvKIHZvVRGbCQYG0eKQdzo3kB%2FvlXG2ckt5SviFPKdZADCMjaDS3xYMUyDt5DETWJX9eCCD5IYAgCgAdFzDMgChkMAlsdAhLDKxiVKfABJt2CEG9V2ChuDOcB8nOrjoIvnwIe2AB9Bg%2FXSD4ogMhp9EYSp0ocpCZ%2FHqKUTPmHBABoQYSyeVSanjdbt77aRU2OE2VXisIEwAAgCgcEBcAYeywrHkN8TG7pHwABWpKEXek%2BN2OHIImNvMgMb6mRigHioBR%2B4owqgFX3zUQD6ml%2FXioIngFMuLkZ6K6AMwMTNPSeM1JnsOt2GFKhi%2FTRkXOZdA7dEByh2j4QAA0PDAIOYXp6KgAYYHBocLk97TuUahSQ5MmgEmAhXSgDniDG1J0qAw0gl9VEa1hAmUJ8gE%2FaYEnfPwDfqwPolT1Bva4jfzMzl%2FhVFbSjSwHFeQbkfl%2BjCEJgABATAqh27qDogkKWoNZCz0ZwUnm5oquWJG9e3lotu9RFVGceskoBrn50bWchoo%2B6zRGDYdIv8ZA2zx9bOeAz1D78Wnfm%2F%2FeFHnGRKKQ3k8ZvDFhPzj9bqeYB0GY%2BpACrNe6j4ocJwSocWU7lngnUr6JvQCCWTr%2BmaoMWD1YNQ2p5%2FtM8aEF9tfiwWL6Umf%2FT6MKVHFufwFixoNbrdC4DRTGePwgAERxoQBFCHxnCLvTAs8FeMSkOX%2BdY2bSw5hKkMQXbBEi53vtYxu6iNV%2FVCOJhHwWtfhruAwCSDiLqJcMAy3OGnC1BMT2AAikgdl%2FRRO6j6Lg6UN%2FsUGMCf3P7xN6fhTsrOJdMlOIZC5oCAGCQGIM9cNTnqKcwQJsxcQACudKULbETJ891Mh7B8AHe6kpk47i6rR0PY4KorLqxT6Uf47nHXmh8e%2F%2FHgtW2b4AIUeEsiG88pLzwBLpDtz4qufkRr1YSsatz79kISD4t4BTnLIPLV%2FkUKmnAgAQiCwgWFZxBUxIHuJrYKJKQAGg66EAJrWtgVA6yXRW2KBQXnH1xZXdl5DheZwI2K3O8ST0%2FMkV3MEE1CgPhY%2FmYB7LjvwnPPcFJtYMGGHy%2FA7IUpRUQy8RCkBsW0uAN8qYBuzBAAGADiTQgABAApFnoOHRy%2FFn3gORRb8M5eOAq0S4A4AxUBK2B%2F6IjHBtvYg0A9K8exxO7vgBx4WVdsAxb%2FVdvhDZeYQGCoiSXnpj6BFuNwpl%2B9Wub8AJAcQmXUNewmhexfAMUrDzzu%2BwNh0LP3Hshw1GwMsuXqggFgNZCLFuAuUB2nBpGggQrijaAbo%2B%2BaoLCz124mGncaBxZ3ioZifZF1vit8mROEQ%2FZgo98L7unKXZticGxyWRQGM8u%2F%2BaYDtPgQ24oajDMKey8TU9SLHxtIONZgoUcDYqQ9RFcXusVtzTMDnv3i1GF6Bn9093H7h5nX1f%2B%2F%2Bv69fPrUa6Xaf4nEOdGq69H5XLgneUrisTitwJUUaZDd5dP41xD2v%2FEYDo6EkGKSkieDdflP%2BFdgv%2F%2BmWnUImoaF8Sf%2F%2F2%2B9vz6lrUXj%2F4QLCp9U6UD41%2FArw3vCBOMq5NJFTh4UVJFSk1AkBcRDD89su4Ej02cCOvbbg5wezgKohOXG4qAwGAkes3uQA%2FmwElZgArR23PsW%2FM88AtyWGoiGvaArvUCEijdP%2F3qcfzGz%2FZLSwIbs5WOs1GYdSfI9oTCs7QQAgAQCA2BgACpxmYAViXwpQDKO4aC0MIKQXD60oJI%2FYFG3huJC8y8ZcXc1capFwNE4SY%2FiCC8qb%2FBR5NhovciiW8i7fjypbHjNREPfnBWfZkTPvW%2FaiCYZQP%2FxHmyB1N7y1kO2W4WuFAvRSTby46N7LRuIWgczJLBHwLPyBosqiQmubK0DTiY9AHAAEBEBTwgkOAQMqSgQhyFek0A40AsAVRiqkoV17R4BGHvw1H5xu0HUtOm2Rn7GTTjXrIGdgNaLN05ohwrbbJOgrwei1gFMA0sQdHSQ%2B9h%2BQE3I4%2BGlCWcSOIhz7z1i7EuH9Z8N2PQ0x%2BI3%2BOb98xVlLZ5KeQ1NgUce4BD3XeMjKv%2F%2F9EieHaEX5Gl1iJ%2Fv%2FTfWggAQGfwQB6C1nPrNV%2BkyuANQpdfQa4N8psyCEpZ%2FNpn%2FJV93CiEVeRfIlkL9bHV7qiglCSobJ88DrLNgaPWfLrgN7BoeKW%2F%2BnSZjh%2FzaaPDronHlTXdpzNGQRbzxcP8LLZ4GRTEAQ%2FSv6Qh3oLBYQ61uv%2BYtDlkdX5at%2FbYCxbvwMgPMIAlHVK%2BK3qAMq8%2FBHkC%2BevdA6dMJDqXvH5w8l%2FZzpAHsnB8DNT%2FP05a%2Fzacnwy0fr6bELvmig9QJOEsxHTKNC9q3SNCiAP6SMeW81VWUOItlN0PZLOtYsev1NUVGL0aUk%2FLwoGahAIAgp0UqrBzcSElbgr5DjwW9sD%2Bb7CkAMulIxysKOYTPB3DFgwJ1uvCw5PgPHwfP%2F3jlTL5P5zhBezj%2BYsnuqUDtE%2BQ3AH7EFVf8%2FgXufVpGlLgAcOsBF9A4YVdq3zPAFaq3gDkojWeslUxyAT4I%2BcJHNbuFYDQA34YOcRx6AOCXLwMXgqjxAWUx2zW%2F2yzUNRAYBsckT2oCXABhgcAAZYJA%2Fruw8CoSywBH%2BhauywHY3ADjqyYBmADYQmtDlfPbPBQCf3ApVH%2B1cVVdQURNnIDSBtbR0azvgZBZcZgSHfe5eboKcGoe2tOTeAmR34PCVllsVAMqYL388Mz8Nnv5lF9GnnlnK%2FBVCsUX%2FwGcdwA%2FzdWpb2grjX%2B0EAEBKCBDIOfcQAZq%2B0NIeKLD%2FHxlLz6fcWjhSNXfA2xuYwrAjVT74xriqIQMOTzNMRLk4A7h63cxoFmdwHRJ4RMsCKtyNltXjHLHNbHj3uxhgBCsQQACMULShHiwDxqYXwwgf3wxjIQl7OcFyA1AtRgAf6JPNh91AEMmg0YL9CmX%2F7Jya8aBvQvl%2FWDbRSAJqBe85N4DwQkRKPL8oHb688ICDtOCBGxoIPAcFNDVQ4JRsFG0uPgG%2F7IkXGTYQJZWedzJVfj%2Ftz9ohwzRWx0%2F%2Bttbpon8wK2Q90B%2Br%2FrxBDWDXzwKUVgF1i%2F2CglOBwHgn4DpObAAEAciWCL8CA9Tz8ytBDN%2F%2BTnLi6CK11UVM1LoQRChDl1sz4OxujJOntKIwDda5sMxja4vc55VCbixqidu0cOZGxGq%2F2QQgBUUGAEipba78dcwjccH7mDDQOYAyyhxl39bAM4mZZMy8xUJAoP9dxmphmco2smvL483JJ%2FzAUY2tn43qYksuBf1dlyDBaf7oYAGdpnYbNm9ZPB7hAAgGhwGAARhL4AWKZUOwjwADNs4JHYMJcUUueHwHMMOHUgnG9XBw59XdjiiCaWyTcA9zD09Y%2BQTJjv%2FKPiaC0ggCUOwMw8QAnWIxiii7YCAe4wyAq6QWOIoCXOcleGAGQTivolX1ErKkT8nieVJVcTijylxRicUfRGAdzwKsaJlJnRPjPgMqpNAnWX3LhIq3lI11vUbHYadf9s3zXaRIqc5UuNwmVG0PqnYkeKRqcyJHYUajBIsdsVY6r8TTUmf%2FM%2FQQELW3C5U%2FOWiQMpA9rt6ptGAUbrioj%2F%2FQ%2Fqqqlrrtt%2FvwvMrxFxbpRA8QOEgKnDyHueqgYBFHmgIYlN7oAF%2FmQs4W%2Bmtt1XsiH%2F5QDEHq0cqAAD4Va5UYOthRk0RdWgQgACoBDBIQBFWhsJHtqAKkaw4xRjaEARoZ3hMdNAA7WQztsPTzw6K5szoaOFFnA8kFiZmAgswMDuRWIAqgIBMBY%2F4Yow0eJcpcszPUXr2bZhi33t5y5AudZB%2FIpqVZNp6dPEgmTCGmz6pGxBT7OmiYEE2RsBeuBAAFAfYCSDYCFiaMDn2m0ACdtO1YisXt52uNCDO2FrscTsHdqMifJ1m5uy%2FZEcnPRVznkPkQqbnifhJXwCtgGoziMtTWmKSTuB7kvuF%2FiCDHftN92hdhmGYZzYd57T9n4yTmsyCAX7hWFEmQSZEZfD7P8bWCH97Rftop1hkmahKTIyor3GrvWXhgmMUTpNgI3mdCjQcH%2Bmk7dutNSDrP79nGZEA9V1MeKL%2F%2F63fJpvtVVvsCMdN%2FEL3lCT%2FUnkoxav3nnQqckke8i4K82zizMkiyT8Ah4IieDi3rb3auvgIgL5m%2FgKMoQKCggVEOGXpjKByH%2B9Hr0ykx1pYwW0%2BjpPPJJryHLJh279CXPE0qaGc%2Fkgdhd53diZMk%2B34Wf%2BzBl%2BdpW0rm1DVV%2F82eMQpSq2v%2F36N4rM3VijX3l2AV5v4gs1pNJ%2FNRoWs5QlG11Rm9CguayJqYADOaqLkUcha%2BaCuYwKVW%2BloFin96y8F%2FuajX%2F61dusdDG%2FBEAwOICeMdfySD6b0gB%2BeOGWMouI%2FnrodjbhEr%2FhfhFNUrqPsSwTKPeMahqfd90oTAgIlYYzIDFOQ1%2FeKZ%2BtBlC64vlkJlLdy4VF9XZSIBqCbshdx3%2FSNB0MbfqX%2B5EhcIno9j4KP9gIjyCo7OfNwwABASYAHhgFpYrwGUINs8TwvAAmgtGzCCNCOdBTcDo2l2RjEQAWug9hqNTlAoYon%2B99gd3OP8Q7tACmiu0bBSpAuqCTq8q2uHRk%2FUDaw144ojvU6ELgZhtYGzx5%2FynMelK0EARNPCAa3fZ2V77ZVwHtXgNmAU94%2FIW9Ug%2BA%2FBy4PHjsEDuhkiOiNlZvgczUc9Ku70TS2Bk26q7ivEIDQq2IAAiINFxtRdvHsHyz7N1S0wDkIGEicjgGrjNvLbPOYLeiCX2fGNsc%2FIMsyKKqWXGrOtgfvEQOARsOqVQBPNUwjIueOYGIAIFQcAAwMqxNMm%2B3xafCgHiRZHiojMmEbbzEG%2FsjMPfi7wd3SmVTJg7suEzcKrwrxTLxEuIgABABkiByVNb6TwZPZ2x6nTXjdnl%2FOEgbGAwAVAAECKeLAe506K0C%2F5HX94xjFoqGYHguvqtgL5rrTKBX5CFY6RZJqwH%2F%2Bebscg5uGd9pj%2BeVxn%2B0nHVqYd3N%2FVsh27jZCCPi5R6eQ0Pkt%2FH9YWC8sRoEUJlC%2BnZXEEVR6IorClGwBxeBm7bK1Xjp4QIZY88wn4sNEvDIpnWA5NeQP8h7Oaxq0%2Brnk%2FM0HAM%2FiWMggQ3lBABAdwSyfMJZzRoYlzzTXX7CJUYpJ45I4wABAAOQPMJQ6ZBggQM9XcaLeyD5O2YeYHFZmCi%2F5O%2BeBfbBngWMOyZAJLzyH9LFKnqmKYauQ6f8gKjp7H4tUiNthJB9YJETQKbj958EARXCQgFis9HLMvsiiPFVgS9eug1NhDQ5QrkG4MuERADAElDHQlyHCcbuolBSVf3TQAkRQ0GgDYo2Y9XImWzGIj%2FW%2FzEkb%2BYC%2BxFkjYFhKcuOBXPwofWTTta7QfdI7gM4cD8w1WCVg1eJjQYQAJAChgYAECgVV6ACFlmkhjV9OONY6iFxAIOt8QxMBrOMU5lkwVVQXFXJ%2BscQrQd0p%2B8PQplVRH4aMK94cReK0f7xB4cUkVlitngnlSI6rIYk0ArG%2FzJHuAd1cRTb36SKqd%2BEEpDhABBWHm5xy4KgfKHRPWuwNm%2B3Mt0Nq%2FkHRIUQh7Oh%2BuncsvILNR8AxQ22gcT%2FZUO%2F2LzhEOTx35gDMFSYDI8zz4MWDjyp9Ms7Abe9cfCABxxAgFFSUfuBwGw%3D&media_id=1254206535166763008&segment_index=0" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:31:55 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:31:55 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_nf5FTSJ6nKSAgJW1o\/tyHw==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:55 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786111509343626; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:55 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "66751beaca35821b237cd01221b29bb3", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19952", - "x-rate-limit-reset": "1587864356", - "x-response-time": "30", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "00709e2d0087a955", - "x-tsa-request-body-time": "96", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"4%2FSmelybPMeReVEoi9MliJPncq8%3D\"", - "Expect": null - }, - "body": "command=APPEND&media_data=HhT3ZoZ0Mo0%2FAFKQ1y%2F5V7TSNZ0%2Fxj7%2Fn2N83rrgkGEmCNhQZO3MQmiMxZ7yAjFXMSvMSrGrIn9YncwJVFZSRWJxWkASorqJ4tpSUzYLCBQl0ThcsulVR6gId5V532%2F%2Fqq1HH%2BhxHnP4c9arVSLOn2%2F%2F%2F6HSYVOfZ7j8Lb6W%2BoOUjpMR3Ptf%2F%2F9BYQ7u1d9Ov%2F%2Fobve72uvt%2BzBFRPQ1iqiyRkecbHSmjBwOVn3wliZBfKkixOonrXmlitnhaqK7aXrUYxlKIl%2Fn2xG6eyhBDA2nCS3cr4K%2FHb%2Fe2EVL0Z4jrhSICAICNoejFHieb%2Fh3cAIcehc1F7UYIs3rAgAaACiwwgRQ0wASev5mLIhnSeDGAaMTFcaZ8Qoq84Fg2yqTLQrPAYmWaThszgB5OmiaJYpoqqTvJMZrxPo3%2FvH2XB6sxSU4JzKi8mbC%2B2s8xIPqXjW7qM73PB0BEWRlYGT8S5e8I39aWZAzURsPEyypqgw9wIifzwwPczcFIBeH%2FnQMIBCBXwgH2Xc9oCL3AN7TUR0bXerFqdBScBgytd0dgj4MOwySL7Jq%2Fsh8XW7baYaR1iNivPVoKnJZXSi4TUiIM3cjLt8fumJfDqo2hMm%2Ba7lhtHURX4OwcigmT%2F4Za2AD%2F4EIF41O5qaNOt%2FjZwD2EttwsKItvyDjWPKlu9PBBK7AYSydQgtTwZdIgAN77hT8vRZTlGCLTAo5fxy%2BCFXkPktTMLcv3%2B7seRiaT%2FBWL6bWa%2Bo7qwidN%2F7hpIogxMU3tYAMc4Hj9PURMS%2B8h6UP1vi23cVNyICjQ46c8Q5JBwABAQcCAA9XjovB9P%2FdEGREJAOdimTAYQcvBDJnaVdEhDgX3gjR205Gfl89RMlvthGSpuAphJdIO9%2BnH%2BkbUzUbs05dA%2BAYHAAJVzoUOuCtD0UanC05nKpYSJMbfYTXk2zFEXn0SegG%2Bagjw1wQfQtzzmvwv7aLKAWVjOJywwATzI8C5jgIAt64g6%2BEABDluDOJGqJF%2FgAu8kTMmABnAtU7UiAlAagpoCVDk4B0TxlPDKbWvktYDZzXcmuWsGACgV8Nhw%2Bj8rjYKKqcGKPTIqSD08AARHaWGAC%2BhITKMgyA8MXfkYnWvDsABAuzM45mY%2FfHBnf%2FOHmmvmmNNEHtKOd0SgOnIF9WdgaFuFzm2J%2BrLgYeN7%2FLT%2B90JgRD5mhB7LW0IWKpvW6HDmGjXn7LaADYstpa%2BorrY1Q8bN%2BJxBMkd4rFIDqOJY3vPcsdUUVCoecVKTivPwo1LMboBgZ0BgexDibb%2Fe4VIctCby06QDkwbnb8i1RJydUoy8IAQACIB4QABMA3jjpMYJmxtkAw2o%2BHAAHDHUCX4wie7QggwTX49q9TbguoG5oOkfl6lVXvjCI7UP6FVSEDzB5o9MEyKwZTMtYIEdDggAHhIlAl4tI4KghW2DR%2BV4IT4xXZrckJGtY7zhXPw7TO7gug7FGeQaPBvfK9DN%2FMpTli3WZBsVZQoAAgBqAgWfFEOyuMYew%2FmdzZrND%2F5wAFA8OgLKATb4ldSEPXVP0nNQdLHeubhEsmJ%2BAMZODuI8K37qzjzSodYgegwAYb4XIcwGNYvAbnQAwBtTwMQXYiiaP3%2Fw8Vp8rD6PUNZ33SwCzizhWGqB7hA5P%2Bv8QEgDxuG4%2BG94vUel8BI%2FTr4O0uDFO4k9gFUo6ABF7LGdEGSVQG7VI8e0Ql99OnRChe4mIM6VvblwGzaQPiHQQBDkmBAAHQAYMF5KpbngJGMY%2BBD%2BYXkYB0SFKVyMDwOTHHrEwEV38lECiQY8iOyd1hELcHwIWnMGcfgu042HABgEdw4HL6OWdUGdjh3RmCWe8XmJxpBCMQoIACMBoyGcqeQHFL43awmzwOooM6mYUOmQ1C38gJSfAOFjrVaw9f4KxtYj1fibEoXpT%2Bt8IRD23x5Vif0TukQnfpeXLxO5UlxWJ%2FRPM7%2F8v1VVrrWq%2F0uonb5EVZVhFHDyq%2F%2F6f%2FciHvk67rgbnwXoNQ8%2FJAHksgHSOLFPQAd2y1453SDB3d31NWB81iHBlDkDyBqZEOkwQaywx0Jzaywx0JzDXXD2FBqIEixbYMdSr9rFH3ieJsLvq6JwNw%2BfsuO1ewQNRjCwRyFt54b5mejAL8BzU4ZP993Vg9xmZ39l9rl4PeQciOLe8hTj4LW3B6tNNR6enq2IPgIAALODANDKxhHJU9Gld1%2FdOsFyewKZRwo78AxdPF%2BT8eOD3YOCip%2BRAGvfUcXWKUC60y3cRB5SB%2BMPXejx6g3G6ZkHx4SKDVf365ow%2B7hq%2FfKyDlAhbxzA9nd9q5mFJ5H5pgRW7zA%2F84MeG4autKdjWs25kFaEci50PNGOwg4wc%2BHo%2B53zvHr8IAAwHJHBgAECgYtxT2YajSK9pooFmGH82QMyruZt%2Bxu5VFf%2BpP82xTE%2FM2QyHp236DXRE8H97UvLvlEz4bDNapgl4VArabz9tfffCAE4RAa0z%2FIIiZXA8W8dOCUwiZXN4P4BFTYvPP4dE%2Bk9DzAE6fitTPvvAwnUOa1SOzqDOmCvnE%2BQK9NV4B4aS%2FXEJ9D%2B7XWu%2FcfFTHcybsIAAoKHhIIFAIEg41IddhB9v0bNYGNHhjCxHhD%2BW52tk0x5KTAieCaeEKn%2BS%2FNM3Xax%2FpmsRf%2BvcEvW6v1QgETbi%2F%2FUAA9wtOVWkAaPh0SoPI8EU%2BdPARAhSwOAARYEXAsP2toBiO5BRekLAL884a7hp%2BBHdsZOzAmL80NzcXIvydMAEMYimNWM6rYxUAKAFd8CgLWC2vkOnRogDdFml3EGTBTH%2BDFI%2F9WDg%2Fv8IBOMCwwAJhYAYk6AmXp6LrgQ9D5Ldtj6Q7EgC0gFs2U%2FaCsCSeLgxe4tvEhkv9fKGg8MFQyjdEEhZ%2BEHZiplOFIyF%2FLci0C5VCXZj6jwWUeLkIApwgYA8FQ04dBfRwVDL%2BsiAW6yGn%2BqaU%2FYn%2FF0IYcclDpWi2vAi4wU40lbLlbF0mrYmUXDz5eFyDrqMY8ngqYGjhATqRfEljT6BCJoTsjhxwAKedwQxr09UzvLuOtaY2Ys5wtkag9GfYnsgNWG5B4zZWqOlGFyBhAA5BBxAwIrh6EJgYytwUSgOYId8CYpLQfBIG1AWo%2Fx3gMaMlcS2%2F9QlBRyg0zDN%2BIAwBF80QDkFJlX%2BCQy05L7n7PY%2BzweVwe7Kd7sfDDJFgBgqHqL4LBmcHyxt6ULCpOCgnWJMCiYsswchwVzM%2BKh6nClvMwBYi%2FkDucyEEzA22TTMUJcj33OQ2XqA6kK1UEh1LAumKlCJAACAiIBoACBZgI00%2Bdsx28vyMArEAEWPzTedzGbSKYbXcJtIpDD9IV9RUl45%2BFhZiuIkj3pEaRjmGtih1LYmK%2BSecffgXQpT8iTYNxF0EevpBPjXMkyIPXzaXVWKTOV3JJtjevIfMgtVjGPI%2FgGqYkAylLbtyRpntsbR07f1sNKfM%2F2M9OYF%2F9JyoCZ7OwGgAgi%2BBMHWRrBrugDKG3j%2BG4CBAyEhAgpwSSDORyuQbgp%2FnhNf%2FKMAN9A1F9KcCg4RhM4cpjsVFtPhEsgCRqTChg7vu0mO2I%2F4l4B1%2BEQFS4tofMMUTCjZitNr2ye%2BeLoGUE2G43F93AqGN5kKJMSgXzrwZFWDrh4pi5OgMAASDIImADBjZY9YlI4FWKpLQ%2FPx5bu60TyT5g86YByx7XgfpgCkqK4qSyVdJDOEmyDx6IfgYMQ0GjyvnAigvOFQsXEQ2oks2CKAIlq916MAhsh%2FsozLWBCbV%2BAx%2FNumlh9l6j8H%2BOOLWr7wgAPShEDvabxK6U%2BqEcI6Eyb4bah9egSj4uTluTv6sm1QF7K%2BmVUpmdbqpv2yyzSyk6EG99QH3HDIUzL%2BC2K7rVLuhNQtpiPmFt5vIClOb4ASTkekfnhqwT1JxD8zwGO8LBDhrdpRRVRgGf2CA0sCAANhGC5d1hFBvnrVTPfQ5p%2BAlHZkvYRoTVQ7YQuYedDPT5MMWC%2FSfwAeAZT%2FzMVWlQmuvJhwq3syY%2Fz8VNRoGPQu7XmglxsnVeEIWHCAANABzQAhIjZV%2BI8dnrjBdl9gJQcpdgZwuQGw6hVIliwGSHN9tKScwSnIHv%2FU87kr69QFieTGuCeb8%2F9R2EAlY2Wn5RiBjkV7ykOLiZPSq4lXqVYnEOVEuK%2BifFEveIlAdHxpOlVRv6n%2FCM4AER%2BVe0n%2F%2FpguHD7%2F3cXviOvLkDd8CLFnU44WegK0HRLAOegsIfpwx1Cj6AfefhIA%2FDguYfFyJ33d%2BSbAvjUL7UHvA5g1ThiqnMasEDUsgfI2tq77XNwMJ4HDqm479f6o%2B8OLvf%2F6G6QQdCczVOZrric2rN5a59%2BEi5ArQYO%2FX9FED7s%2F%2F%2F4rHiS%2FnbrwKPLpTLKvBSoDrf04%2B3%2BjP4XVBAng7i8VF3V3tgMddZ63cQ3Ge7m6UMRXA8WYGROB5lB%2FQ0dupjLCuxXyOh4mz%2B0SiURFqhi8GO1JsBdlp3xL7o%2FOUTpjCErsS8h%2F222VhTTSEtx7N2plB4AWw2tkOE1bvvxQyAFaZTGZUVyO9mv%2B%2FCFpshKrcEAAIA5wAEgMAKgXI3Gg4ox3Th8sJ%2BQInbBY8gKCBzX7YTeLklxoEVR6INpzWJ%2BDyAySABSlnfR%2FRERUJYAf5xEDe3jaYfIuq1eh1CD%2F36TB7viwLHvzB6lcJRCLgOq%2Bpr9ATdez0dA7F1ReTnrs15LaFaNGjMZ4Ub7AvloYC6sRQt1oAXuja3q9sF5FJ%2BPvgb1LKz8gxMI2pcv7h3Kg7V24apXgqaw0Y08UrCEGg0tjtOx7699uLAgEGi25b0y%2Fhf8HGyzML8n9txGwMIAgNhoGNDEjEAwgLU8eAV0yZDyOc8wy0YCR6b%2FkP6a4BH3%2F%2BA2IzwAHgVt6WIfhv%2FxwIVYFAeZVrGmIC0qohJwQABMAOwBQQE3Af%2FBysmM3GWcYMofgJy4NqJkdf5VU80aEMFG%2BSz%2BKcstOJ5aAAabJZQ3T%2BNI%2FKz9rEPTGukfq0jLwGBmDP%2FjFLH7jt%2BtushxxjzzFzb3F%2FcAMY6FFKwD0Ddp0bM6WzHEuRM7lEHYABEJIAm24YP2bDoEGlCMnYjWr%2Bl0CYgGJNgiVQvLr6uMS4RiwNdkAg7rzx1%2Bae%2FX%2F6Od8TKkgHGwq8t2AvlUYHjZe%2BA4ABAIAsIAAQASgACAcBAEfcE198OnQ%2BGqDRXHiDvBTFCbACspiEn7saqHtkDBBjnkYgO4%2BB3qEtAA156jnsSohFlf1dpXCfUHa2MEEqRzg4tng1YEpT9FZ6fKcSJHu%2FtIyAVEb97yF6gAAARCAAPAgA%2FQYhtlkYxvWVGBwznPT4jWA4rYuRwa00AMld1zNIDTCBPrCAAYC4%2F%2F%2BxoiardOtnJwSwfEf%2FJNz%2F1%2BO97uFb1x6kw1E7GMbdzQWl4azzzAyDIEwJ8tcKblndYxoESbbOXLXt81DMhARvUJrW%2F4ARts3Cj1%2F%2BkxWYynBr13ABTH2J2GHnRgt%2BC2QLSDtOoClhcIAA2AYHC4QEOaIFWBMGYBjEH84AU%2FkLKXkJJiKIbEMY%2F0KsuFeUwBK6FFeEfd7fte5HYpMTSfLAP%2BQqBPfk%2B0oFyxnt6Sm7RKZLlk2EAAZA5oSFQXiKhMZO0CMOv2Q3TuTIaUdNGisyxL1aZSzPRSAOD1DZC%2FbCjJroQPsLfHIpj4UHWjK3X6RvCk6wYtrOnSBqd23e8HZfnNCbw2%2BthAEodgYZ%2BDYra0ZD5hY0SBYU0fBd0Nuk0tbyMwfQsB1naKkQqBsDfkEJ%2BJ8sh7QAnimB0IYX%2FgDNISmvRFoVh3T1mecFbvgi5%2F6i4NSsoUs%2BAMtfZz6NoBdVlnhjb9ia%2FvAlWBiZI6CUaCLNeMdOh%2BbA5ZvcDBUJ9DT3gRW%2BXTCbW30mVxhoJiuarIzQWTqKrJJhyC3tW1f2L1mpsuS1wO2KM836p1FVh1vcNZBnPyVn7c41gAX4SxWWapsbwo7xUKU5sPU92bAW8oWAu%2FXfihWK%2BAxCvKpj397roQABEXzQqENOV4mVC%2Fm%2BJ4WrqmyiY4FXvzdOgQSj6IivSaoQvotj7WI0AR%2FU%2FkfJuZdcbhhVCgcBlU1GfrwxulPQnioMKLEjAVmKC0rUUymsjaSQhDGIt%2FA7QYsbON6ZGJnOK7%2Fd0gSlBBl%2B8%2F7q61RCfAfwCO1zBsvIwD1rh6erNe93rJnoEnSyzN98vjjitp3zw746T2nno9%2B8Uo0g9%2B4pED81O5JXK37B4GafEmrwaAwACTJCgACAqAAIA7o7%2B75mpeCYO41TACWaVFIikkoA5pZhQd2EljrJCA7wABADz3NcZzXM2PJ8wCzUej%2FAmbjel7XA3wgADYBRRDuq%2B1IOLzUC4FKn4Mqmh52H4TqVJcViXFfS4rE4h%2BeJ5UlyYJ6VipQHcwKEl0%2Fidronai7QGwC%2By74G0fTQGTyGAWChJIQesNyB6UIhiAKvXUVVKyEkyC9wMWx44I8gveTv1r8khxYp6E%2BNXID7i4jnHyo0oo3mYGMwS8ROwSQoOLgMBwgOAioXBlGbhWKnsgHHJgofGUT%2BZw7H%2F%2Fx4dKsl%2B%2BoLoSa8hK9nzYbD%2FmPmeuq4BuH0oAPxlCKnEDAErF5WshzvAUfZ8gZIwYQsDok6GW7kDzfQ1l8793quFVg0iFvqG4JAapwLw%2By1BqdNBYAgZgJDx7skggK3z1kXFBj6eFAa5uFw4UhDqsMJgAsQEBKA0xIy1Q%2FYGyFJsKv4qilqN4JBfhrXFQr9DTLiB0geeLqY2y4olk7BfHlU0cY2PUDgfgMNpEa49xoZYZRx0gGbGxroWlUH%2BFP4YhFZ5u%2FzwwFROSAaRV2RiRE8AZ3QwjZwKbtDj73%2Fd0QSLfWWJBO5nmdnaQ3f%2B5Hhdb7WQjYgxBC4z9Mr2%2BB9oI5RLz3g7r6Gzgh35%2FM0ef0Ss428zI21JYCtDRM0HKzHyIndsOuNgQD30x%2BA4TmBp9I6RkElfSjtHJYGJ%2FbhF8N7raPjRcP%2FEYj3uiUtaYhX6fR7hxSFOGqtAQYQAKFAUYOKNkgNKAi1%2F5DHpvmfIyDz05%2FZMiQwPtNEyzNQoyDo9fkyp46ICaWG%2FAKYppPRv%2FuQk65I2%2BrbLNu3fgImqYMx8zCAXBGBCYkGHJxhdQjQY5BShvPYri8bfHzC3%2BfNRRVVKTigkkfo0mg3NPF7s8yCQ0RQ72uxSGNWg%2BISvQXcdr%2BM%2FS0PIdkMACtljNgKI7xfVIb%2BsAMMCMJYPUL9GjBD%2FbOAmJTCj2C6WGJPJoy6jvy2Cvyfa76MxO44lc7IbkL%2BmqvQhypmOfLjCb48t6PzCiop1O%2FiKQCACfu7Ji%2FrnKygpDSCPF5NfTrFYKxTAygnctP59iBIARe5ksUoTc4qxhWOsR8LxQ1MG0fAWABFDgZBQCUhD3TvfG5REdFEz0ColYPPOagpB7VQaau7NI1Eb1ZAsbNRiSVx9sAyhwMvPOYWxfwAvSYR8e%2FPsDcRzQtHJapsBSAQ4yY%2FreMeIYDPyZ%2FYbIMQABAFA0KMAKDiASluEhDvDxxOt%2Fnh5B0OtO43AydMCUihx%2BjsvQeRAbAAXNQZ%2BGB%2F%2FZGRpUNkrP7hJWan7lyPF1lpoL%2F%2FJ4T%2Fnzu2lb0uCm89%2F2dMuBN3B6O4KbCSCUIJmhcwSaZsgtYv%2BR6QIKPXuraMSf8c7n%2B2IkIq93XJjmUxMQFuGjpaTpydgAfN0BsuLH0ug9MgYcHAIJSmw3Ygvg0yxhl4ho5wF3z7NCirWdnt%2BASLYsqaAGF%2Fu1Y1wB8xdkY2AAEBdl0CTXXBzo%2F9fxxqQAZ7NfnXRAamt%2BAlBykaXwGnxjTRBP9uGRYUaBz7WrsIQklxTR%2F1Ju4JE4rfXPnZofRizIGCnfRvde3ggQAoBRAKAEAeQDCPLgIObt%2Br9eGhlVxhMNaoUGOKBugEvXAYpIgEBqC65V4XqCVvmYfnSJzJpSLZjjiAXS2DqVEGJuex37tdrCzBNr%2FuAJ6319eHR0gMQdBnRGwAgYDMAxBg%2F8j55ouMSfMBgABAFAArwMAASBIq85kAWBBS%2FkGGAC%2F5iNNQoaP6NrH3LHAzDAIB8xDfbTIVdTJ6IZD8bzCoHVKKZBoOHOjXPzABllveAkdvwKsRQM8I%2Fr2scjFg7Vh%2FZYCnY2rWh%2Fnd%2BDOr4VawEWe6c5bxA7hhVEtUg2s7QEoCHAUAMYNbEXJ8cuGvtGmdr96OlyAAEAdjXyUEELTGSQ03JuUdYAlBqpkzAwMDqDr4RTYwXaZGVfgKP4rI2kl2%2BoSX3PXEQEmAlTAF%2FFpMu2LMBesW5OUKIp9p6CaIBYx0%2BxY1vZD6MbBZT8LkMAw6Mt3J7UgbKg0vqD4EQYHFBCFgrkh1GvOHgjsC2sACre5B2B7sRXQ6AnJIHL8wCR8IUFZaJjqTh2uC9s%2B%2FwXI1uQBHX%2BffbQyiBStwLK58%2FyR5Sc8C%2B4SD%2Fnaq%2BeQfIcqvGdLwI9mN5tIaug3vw7ai6X%2FHwVQ%2BsCZgN97M0Cdn%2FzPGFkfb%2FYOiQkjm7s4tSfW%2F7T0UiuvftDKEXBCSiS712KeAInZshZSoqS7MNXMMufHhVOhyk82pnnsum%2BoCJQdS%2FfYXLB2OiQCBQBlhhHoiU5roieJzxY0Rc9AAkz%2BpCDcPD6COwGmpPAcwVmViYAYQWgBEBS3eY1FoVxWO2mYa9gZh8dViIK%2FDDMwFftc8GGs4GoQ3Br3AW4tf0Bf9cKXduZZuRKcoQEKhAJE35EnwRLUsflixC75BC5Tyyy6uuBSYVYWrf6Qor%2Fk%2FAekgasdMQa6koSHeJgGJngSXlDCNNhwn%2BaezVgqCTVD3%2F5mUw8R%2BcM%2FjwEQl%2Bg6nwJmYBbY46x7rhNpvgQABAdywgARlqPTQCcByIhwILvjYaDUvMHgxYN%2FVFroro1W8yPHXoETPoZOXPqJbUaq2h2GkIHcGbw2L6FazucySTZgk%2BoL0szGRFbiX%2BXgF8QF0EAAdBhaw6BXdhFjtfoWXy6xEtmBHqf0pXDEt5V0XnGHQ%2BqYTQ66U9RTVCS4v1jU%2BGyF%2FRb5a2Hg2Oxh3O4G6f5iUMsvcMXruOfWCpFIjn%2F9Rp8EhOfS8qxOKy0u5XLxO5by%2F%2F0VV6%2BqrrNK6YnfUblDAYz1%2F4r4%2FSr%2Fh%2BSr1X1zf1X%2FqQMUwsCCCwTnIeNPOwP0oKDMCwv5wkXQDMxbjFADcPYjAsjlHnVYK9fyDyZFBwsB7L3Iw6oXEU2CQjJgaTF8g5NgZUK8fXWO%2BFmHxl2SvCsKiquFV%2FXA1jouxDpqgqHkxAQ%2BHyX21UsNoDOLhQ6wHMdfWpMDHx%2BH2A3Xrqq4f8K0HLGYFccf1Ff7Cw3iCpg5ZL58CEIFKGLhiwMw%2FDiMu%2F1XXWFePrKh%2FvAlmhl4%2B3iRIHcFUXxvwcHS31%2BCow%2FJtEVagNlwQs4Me3tHsQlkpSuSoqZtGIDrbAy%2BtM1lAb%2FECSKFhSe8SxAkp3u0AzMdIGg%2FvKJ5bLSDr%2FCnEIBeu6a1TPyNAAgPn8%2Fh0QaTnDcjBkGCABCCgmEBOJwOz%2BhFHOO%2FT17IgMFh9fobQOUI%2FjImaxsbRrD6R2jEoZyD44JfKsJF92Wch0R3Q1V072RIX1G%2FwMgXipgXVv0j%2BloIr3dTy6E%2BOPmE66HSyRzD3TJFs1KlW8DUSKvi3GNTwlCoN%2BmMw5AgVEGC6YBPE8rJYoLK8%2Buo77MqQ5pi9%2F2CCFaOCNBPeFI5%2BzTbCXBaMBcdGYDe%2BDaL4B3HwXivzfobsjZUeRdf6MKygZOh0o4rd1ieQqly4xvEZZBuNbjjhnhPqBXv3IW0wfqehRAAGzp%2BddQgWQDCHN3sD%2FhWC9tL6m2HVFbd%2F7wxI74JbvWR7VSbnhAsBRQGBFEeMApA4INbsDlpk2YHQ0lWAyj5MLdDUtGMPeHzWQj8LO1aAgL75VBT1eru%2FJyvyPuh%2FFPnwH%2FssKWri6KQNKADrPvRI3gAYa8%2F9HZuthhf2lV07O1%2FSgMV4NMAMCACAKtTT4jQ9JQSsF%2BAhf9iwGeE%2BVsEHnwQxKV9OPmHyzSj%2BAv5k7u%2Bjvwkw34C8Q%2BsmUQfHeTyDs8C27z86xpsbKH%2BLX61lDhwIAh7wMAA6ABsQdBQwoS8cqDZF4PqBtApQH9P8FaeBj1fcF6ABbCaQCJyygCmw0Q6v%2FUMvWiqVFj78yLPRpgG66mQyze8MwoyCEG9yE1Gtdpemct41SSptjgb1m0hy%2B8Ztkc%2FOlpWFVeX384KXkAAIAAKDjZwSEvCgBgACAUH5Mhg7SAblchLkewNgaD8BkARzQ8ImjhQ9T7UnKCxuBQizraChiYCRqidBy5CzJhiUGrkrb%2BGEKsoeKA1gJIZwQcNJKw4vHYu2O5q%2Fmc1yofSANTA4LkCACAWQcbAx22ZpU0nsAVAST11zJowBUGG%2F%2BV6gKOMCOOHj3H3NTXWQmfPiJkt9OO4DUuQMu3gKKsMmLd6DLD0KLx54FTmJ%2FARYBmCLMBCtVwBkF6cn529ZnHp5OKgDIL%2FFitHgL%2FBcVT5QbDQKkiGrzjRvtJXIDPQ2%2F1laPSMxWRjgnERL101MQ6hX6BkRFuKpK8pRATgFU%2FRrliA4EDGcdT6yXl%2F0RXXvcGEHcggdjKaWMmJbbSw33bcEoAM4xHeMdAabLkDTiI9fYFw8qomxgNfa5N5ELIypjK4RS95%2FtJWcNySTBx4M%2FyLcHKOEO6GVaHW6VCMkc8IELIQDgBhWLHbEmTwD2BOrwFnndWprVjU5ZJ8zLhNVGC8bENrXvfyb926Qfifyjyl0nMoMNSBgEn3Gu9dWS%2BvijDbRKhKiAzseFyDvFilmR2eoHGNdBtKXd6COy33JKwP5WJ03aCeh05b9G1CvHLDG1HCLgMLs8PjoswVv%2FokWBGcOMG8E2gr2fImYAcwDPL1vNKYrXlgj%2FJauQpRSAIu%2BQLKVzPD83nM42oUnTF8W%2FfDwcApsF5HVD5sfqQN2QLTq41j%2FwSh2aPGJSKNsltN7wsk%3D&media_id=1254206535166763008&segment_index=1" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:31:55 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:31:55 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_Z3hFEsqm1\/ZZt8JdhNbQBw==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:55 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786111552419044; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:55 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "57f08b9e5acd38f1913056871cbaa928", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19951", - "x-rate-limit-reset": "1587864356", - "x-response-time": "35", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "00cd0d7300ac94a5", - "x-tsa-request-body-time": "98", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"nLcH8ZfnQD1ew8r9o8aBL3Ot9b4%3D\"", - "Expect": null - }, - "body": "command=APPEND&media_data=cZis%2FifBlNa7A0NoHhJGn8G6eEq8WBcfz7W2aYVDKVFw0V3ij%2FvbOgM7QDLsufz%2Bshig7Lzag4%2F668kA8c1AjLBTrfYSd3vDMJMswY3hyhyqgfuaM0Qvj9nMnYoXYCTWJ0tjs9luPdqPDDABrQwAwPBFxAzEBWCTUxYWXWQFiiETwaagBSjIZ1FaiAKrigKGTtJ5otpVFOS0s4nT%2FWuHWBiZPOcMGnVzJHSpyjUZhh7zXTnmlXcZIOCr%2F%2BAtrmDUMBwGJmBxS%2BCYRywDsHh8Vixygf1RniqhOCHn60UJLINJeF1iz29M54tpn4HABSHnM%2FA4DHbGPJ2Lg8xabN%2FYexA1iKWMdYjH4N0S4gmZeWQqZoEQBOyI6LDuWR339A35ESNkDQwutHPgQrkcetCsqRgfNw0BvQdnf1%2FnZmjXNDFdyDYmOom2i6UCCAeasDXg%2FFjci7kIUzCJX55KCQN5DjX%2BiAZFazqGI54kVSy6Q3P2%2BwcABABIEABAHAtYMnhK3MTjQercS%2BJMM9s5B4ms%2FnVd9eqGwwAAtaFV5ndB6SIBlcI%2FP8dN4YiX%2B7UltIA6HyKIrVA7EtqBgY4SFWFQYME6BzYdvUeagWRXY9f15%2BtYjjgT3PA4IqFzyk%2BMdDEOdwj8F8Znsbv3%2BErXPz4UHnA5yMzXMB24W2eYvgZAN2XzFTFP%2Fj%2B61EcZBtVMEWjAThn5fyLIHHCYAOnEovueuo%2FrD7Yih4JBdsC4hy44IyvYHhVa%2F1cI1sO6YXcxzQT2AZQvp%2FhiIMVFkGbcCZFWRHXb1un19VFqkp0e12tQYfSuEXEgw6MRe5k07ucW4ROuqyUUQL9peNKD6m5pflkGkOUv%2F82q1r6vEyhqj9CqhPzft9umnp9oRUFJS1P%2F%2FCuEGup9v%2B398X4%2F639a6qq5SqGcM%2FfkXlRv1LQxgGE4raN5XvPnW2qipqv%2B6mCk7Ed1G%2F4MvIHRv5fbzfSSfyC8IMy9glE94E1kZGB8m%2Fzr%2FlqEi6GYFZeBQDTHhI%2Bzk6Z%2FBVP66q4%2FBq6vCeaqfcMlnG0jcGBdRheFJxPud%2BCPqINqPrv%2F4Maayc3%2BdyG%2FX1L%2F6wYuCaMfh9MCBhWeFGWv68EQarRU%2F7osNAdI85Rx94FB4xA4r0Uf38DKtflekpu59B0Uo2WBqJ%2F%2FyA34WeXIFtXe8EO4g97nr2ErXU9Sd7vn%2B%2FAGEAAwGDQRfGHlsJFOAT21UPQMAKMKqQrrigyP0x9spDKASUR03sIcxA1k9Vf7jMSjU5bnDCrfXO9XnMxp2rO7wGVQuVKJ%2F8%2BOXqNwBBm6fT5AG%2FAhKTsdT%2F%2F7AhkDn5kggACAMSkIgbgaT88mICnfF3FbVirA9qehtsNEBkGt%2BFHRQ8%2FM2vO3EEK4VKY4nS6I8h%2BxG8Z%2BVsGV3%2FgcEQAxMN0BCT7czBa7DF2kD390fXXACB6FyFEhpeMHGdoJyfnE4plnEaLFqhDyHlCIB8AwGAAECIAYBYxj2zMvNoBjoGPYACaUMOYg1r30MfbkeiRsAShjbM6BsxKAGpquJogDYMWv2q%2FrtE4crYSMgfC6PGGLqw0sDtnEC415vT7mXeTROgE1WbY0oS%2FCD4Q1JmQtgTagCi%2FyaVQYKBBWTkNVMOaA5QwggKsK4eG%2BUzAcN%2BuCuN3O1vO%2FHtvAoNSqQSAdt8tzYm7NnHVBUKUBZch3XCyUSJeHav6j8sgMqwNbec8WTOA6rkN4qjJBgOzCAAPEBfznnukyl51EN0MwYO8kZAqTqU8mYL45yiJdFaYxuvdOGIa43Hz00GjSM4a%2FynbZdsKK1DbcyVVsgN%2FlMVEVC0AlWqQfcgkgGECBDC4Gg30DbqhswZy48EVVlhJzB0ayMHgPo0Mxmo62iCnc0kdvebHYYEqN0Ij0%2BMEcVXodJYc1G%2FTx9Zt3eEQmMGBGQR1vnmv%2B1o%2BVZ5ZAoJxi8y5mK9Cn119d124DEedyuChh3snLYtHVhZwW3mzngYcQSLlKN29SvVKOOZAF%2FxddlMg5ycApXk1Td7isKqiVmvW7CXI8Wbuv8W5CAcATLTA8pMLwIpwrUCy0IH9iHGvOjSDc4QgLOEAAIBAAAgChxeECkdyU4vH4BqjzO4anxdg91KYlijJJUKfsgcAHZ2GWbGGUuyMB4LxtVTzqY5FmhrXUIIF8PgODmIiBX5LdanBh70EeQOG9zodK8MDWdDK2Y%2BWAsQw2XgThPf5UQ5KEACABjAaEEwUSgSAYEvAcvhsUOBxvHhVF%2FjdGXPF5B44D2oTkupG3Q4FYD4F6mAYq9c%2F95yzbHbFAuPfgM2mxUL4r%2Bcv%2FCVO224NV%2FMJyL6%2BKDcOWwGBogfB%2FkQGxRBFbAcKxFo0jFZ9iNdYAY0ep4MyZeBkfmaQc3eZOKimJdw%2Fe6RySbe1IpTh6UVDL%2F32mSt2Cg%2Fy9JTeFBh3Kys%2FCCEwyBYRY0DAnXlOujN0nrKti4i7%2B97XXUJSJPjtHyt8n9o3lcgWVfY%2BX%2FnHEZo6goD2XWw48oNoamoHO3I3AQtd%2FnDf5EvnScfWsmKv9NGPP%2FMGhZBwfWYucUSimNxEtWJ9B62HUR0eLyQu7uzvk5E%2F1siC6gmTplFUnVSQHoqwVNSspB3s4YR%2FQiqpfHO5yjqhlXsKvPd%2FnOYOHw0wuQ0spHop8a6jcKr6ocmw7Yrgd8mRMxXG%2BtSREsRJI7iAaIYR6r99G2QD4yYAnKCMcPc3lSrfqbsRJmFh93uAk38OA6TU25QBxIsf2937HmBP7YBiPDIsTuZwxQMwxyAbBff6BgyBYNvo1sVAs3ngBM2CNaI8TnqwBpi7xceo4qr6NC9k88toEO1BCViv1A7%2FTCHRY0zG%2Bs8373s45C57GKOwcYcDJKfggRULizJxVNkUsg7AkHA4UUyzZ8SjYfofKiU8Kn0qtNRwV3reFPjijD0YGgdf4MpoKltfv96%2BOEWLMbqZguk85YT0Tf8DAxRBBQrvAp1%2B4Yl31Id3%2BGpH0rND%2FDYcljD%2BCvmWzxhyNh0Tzjgw0GQe9d4GvdesD2IYAAR5zQFYrh%2FAwlbD1uPjPpQ6IbkG0ntbHFJ834IUI4XmzDWKmHQKxGD8WOiUcAiAr83f4SFzBRx5Td8ToO3zeVYwFS7Y%2F1X3x5MayXeEDHAJgWKMUNJ7q3ebH%2BaWOCkP5X57bAKh8e5B5OQQvFhr%2Bww2QM2iBupYssWHhxxc9OSzSWWdS1rUFavCC6lzgdSYZA41DOAWtLoDi8ChA78MySA%2BIBvwFomj1OhNnbhwUQ3xX5UkulhcKPg4yINE66ERWWcKnpDE3YoTXSJ2Cag2ExP9rPEGEYFVVbOb08O5FA00zg7YBdCuOQq2kXeYQ0O3a4Ej%2Bt%2FQsjZMgmkELMDDoRhKH%2F%2BvB3mwNEaigp9Y%2Fm7Js9UTqAXRxayxRMmt9fwuGw%2BklnWGchUUvUe8Pd%2BBbvLpw1seJwBLCxukaufeqP1B%2B%2Fj3xhVUWyM%2BakUy2ZjcW4FEYRRcISm7Qb8bLCidK2mNQ03rBOJEAAICv4IbWg7P8IAI7yggEZT5zIC9Zh7Oh0wQsg9ggPKX%2F4vXqvqV4llvCOJ0%2F%2F05XFMaonRe14VwO8v%2F%2Bnwhlxr3%2Fpp6adaf%2B0Zr%2BI4Xr3Nj56E1BGmCSP%2F%2Fb5ItesXEx2JSf1ZWZAlJ4hAL7qI6ytvqNgPeh%2BOl8Wg39kUXt%2Fiq1XVm9SNktPe5NAGS4Rneje4Zy5D7PdhbUAz8Ku%2FdZp67fz3cBXrglJ%2FgSOsgfUx%2Bd9hhUSCwiQFLxQBtHfdZwV9GU873HkaSdQVb1GsAMjhFQgKN3vqktYM8U2NCwHwbtGEL8cAB06O0Ie2J50NZGEX83FK9PUWUo6GkhQKEOTjUPA4IlTD4T%2FgSH%2BEAAUagAGRmRM81kCbYoaepzcGEa%2Fn9cSoGUAOWXjYGM%2FEdgAvsZdGq%2BSKqnhL9bu3ozAFEoDgealXa%2FaQV0HD7ImWLMQQVpLqeKK8x%2FCF3wDOQOKBq4n3SbIDhyATCf9J53WWcnYAycS4bvfDEKPYKGFAMOGLnNv4rj4OWdPp6VsW901B4gFXznQ51W4KB%2B4F2eUGYNoqozOnLHhM0n1dzYRw5KK%2F5VZKfv0XeEF3ZIKjoZX436twZ52BWCTyDmkfYKUgkDKOj5qXFAHaxhTL9af3EHDjFN4AbAHQbo44v2Gz2t5mFrBSCGgs6U9OmI4i4UzORbrHIK9vA5bcM4IO1lmU0SwHTMJGQUa6f7gDxov1gcJcEEonsWVpPQzMI%2FoaVksuBB%2ByFkKOyEOUivU0SllQB0iTB5smxLCQKtlBHOMknH6yHrJrNOzw74eDlARJSCHVPH0N%2BgwKLDAgXZoqOk1ZJKLgKupGxQgKP4VhHMcwAwDxUxtWcHTSBMLhnValKF5BCo2qcYH8IuG7wmcOidhiyScVT9zhJ5TgVAgJGEAICeEiw3iBr0vOJrYBWE8OBuybAQlESuhQkuMAEbKNoVmAvmqB1AoO9vZvSSKcRez1ZOfjE1t4s%2BuqhR6EUJFQCveYq%2F6BcKg0BemEvoX3TbAgnUMEAAdAMcBIxpKedUjfA0wMu8CHEsuDDPdnIGozAsGEkA1tACCl%2FZEzynpoz5PNb2OEvRo1GkLNlhCZsSrH8VS4EXQkFt%2BW0zo99s%2BEAQwvgQgACAq4AAgKYj2NxKMAwjupiypxibu994AygJJeFOufBA8xkphwnOeu%2F61x6CiCGG5Z%2BWuQorgaWCN57SLOUOHF4FRkDPXfL3ADIUGemCFkCTAAEAgChOODUAU71hljAMuG9OYsTlwPRQBDcM8hBFuBV9kE6k%2FfEIItyEkNwC7OROT%2FcBaxGVyCR7ENFcpyyI5sqwH1sD8AhQ9Nh%2BdEuBW2ZlEOSB0NXhmRMH1XyCtveIyraTU20wHfToodomIeACwkAsAoGABUEEUzSeepkkOMzGsXPmJcBevLPRjMwTkloPPtM3dxy%2FoaaqGmmBNcM9uGIJXChSrHebtz%2BZKNp9HEhad5%2B9RbkQWb0A%2Bwf8KOHByJLthZ916Vug8L9v63e2w6DUPQvsFwl%2BHARL5tx%2BD%2B7QgssBw9TpbJsoMnz88JJoDM7DQZAbRX62onD%2FYev%2FQ7OOKIGfK%2FA4hdqCoN%2FxeRmkwh%2FKf7IoD8TO8fYy3A%2FQjp5RA%2BN0%2F6yul%2FqoqAOOH%2FPJ0YJ2YjeiwGh5dhiDG620yxPOAcBzCtxL8%2FbXbn4RC3vwFItdJtnYhXPvDTiqes46jdbhXFcmA3nAseeFaMfI8HtmPhHtkHJ7JGB301Ax7x0QhL7ANDxefAE0ywihdUv%2FPuCPxTIwKOq0D3BHS%2B9%2BAsgKEgY4r44HWaYkK51yk1cVYdMMFX310HHFGwE4R%2BDcwB1xn5mEkYGoS%2FAvGnUwfYDgkIouLfghQuH4l43wd7ItPwQRwNvEzHI%2BoiOLfgcNEDkaHJZ5qw5kKA2n21XD%2Feq4iNVxw7JRENrJg4KZgJwj8ZjYRSdTFzQSYB1wmANIuF1zx32FNkB6PKD%2FCyHOYk2GgOP68A4LoO1bUstZArXUcYFaHUmfbZtAfzEJqpkXwITRdC68YgHFVQQ9%2BvKMwJRn5HYeU1wtsFgWO4F8yOnBIo4GBrfj0SZgZzwY8s8HZ9QrqvHOwutID7xExkH1J%2FN2j0sE%2B6%2Bsv%2F2n%2FrGQ06Z46Wy0C7Hgj0PAtGPeC5S2Hn%2BLY1fLdb%2F50aC%2BsR7g1qJGTPWzKAAVC2ox8qx0ewPmFh1Km16fwpBCggR%2BQXH6DWh28oIxtLahpUmT1B1yYR6yAbymYDCmQri%2B1B9BJLCsyG8a57eDIpZRK51iXf%2F%2BWi61r11%2FSuon7RLqZonLR58PhRGv%2F%2BegVleutlXzKbcpVhmQCzqj%2F%2FuYvX9pSFStw9c3T9ffjEAWVX%2B0BHhhOvv77%2B1GQX0%2F68fCqcaVr%2F%2FrFeG5QEG1fGU%2FLf3H8OhxNKLKlpsbK13%2FtdCQIc3nzzn%2B5UDpf%2FfYEP%2Frf%2FQ0gcRKiD4%2F%2FBoA8NWEvz%2FMwAlQNj78M1isvBZUsUUnz8%2FvEIQJyfiexN9hohA12I%2BOK8qwgo6zuO557ZuohQjhcbMC0JZmHx487RRjUWAKIK%2FA4u0CHwe9%2Fr6vehAIbzPm8HFvhAoAP%2FDrqulUNbj%2F6K%2FF0CtlWy7p5d5JAHm3E2rYX80iOKQ7K%2FG4CofGvznw6TkEdAo8HFsCyHfn8jpCAEQhcTJYm4ZPsx%2Br%2BxCTsI32eS1ZVyXW84SDVaE1N%2BhdRJCjKaRjRC9PcqflrE9Q1oxxX4X8iJiwGh3goMEVDzAP8IAIFjpLYVUpetttZN8iIylNjjMF75CwcK69jDWoONZqK1aPW1gAZU6EFXLQXzKs%2BGDxHSbr%2B0f7jgFECzDYh1MUMDbtnhW1LdMIQJzBAAHgAHKJrje1LIH9Zsfg1osaBybBJO9BwiAspj%2BFaNsVA8D9VCa7C0mN7d94jt9hK2XtSnYO2CeMNgJszEE2%2FsYAkgMoDT0lFXUEYTC8anQZOAQAAiEAIGBCbUzIEwnu5KDdVaLgyDhaoaSLz%2BENSJbDHigEJ%2FrBnZEUxd3e%2Bc5%2Bg5uML6obh9cnbTGaMABXlNNdgeYUdynNWKDVIhj7w%2BGoQAuABwoIAAio4WKaE2fartcOhSykHDvC%2F4ckElwmK4S%2FBMxjAa3vN3M%2FYsbFprBonoN5ckbfZGgyU4hkjpxBmvHYe764PU8EHs3%2BuGcBAeK8m7K%2F%2F23mN5P%2F%2Fmjf%2Bt%2FT3wdK79YlQIlVOLERhPVLcCcPhkRZpjpx1HDnt1i%2FeZ%2Bl%2F7j6ek9DSNTVP9DgkIVuNfn9haXCUCoPHQXDkgE9R4Hf98BZ1kMl7PbXqarOtaehxCQr3gBgGodVt%2BX5KIF2DvwMfQh7YDv0vCQXMFDxTnadhQB1H5GXWCjL%2FU%2Bqj1%2F%2BralqvCVRafnwIlMEohvyJuB4rx%2FY7aQNBX4GS8VF0hfT%2BGECRWCCVHlN7PdUFZU6XR43%2F%2Fr11WSpBckxqRhEkP5f4swBuGxgZMPjUfGCDpphqlHiV6erEBccyZ0PC42AIQmYwk4DIGiDQXQNXLGIcHlkTCvYCmWUDVXKeKWq1Ff9VWEPGZQ73tqlz8GYGkGwV1mNbMJxH4UKB1wkzvzcOwuARMEgtL%2FC01TiXkIQZEQRFdcguBkwcMS4AZasyGD9DNNg2GqtTWMV4%2FqKathVmoXrKy7lrTUAyH1DYCRMKFfmhG0YsGWxYVwo9wOhxeV%2FkQHH8YGCr%2Bh%2FfUblqhHMROSYgIJRMWB1GjAK4Bsa0wIHMwM655sC4ZMOsKjLNOB3JCvEuF7JpViWVStE4YZMJlBYaEsxPIEqK8Oic2PLm%2BxbNaReQMaq78UxuKRQERrc34bqv%2FybPKXGx1cXF6pr%2BCHr%2BYJIhnzngqNL3vjUVJH%2Fk%2BLy6ac788PbH88AgqiqLH9LzliWRfgt9eNv7907WrjBPwV%2F3mYCgPl3Hf%2F%2FxQ7g9KunqeVkDHpMyLB4V%2BX%2FfRpOvriqueJ6feLuJxxCyHYiXW6DXz3frls1R0fQy3T0Mhx511q%2BSjRnbN%2F1xgDh%2F2cuO%2BdnWjbsa7wJYGAkls5gKzmHzWQ8f%2Ffbv3pv6qGxWv%2F%2BUx%2F6JXrrXtew01CP7HW19fUf7L7zyCqaJwo86JUtSIqLuWUuic3yjVCzy%2By%2F4itR4%2BFr84vfO%2BLvjmipnoLeG0fuKEhCtxdeHLAeHo78y%2Fj8Vpog0YWy5SU5p0%2FDtyEdgo6JXBMHfm%2FsBSs0Ky8PoXH%2BuuoTA%2Bh06KCYPRGI60PEKQyx5jq2bzOnA0CwQQGUia98fA4awUOOz5EyXse8yLDYeAAACxxBmgCALBX4lC069XMZi8WM7H11WL%2F9cvrFXVzxPpUq7%2Bt%2F%2F8d7V%2FCPjlrz%2F%2F9XxGFFAur8Nfq2X%2F%2F6v9YsZk6Rfil83jvq7zeFvBEr%2BGFT%2BIx3a9rF5vELroQCPhxmihMScxJBBh7Ur2QEdJAbgADevIWBbMbsv8VXRZY7Fb11tqO1rHLfFKl65cFdXrHK8mdXPr2M0uxCkyI%2FE1mV31fHZciov3wjnpHLt%2Fl9%2FTVI0X%2FvG2Ybi4agJnqrZu%2Fkrw%2Ba%2FvuPFbej8d56bCBHs3WZnpLp8P0Yia4XPKXN2S%2BMHifauCYgAYHu6d%2F9f%2FZtjw4tx6sx2PsvPSxeKx0rbYSX32%2BxRPBvVvrX1d%2F6pqFf1r66xymxvFK8mEfrrxP1aqglzMaN57i%2BhUV9F76KkFcEMcLP711fFZyMVuXrVYR8I%2F%2BrMctroyv5cYt8Z3Pq1Yle8dQh8Vy8TdhvhpTP39Gc%2Bj1YpRW1hX2OV5c66octOubzq5itNCl8d9arrX11il%2Bteb6v9ZVwnMAAIdwo%2B0jdOX7eqBTu1BCbReTo2Qho2mvqSocorMD614lWPrX1Y1witdVehWlxKy7FK99Xx391WNfX%2Fm%2BqbFfja6uX0Xtuos2ODEUvraRCFpp%2BhNfRq1eFOVexCKmFI2QDv6vuV2FFvinQObBjT2F3ehlfSmnUzTr%2BKe6%2BZjzLX1r61jt5YpRW8X4muqdRRPi1TPpeocvtzanBXWvN%2FGOkVMZ3xT4xYxSR24co3UTwqZtp%2FqFOXOMNO%2B1ZXZx2I9Zf23TClwhTp%2FiQWRkZEcRgUoKLcvgMf01HuHmIkfUvKB9BsZf%2FUIUoyXUwt8i2FmwJW9sv%2BnYI%2B3JLL%2BT4U45lUUeSZFNHGCdUNC5IZuoC%2FhAO5IgTdPVsuJE1RqWE6pPx%2FDLHBR%2FV3lR2kZvrWOX0nWvMr%2BJ8Sr475VH%2BF9il6XtexS0X5%2F7zK%2Fda34uXNof8cmnxYMHywJW%2F9N%2BLzxg1%2BX%2FbwnRq2uM1rHx1CkS0aREv2jCuLPvpji7bQUWy6BLH5FyCmgnX22m1w8e01iJuPcxVoxaYKrDlpFeIJC8KWQamkP%2BPUW1kDfsLXhmgZ8zFeZ30xE1b3enXxkdr2I7m%2FKhLnAj0zTgOwhf6BUOicFFOJ6gr3c2XhPr%2F8%2FpWPKyNz4RgmP3PFefUzKu6RX7WxCB%2Bla3JE%2Bhi2ircP1b7yOsGXuhrH46%2BMC7yI3ylolRHNNePr9erHifrXi8VpRW%2BxH16h3M3CX6t5qyeleuvV0XveX53dSkhWYn2K8VYRi6SghDAgNX1D2gHGCfyhiMLJ9TlJmWCNEqz6TYQPLOzkNCvGoE6boFsi6wbamED%2FjeEt%2FsEnyspJUFmZ%2F8YD%2BPmYVpjF6yatmagyNEKScfuX4I%2BbOTDpAhvewl%2F1cIy6zIRM6k%2BztQjnlOKJsPR5oaSBhHcRSw%2FCz4O6b3oPxIZyl9aXqCV6xAlBveQ%2FXQT8QHWtbN9uSCiHZUQEyrLJ3p3%2FoUrCcHJBR2MGvTXNCwt3fCVX4zHdU%2FkxLUfoLJZ3%2FDTNEO79QVSL4tNx7EVPsjLTTPIvGD%2B%2Fi1i4U%2FxSuuuGKVYolr1wl2rumuvL5Smd%2FvX7ugwcVjscNA5REQ7KOHXhzTmNriXDc4hd%2F4%2FjOSjw4rUtRk%2ByoUfpPEFW5whZnXn67Gc1R2Hrh1ADmKhlIjlZM1S4EvplWDduv19Jft2lGktsMQgbZUEzWpcO9mM6D8rzklYkCKNffjqCoQwP6gn5vNV9W%2BCIpP2y%2F7dgnJ8dOFy5uzt8RD2dKPfDQZb%2FghomggexoDTqtQVQQvNc8f8lTp6m00daddjdswdseRzZi8De%2BShrd42anpt8uoEzTp6CsKGN8o8tvFPicHYOyp1uIr6bHJWvBLeMr0cZaBSj65dwS5bGallDUZipx1v60Xq7zK1CusyufXKowLcP1fhky5VFVqtq1T7L%2F1jeB79wR%2Bu7cICLlTr4KggAlIiCYDHkU3hTnWxd5lUsuAMhz%2FCFfE4I%2BV9%2Bg%2F9fh2IGkGo%2FxtIgIAyWmEbeBYr6VrPnxCNN87R9vlQg4mmOEP%2Frw7xFykhffdbe%2FxuBjPjWv1clIYkBDLkz1%2BbDszDHqGp8v9PhLn9kDZ9NLJd4IBsOlwQ3isVxtvYJPHC%2FZsqIi98yEvBHyYHYaIRmSReHIPs3i%2FsMYyrsTyYZjHvet4nxfnqFP1fHZclyVv5sUtDltbUnTJiuqqv4%2FezOJeQYMDPyjB90OX%2FvDsETWCfdAW8cnZsKm%2BGX3uSX46q5V7C%2Fyx7L6L9pdgoJWbMVgm7NTM9jp%2FYxIiA01UcTNhpiGkEJ%2FrLEampF9Vu2wSSZvj%2BCYu2nu6VeCUghJAR%2FUqG5tl%2FYvKvFFsh3wn%2BPjqwpLH9i1x05PtcaJaq3dKlpZ7xfYR9arvccSpTHYyAy7vgD5Z5f97BRppjI5VXxZf%2FUJQlXJdOPtXkv4vYG5LAx2J0pCBAbvIrCekCDS%2Bv4b9R78%2BW4%2Bevz7P4Ez26f6HK76eey%2F%2F%2FWr61WltVQUee3fxnwSGu%2FMVyCXfXMaU2UycjPlKDcS5UVsmi%2F%2FmuKz1%2FCVz7tV6SL27woRpVs58KCsfN3pESGLfZZ3EEGBbRdgnJPpHpuQzHuy%2F3pdQufGmTCEUcTo2cdH%2Bvl5xdmwV8I0cJ2DxB9ZrrmXAEfdwVa6ZSMv3fQKDQ%2BPMIWEjyO2lsvr%2BCc4d8s98IvPJ6Y%2BFbMISR5IawfwK5J5ff9E6NWonSvm%2Bor1%2BvBFNxJp4clyGl6ysF3dwxqIt3%2BI0lD49mLov6%2BaTDU0%2F34SK0mIjDLm393hihkI62OyqJ%2BBQcitiMCic7vCEGp87HguI4ZMZZnDgsxjz7L9eozgxvLdzRUTnxLAgfI%2Bv9vmAvF4ZNyBYlOuBKva4Ucy%2FdN4LCzhQyRwYvGZW%2FPTz4glkuU8YWdUhen4iYiWhKjBx1kV%2FtC3R4JcSS%2Fz0TR8fjh5x4Jp4c0ef98EZWBUEKryuid9eqEPPror0K%2Fr9XkVfwpQ5UKmNvhMz%2BqwxzJYAARjetIAdh4fj4wWD%2BYfBW%2BYPS1NjAjhzVUIiuv5f%2FLBbGwcEjbHeJleMTYMTpre4drWXDQWcxLAMC902le6jNQpM%3D&media_id=1254206535166763008&segment_index=2" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:31:55 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:31:55 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_88U7rKO142Yu9lpXA3dvDQ==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:55 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786111596910130; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:55 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "2d61f65deb660b6f9e5e929bca5f938b", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19950", - "x-rate-limit-reset": "1587864356", - "x-response-time": "29", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "00f384e80016b72d", - "x-tsa-request-body-time": "97", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"bwZdhRo4krHJwyv9210UsR9Fb4c%3D\"", - "Expect": null - }, - "body": "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wn4eqeXIPRVXoysocf966eztTqjmKTf3VJb833nlfKvxvMPwvHecowjEnQfkz0vnVAJ%2Fo4V1ooz8Ga7HokH%2FilfsDdnmGv4oH7Y30pjacOW%2BV%2B3vrk6nPtEVRwVwtHN3D9Ckxqutrn6JZy3bte%2F44dPaIO95hjQ5c0BEW3wJid%2Fk5eUXUh8kVK5VNHwLSZLa5118GctUQYqZK5LWlBjT3Urt%2BIt%2BmOoOABJBSQzCQLEgLBgKBYSBYaBYKDYKDYKBUJEETfG7pulQy4qWVdKlUkRI0P%2B%2FXGpfhug%2BbX7uy%2F%2Fz3fmft48R42yV0%2BGk2gwo5J4%2FovVHQ%2Fea5n%2B%2FeAXjy8W4N%2B54c4EhapT37KHBmWlE3UHWyfQPJuv9xmo1CJgw6%2B1cUKztdde%2Bkq87X4byBNW%2ByaoHziRXVGYDodC4tZnZun5TxP3FexcX3v3gbr3YfhuC9nw35KBmIqzS89gFRFu1zy%2B5zFdt3auqy1cKp87d%2BqIAFVMGVwumAcqUPyqSO3SlZBioVRrVXh3yA4ASYUkOzUEwnCwUCoUCwXCoWEoUCQhG8%2BpHd5eVMgtNVzwqVV7ksrVcDi%2Fc6R1jrr0%2F%2BteGtr%2F1d940dlnGrTo4X8ccZVwz8aNdFyn1azp6116uU1a95dOhWEKLjX%2F7l%2Bzf4DSjBzX0eXPSwV5jwmnR4vPpQvbRWTo%2B0DBxbqhGwYR%2FONdCZXflhMxgct5dL%2FwsjOcAJRuCyeTRFuzT01UPX1Ma0a5d8%2FLVxfhxGPKYADQMiWL%2FoiTzKhECNOvO%2BgQchs%2BequMV%2BM0KPF7ZWVYWL7VmZKs%2Bw61sRen15Ytil99ZVWkwZYg4ABJhSMKBYKBUKCYUCQLBgLBQLBgLCQLDQLCQKhYShQKiEphSpVZLzetgmqKl1SVS7VKvgf4t03Fx18vlH49%2B7SqepzZSBf4LaMd3iBbecQ1Pk7v%2BR9r7Z8ghRzH74wuWnDcPQa4bQuk2QaZnbisWF71OYpsfbPgcEVnD7Ena%2BjsqJyYbXRB0HaJuBhQ6qLXgzoukfQ79cFSs580GFDSiCK1OqYkpOdAZIB1pQJ8OmnZw5Rrr2c3o6HDnBCggH4P%2FZBKeWu77eHYBn35g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" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:31:56 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:31:56 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_ym+XMOREfW7lUyL9cNn5Lw==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:56 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786111637858926; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:56 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "52661200a02716e08b016e8b92bbd104", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19949", - "x-rate-limit-reset": "1587864356", - "x-response-time": "33", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "00774e2e006bde3f", - "x-tsa-request-body-time": "61", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"fHQi2UNYdgEsY5rA%2F7OeMFPv0II%3D\"", - "Expect": null - }, - "body": "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eAttUd3s%2F806wSfOVKzUIo5mD%2BYg1vTQbX018apAs87GMtsEXOqR%2BdwQMk6nWVywtV6UsAFrOe5r15dWsz8nTXe4CyIfxzJg9Wwrf5G%2FZOPTZI4rZ1qtzMYKa9E1cYiEEZiSYZqjs8%2F%2F4A4BFpn%2BDSbOSJlykiqmtBh19iUSimJl9cSY74Azb%2FNcgAnukhknObdoPKmYxhyVU0TIkLHuOX0fGm81%2F8rmu%2B3t8tXTwp0%2BWmLmOj8l1sw4e6fupmGcGoonhUtRIlgZvKu9P9Vc24t3soNQFl9M1dzANV0i07rqfJZBzle0WktISvVS1BDJE9SzZ24bnamxpxIjhapCmC2WX8FRkYaBTG5uY0%2BmZeZqtMmNBVXl5IuJaOzrZ14tyM8JiY2UTnhvuHBy1kuedcr1EQX04UUWowvZx9S7MfSbHCuamgyLs9HtKFqH9WOogR7h0PGa43eA4AEi1JCslBsJQoIgoMhIJQoJRCEgiEwiEwtZzU8Vn39ccxaquVdZcoVU4o04Hi7V%2Fp5roJNqfCr%2Bf47OvLAfM%2F0CZqF3%2F9v8o0f%2FD5T%2FZ%2F%2FP%2B395xxek6JoXDubnw9HQcz9ZMlqst5XVN%2BGuQJuW%2Fb9HeL429hHMerw%2BB0T03uT8CE2L%2F3%2Byx%2Bs3QqqCsxk1W66ygC0s5xmuble%2B5R6fX9U15tfWdB917A31vOBi7vIuzXL7s%2Ft3KIwDSfwnYjbNlWWuhomZEQGmLso79h9tqJXZV9lVzF6UBwEgFJQoJgoJmIFQsVBKFBMFQsFQkEQkEwkEROa45nN7te11Kq6nHaXFVRqVdTQdmp%2F0nFdQfLLumvXu1L2yT8NM3aKCPb%2FEmntfKb6Dhqa2L30zWTPzv0L%2BP%2Br79f%2FJm0evvmMN7T0C9w%2BgiO4Bx3%2FUCG6UtLaMSlZcHHpaAX%2B4kDNF9g7GTGiKtc538a86SQrnd6jrgtwoX1J04oL9dbkZgKH9Z6Ei99H7kV9%2Fdz8Rrq2sAXTQrMyAB54dnTPHWzyTQduVc6z%2Bn5Ya9GkU0xFvOkWjCSXi7FLAsn2Zlp5GOctEPADgASIUkEwUIw0CzkGQXCgWGgSEIVCImarJmJkUiYXN2tmuZM4pdV0O71U2797r3SP9Go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" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:31:56 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:31:56 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_I9quZtwyjvi7QmIAdNIoZA==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:56 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786111683115618; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:56 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "1b8ffb9cd61bec2529599abe8a434732", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19948", - "x-rate-limit-reset": "1587864356", - "x-response-time": "40", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "00a1c7e7007f92ae", - "x-tsa-request-body-time": "95", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"K0VtQ5SH2exY0WtSVz%2BaZ4zgl%2FU%3D\"", - "Expect": null - }, - "body": "command=APPEND&media_data=lrH3v0DPfVdMOPMLGsE2%2FCYtZt%2FQjaektMBPKBsGUTHBnVdEz3OyN8xmBgk2tOVJOTbZguTRWbifU0At1%2BhmqVHdekG%2F6tjTfCVfFfr25WU8LgafsM1Ovw46zwu9kfxsvkRuA4mbYAONdlRefAro3NzXHpSXH2omUxhwFxv7ujA670qOljqJDqYyfNXFQ9uWhkdVm6ecHAEiFJQoFhIFgoNhIFkKFhoFgoFgqJBKFwkMQkERM59vXHMvlrMLy5KK4qlKSLpeg7dlXgnL%2Fz1H9G%2Bf%2F9beX%2FU4UGNCa61pn8yy%2Bx67vw2qyaTYU3H1rLmIRd%2BNkvFBqFnmj5197qd1EqmPJaVrp8YWwnR69u%2FalO647v7aLSYyETDmo%2BfEeETTXctywZwJoHCSNld%2FWc%2FomUS90O67VmpxJefIPpW5v0HP32v2%2BsfzQisk%2Bq95F%2FPttpQrb2egudbzDsFWE%2BpfOLuqSlYSldMrvqD7fS%2BJmmGMbYart8fdOKsNnlgDgAEgFJAmFDM1QsFEMFBkMRGFvet68ed7lt1Nbl5xWIRSpIXXQ8T9f903T%2FLor4lpuXbqun8LZeEk618Wsn8k5bOlm%2FhmGnvpizTniKbwlbeXnebqWQ2h%2Btdf81%2B9GdgQ8uBTn80IfZvtvk6zAD2X3j%2BgfbtX2DhYnys7eXEpifwUD3ahkzj3bETfOWz25QL5m%2BdT2PH3WuetQMCVPUBLFb9EpP7njqkbQx%2BCK8Kz%2Bz6FaNK%2FiUl1ytallGlaUdw3Emt7QsqlDBnWS5HpVvyWpKDZVlb%2F64HAASAUkEoUIYUCxEDAWIgWCgWEhFOQhCQRE71zKOU1jKScbtVS6vFSSkTgdG37oaa0f%2Fl%2FTfw%2F693ifVRX3A%2FEuzjN%2B4%2FteItEvP390sHq%2Fdafs9uLS0Udbw6bl66hh7t%2B8%2B0sFyraoaeutxWRIxH9f16Em7dGAWfmlMsv8PAikK7ng5AkkNkJVHUt5RhUdisz6YecGoRdDhzc4Oiuc5thx6JX2Pr7%2Bz2o5cmIHdzXPoi85iLa5EV7i5aqbi9WoRrF2k746mbWGE81d7tKEhA5FIa2OWJlT63wA4ABHBSUKHMK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vAQ7q3nfH8th4eGrxqwPWofo%2FQkRSVXfbncSvUFtuYFKER44rI7TJOe%2Fe2htfmNUDgEeFJBsFCMFAsFAsNAsJAsJDKFgoFQoJgoEhIFQkEwuZuVNermucSU1VQlXhkayLrgcS4p8y6JzHRX5XV3fR%2FWNci24%2F%2FWWrgVnYGrvxTD6p%2Bt%2F0uTYF1q8n3v6h9J8airIa02WG37Up%2ByBPifLwLD%2BFsBDaaxLHU5vjOrSo3zn9Gib%2FNsXN6x3Ru6mOA4ekUobTkzVqDJQj1sO2UV18WqlZlFZecN9nqvICV%2B1%2BF8sz2P5lHqzit%2BKHh7hRmr1oByCB%2B1qmGJSn6OHlTJikZpNQS1CnC7CluGIbZXyt7E1WeihaqQH1QigGwb7xgcBGhSULBQKiQbMQbBQjCQLBQShQJEEL11723qhKqrqRV1UmJWSuJUVwHhJz6C9jw%2FR%2FMdaL63%2B%2FyHKbIbd3QK5NWwXztLjfr1ZL4kLy4AXfrmGxpN1qikJedeHqHuPstmhv7XuUbaVOAReevjYHlyUrsO1P%2FkZkfy85%2B8S1WNJ8UtzISAATMPLB9sVFC8EvAKkWgQHx0%2F3%2Fs1ypnZ8e%2F%2FkQC317CSiSJznX6z8uAzHTafj5t8eEewrLt%2BvmnX2%2F04IqW6aa1ovNm1tPe9YT8xWWHaYpk4saSDuSkmlF2ZMxBniyagcASgUkGwTCgjCw0Cx0EwVChmCgWGoSC4RIbvOua13xhiayVJSVMmUk4pGh4fzz6%2FoH81qv8n%2FiHSmte6KUX8JmHy5K3h11ZB2yzLcpatRT21tUte0l0CF8mAtCdZtsQ3pY3Vxd%2BdglG%2B%2FndOqDth6Tpx89aIwhCuKDCXE9CwW%2B2bmhcDfT%2FblUf2qapGNFpMKwC7dzazdB72yiv6VyqA5K2n6GdVjt2ZCS23IZEXZKo%2Bb5BvuYx2ByyKtpwnj8%2FMsz4hToTrB7O%2F08TVF2u4m74HSOpWl9uiJDHH9EIHw8G4HASgUkCoUQwUCxECwkCwUQoUEwlCIXCQRCQTCvtKVrvitkuqmtyEqqqrzUvJOh2%2Fe1d%2BN01q78r%2B2%2FF%2FJOS5hz35fRhbtk1%2BZPRqlCj34n%2F%2BMgSlfCbTZZTxjtPq3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" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:31:57 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:31:57 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_tSNJ2BX9jZT8jZQB84ROfA==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:57 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786111730493788; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:57 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "2845491e1c0bad46dde60b8f2ad21e38", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19947", - "x-rate-limit-reset": "1587864356", - "x-response-time": "38", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "00df20bd0058afe5", - "x-tsa-request-body-time": "103", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"9zgT%2Bx3Lr2il7LK6kPQJLklIRAY%3D\"", - "Expect": null - }, - "body": "command=APPEND&media_data=rn9ffrVXV63X9WRN%2Fq6rVyhS369JVQjrlu9W7K%2B785F%2BPf69aq6vtTJPfav1K5XrX69Xq92tSevRF%2FnqYYu%2FxHSt0TdrnVWsU3q8nrSrurRHaEP%2BjyltaiZ0VkVauS%2BrV6mT5v1Y%2FN0Rkvy7Tf6t%2BuUTasVxU9rcq8QveO8Ut9l82PyEYmKZFJeIv1lXq9jvFfLFcvzd479%2Bvfm3Ip17KMlL0la9%2BrD6wSYZ3Ldr0nq8nrFfq9DHcqd914J9JrSaTIn4IaCN9%2FzaZwwGF9SIoPwl4yJBm973w1SndWsu%2B%2FPUf%2F%2Fz32sXNRPrVXXlsE9D%2BDCY41kSx02wLvoBpDrg3debDLv7krf5SZvy%2Fotfhmyrf58Zt%2FhzJ%2BroBk39Xfq9wj%2BsUg79dq5L5CS5rycMWT7q%2F0d%2B%2B3JiNgaRbl3RMq4u4urifLh2JQsI%2FCFAKX0OYMCUEAmQ4P82Y%2FDcmFeX6%2F7%2Bu5vPX7A4dp79U9CurWu5L%2FVqzYjwmTl54d2XJDPYqwpPTp%2FnFs%2Bwo6%2B2H%2FlEUG6ZPXu16P1LqXdeiua6yEjhslt3V%2FlPVZi%2Fv7I7Xv9YvxBONGOJRE9%2BvpfBEWr%2Bm8RPiC7yr77qxW8dQWse7feItsrjFvPZsTgb78mecYP935bCNP3491fKuVWsvEe5bJbd79WK8mwOMxfgjlNaxdm0Zr3fd33%2BCQqyqXuPlI85lP4JuWuRIz6qzea99lh87xu%2F6lB%2BidV99xHoXcmsQYo1j1NvvwRlu934IY9p%2BLtEqrJz0q78JeR8cHn5PP%2FegE6mv9Hufq52hGpLivRdV64d9%2FrK%2FZMnnuIv9H6x2KMiSX3RPX%2Fr0Sqv9XG68hYe1r7r11frl%2BtS%2BjMV61Lk16LUlrWTx%2F6tFa%2FXL6Vr9R2kuS%2B6v9Ea4AEiFJgoVgoJkopQoJgoFQoEhCR4q7y850Mkpl2UhUxWkhOAW%2FUHxTWug%2BEPX%2FF%2BI1aqg23V8Dgx%2FVNX%2Fxey9dpppt9crWSfLSMpf7fjGqPgv3kdB8P2jUtvyYLCfvRxQam%2Bd%2BTV5os%2FB9sLVfCAOwrgdvbmksh7k%2FNnHajt1mndK%2FY9%2FCarI8XDf8pf9gvXx3caVLbwsL3VrXtpvvosRPHg%2F7gO38i6NN%2BZ%2F3Ywn2r%2BMO2D5v6lMQcQ6lgNsswPUrxBhW21PmjhSrqR%2FxPOuhzbY0Qj7IcAcAEiFJBKFAmFQmFBMdAsJDGFDMJAiEgiEgiJfvJfPWbqVV1KrUyF0qZSSIcDk3RfS3j%2FC7fz35vwH6qz%2FlLdS0hdj2VavhNqlS3NNUcD%2FT8Pv5XlC%2FI7OxQTrezsOfFPugZt1bmcnGroFV7dXkVtRCsfH%2F5h838PA4OENV6J6%2FzRIZFdW3%2B6PYUmvpB%2FHYBj8Y%2BVc0vOoITgyXbf%2BsOT%2Fmv7wmzxeqGpIaYw1vLfYkJYy0FLpmFwPERD2kcBA2L1KVjPjXJd1KuwJVv7zeD2eogRCkgSo7hTvmn8tIOAARwUkCoUIoWCgWCgWFA2IgVCg2CgSCgVCgmCgSGYRG7rLxMmRuwuVUlUlTF2q6mhpfwbbpL9L%2BPfF9%2F7Z9W9fXo4ViXc5Ha4CxDFqW%2B%2Bp9uNndjd6gZEnZflLrvnNA5YFLb%2BR2878obV3XR98N%2Ft9xxSuZRjRAmvWY95IHnCOuwQ565sVb%2BGFbaU%2Bk%2Fnm0YbvEOPYfVXXSzKSpPHp7jnvfhfu8%2FIFRUd%2FoPhfbQYQ4leti%2FUVf2rCC0L%2Be9B1oy21JgVesiXWH7FoN51ZKew4tPXepVCW5sGvB4PCDgBKFSIKhQjCQLBQLBQMBYSBYSDUKCUKHUQlMLjvXO7mJU5laVcKqVMlKmpS5ofrk4PbOS8ZPnvfk6eXmnQaxLbJ8peleuPKC893Z9TPfuyu25qV0B2CP85PgqL4t1HXiqGHNSO%2Fi0SC3gbo6Ult8Ya8Oe1L7perAi9M5mxPT7iSBBy2fsQvnJbkO92MwaGNGn%2FIIPf7wYA%2B2uQ%2FZfOer%2F2uHb24IYAuMeOg%2B%2Bba7%2BvlLXTRTfj%2BiGd0sN0hKneqm505UVpC0nROxP1zqnf6CF9vnE4g4ABHJn9jEaOSJlvJdMTXQKYdx126n78bVmvmZPSQdvS8L0JUNCml%2Bs6b5hBdXnpIymlVdtPiBK7cVKGYWylGEgTcJuMYZ0EwuCDvozpd5CcZ5Sd0aUIkklbtqYfjhhwznmfxyqlcZGtWax3YLZak2R6sJnYpYmYUs6Lbr%2F3ggUFhEzAkAfLvn11yzdmfAJlSWLcpqIOTAlgKWxZpisnqbGtELwXPLCe6q%2FA7vb24XbearVtzKTgHIxxYY6k7R4XA0FPVaOvgei2cpMv3L81KpuWtKDFzv7IaC69GQXwHL9wYjYwkBvsRuBgxHABHNSUJBUKEULBULGQLBQahYKFYKCgLCUIme9OM13JzN5xzo1RkKlErSI4D4%2Fl2%2BPyzaeJepzq4h3FcIjuaX13454aSo4lTS%2Fd937Ws%2BJpT%2BHt%2BBUPus5yt%2FhmvXxdCw0ITz2wDfpvtuxyowIb%2FT4h3Afkurm%2BZJdLKb4Qz3feNLap6IEASiUDM8O7TLw26Ud8dLx%2F%2BmgvK%2FbufRE0WJySXCRMNGbC5YDZtAHLcTBeAy400btWbUgxNqG0VEAxH1%2BqLmSIKwtaFKN2TbvuRjemdCNhsiauJTspJLdcHAEkFIgoZQoFhIGAsZEMFCKFguEgiVlXKzmtUzNVdOt0EZFGpUTgbNg4fX3hcBr75vxccuVQTdfturgLW%2F%2Fk7PC7oTL9JE4o2d3WAgxUnoq7Dd6Fbj%2Fufs0YV6d3%2Ft3UjdHG%2FJQPw17Q4LvUSLQd8%2FdhL2%2B%2F%2FKJQQkQk4naWvLf%2Fqyhk3TNZ%2B5%2FVlFOC5kunMM6ANZv%2BY9biWqOm5L4PBx9qZnqceeV4vqpsEB8kgEMCYV5taRIHHgHvQYlFCydFKSgj2spHyIUxo41kS2TVcHAAAAIqQZoKAooFfdehLAvSvJ6vXrU1r1evX6uV65TbE%2FMrH6ufEV0vTerp%2FWu5fV3d2rV69iu4FGtVg7%2FWLvHLOl%2BvS%2BvpBy%2BrwSFG2d%2FX7JyYS69WumocT6uJXr9ZdE9X6%2Bq6u7jxX7VLjf5qnvirg45fXu16vXX693FXL69JD8l9r1evT%2Bvaojn9ZjvuvV%2F1qJ354mi79Wv1YxXL6LFXghMtu5FUTdz%2BtRVrqXyTkjU1f6sriJe4%2B5PXC7r3zW79aiN7558J%2FdFqvXq9cq8ENxucwDqvRJfspd69cvzZUSNyVXXq%2F6y%2FRHm57nnJ8hT9xFz%2BvT81%2FV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a0QsT1Jblf%2BX5o66ZtUJrQqOFXuvwK5in4eDL7thUtn%2BxcDZl7EIStQraqTV%2BIWcLrgrTbu4eUXHf0dXWZ%2BzhtfMV0Qs2gp9fQqKycLWffut3Iwn7p57Pze6cbFMEi8YWlzncHABGpn%2BG3CEy2iKS9AlE2%2BmLAUhZpgHIBrk1zqbF3g%2FRDwnBYJL1LJgRcdZ51SzqLWvl1lwE883Zq8PtTb2R359OHKGfpX3Scj6Y4a96nWVk27grYTl65CBgxhcZiwXn2sHkyoaaqpwJGoQ4ofjqGdMWhyzpx7JUg7q7xksg8mO%2Buuq%2FBXCc711V2jdYRhjSxCjH2jTwRUZdvEqcwy2AKTvKg30S3JlbSvRB80gGgrCmY6CEBDUkO4ASuiVVXBBXhYCPbRWJhlnEuOlEnwaDLA9Lnh10RZ79E1N2Y4xyR7H3TrqnzNTlRM44AEsmf5NGCySKRJli%2BJVVNcDHXcSu2x8e9tnujsllPjbnDKvGNXCciPQkmIQ255fgN9rAQR2SbN%2FTpABVdkhzsFmrXhN%2FsxGMBOxhqB2XEz%2FTs%2BiiwQREz5x3wOZ1MxXpxe8hPjtPt4XiIf7YszSzN3sVFLTNO0iU2sDTxrWs0ImCSHfMckwP52HdcEaNGxurhmMraYhFTmy0jbs2I6VsIgVuEkPVxy55RpwKiN2uF59QICg3Q5tD2NCwyDgASjUiGoSCgWEgVCwYCwkCwkCwlCRRCoRCYRGYhMqbqd%2BvM3hMu6nmZKL2ZIkup0O%2Fhn5PTktfy%2F0t3dxU%2Fm148Gy219%2FX5uuJv0WnX7Vy0Tzje2LUsOEn%2FWNjXg%2Fa2cPUVt1rKL9suDIozVINE0KERxSozDKk%2BxRaK%2B7Tt5ttv8wZqR0J1rC0sWxFlswFMF7Hvoe0SPN9yv1EKSFZ1T3BW5yEE7VCwsj9wHAASYUlCQUCoUCQYEwSCwkCxEDAiEoiEIiCoRCQVCYRMYXetd7evqeKyay5zflFVKMXS5S%2Bg5%2Bm5OHjaTcnlv9B0VvoZ6Nxfy%2FGpLvCPKkSNInZunarHrNFuTM1oarMOUEkzp3Oo7d%2FDCViGSeNS5YMUvkdaDls3OkkebHoOlxWtQdg3cCbi6pDPM3UFzSyKcQ4hmuPEUo%2BjcNkpXtof13KxVQVXup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meF7ESx4G46hMeLx1uK8isCYG8uahka9zFUaA%3D&media_id=1254206535166763008&segment_index=6" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:31:57 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:31:57 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_ldBTpjgQQFLXxpCDfCzkMg==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:57 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786111774319906; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:57 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "48ed625ed57b85182e807dbea12e4adf", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19946", - "x-rate-limit-reset": "1587864356", - "x-response-time": "32", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "00f5e18a003a9e26", - "x-tsa-request-body-time": "64", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"UKX0%2Bt4s7ucajEBXS0etQVngOuQ%3D\"", - "Expect": null - }, - "body": "command=APPEND&media_data=gNiS0WVb9IgxoDmQGpCuuonUVCmrM6%2Bi0TjX8OFuc%2FzjqVrE4ViqmQRASRDy%2Fj9Ebj%2Fzx5eHdHKfh2ku1TFdwvrX24MrS4W37ae6pcs2%2BIuNBW4mfKBkG2J0wnABINSQJBQJCQLBgLBQLEgKDYKhQShQJFEJhEJhIInfPGq7v9vxjNzOsu%2BfJlXKG%2BM1SJ5HibvG%2BWvWXXzwZv27ugL%2BkWKo4Hdt8Lkk7bHviBooD8TiWPYgBNSDa%2FZ9Eobbi1yABovHleqmQTZNQ9W%2Bc%2FcMCFR9hlzKJL6gczffP7VH9Dj5YlLl2zaPH%2F%2BW7Fnf9okJe92FMwXU9eO%2BGVC%2F8CkedJij8bgzEJzI3zhUsrZ04gcBJhSQRBQbBgKEYKBcLBUKCYKEIRhIShQShFDK1WT8%2B1VWGiri6zUyl5dXUq66HIuo6%2FG3PidPuwZ%2FGuO606rUXjDnPp%2FU9T%2Bv6qgbhp75%2BTetlwA631X9VCpBRq7fJ4xmHnlmPl%2FYpoX7JH%2BwyR9Bg1Pm6nhelJHeVWz9qrnWYOHDuK01B3FORcv6jinqW%2BJTLwLorWz3ToC8H3lnV5FcIy1IKfugX4U3JxlIrgCcoiGpS3UDgAEsFJREFQkJQuGAqFBMKAoNguFCEFQiMgmEgqEwidxz1vnfj9e6vmV141rnrIzjLyVlolScB3dDU47uT0v7dfee3%2FNsCLhFDZ6qq%2BaaUpz%2FFfumiA5B0nXKxxR6O2090D%2BSjbGeG%2Fp0Js%2FezludSN1jNmoEOClpWl1ttjjJw48COPLOIWm7gmDj2k9bw%2ByoUJ6zDlR8lCzmB7j28iKa2WVEk5KYB3StBFE5kyl0ZUJrNAOAASgUlCgiCoSCwYCgmCgWGoUG4VCYSCoUCIiCYRCoTCoTCJ05vPbx%2BfvVZVWq6cZFWlTBcpGg7t43rg6eF%2FNPzvleqSfSO5Gbyo62T8LvphXx43%2BhG%2FCulPSeT%2BL9Rsxo6znV29P%2F39dxc9jrXZXYy1PW9WOFuy7WY%2BmKBJMC6CinovNUvfqhhiknAJvZz1cE6w98rJ16LTRiiE2gt7MvaV7IOC8c9zsw5A2E52lG%2FALky6%2BioOABJhSU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PWXly2rO%2B5fWoi5%2FRHX6xX6K5XzUkRctqyrRUaod8Rcvrzd%2Fo0U19xlwn69JdevSXGU1Wjt33etXP6Iz9av1cFuMua5i%2F%2Bsl916y%2FWoz1yrzDLx1SXT4%2Bv0EYJL7%2FWpfMRndonq81%2Fq8Rdeit8I16xT0k3qYsv%2FXP0tXzdq8kAEoFJQoFQkFAkFgwFgkFgoFhINhIJgoIhIFQmRRCcKyfnz57ZWqKvjvVUky4SrqVOg7tic%2B3YuandD55cOkS0Kd0HC8S9usC0qn1p83%2FOQhSflRCWrXzj%2BjuL7nK%2BdhaKHtChbxzZLt8zLxjgfZ1rK6Hb7RjnqPLyuTm6o3UCfId3rP3YF3sVc3Jnb3fq4jf5jGddiaQuyg%2Bm6v2qFglWf5AkFWvamtKcKKymnyUIWhOAsnUzRqDgEkFJAqFAqEgqFAwFBsNAwFhIFQoFgqFhKNAmFRIFQiduKz2%2Fr9N1UVKjjmKl5Vrq6gljizl0PkzOnwtTg7blvEeWLRG1qdM2HoAeMfjzJg1c3C9iT9%2F1TEXwH719%2FkOarujqjrk5oSUq2vr9yETXwFraUJtgqU1VmKwb7OER7E4KtV8vO4Kb4c%2FVmb%2BQM9fPe37xTyeUbPf%2BtZZdYvWtCXb7FiyY6oo267XBgfy%2FHbZJYO6czPVbWqH4rz2qwXYInC8JmlDCURknj5WBwBIhSQihIKBgSCYaBcKBYKBUSBYKDMKnE7tdz39%2FqepVSStLqVuXkvL3xCVfA7fYOPbQ7uvmG%2Fm68nyNZ%2Fxjl3dU9vlGXu0U7B%2Bjre8vm%2FD%2B%2BmqJFp%2Fimvf3DEWeNfL%2FLyqkwETtyZXNo09Q4P0hfxov0%2BOtIlSedOb8Ygtw%2BUcea9nGnLjFu7tAvIe2MREV2sNDnz6OAXiRCg%2B2c3AA%2BPGvG%2Bn2kyErQmNisH6RpHWXmgtaX0mKo7dkwEV5p%2BRcHAASgUiCoSCoSCoUCwlCw4CwVCwZCgVE4UCoUCoTEojConCJ3Gbm5%2BnU5yEV%2BO9c5pJuXvjvzSovgdjpyc3g5%2FsJNWmV1Dyxt3Yc6c5vRUjhzFVXPor%2Ftgte%2Bn451xORKr5Hz5gHoatdvpQPAceDUql5pwt%2FLVKtPnrJzRIZLQfV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" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:31:58 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:31:58 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_zbsqJTPufqcUeLFfOaptlQ==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:58 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786111821321190; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:58 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "16f94ee08dd5ae5a6fb984f7430bb598", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19945", - "x-rate-limit-reset": "1587864356", - "x-response-time": "35", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "009b24530090c340", - "x-tsa-request-body-time": "96", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"TX0HvAttnyzrHY%2BkF6qYAc5Bxlw%3D\"", - "Expect": null - }, - "body": "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217u%2FWV0366%2FXphy3v176XV3k8Nf5ec5oJTRoNf%2FR%2BuiO%2BW9hBeqjNXz32sXakSpmWq2qvvu7MK3P%2Boult1n%2F6FvNct161XrXeK65q55NCpCeP68WYnDZC1xaPrvswyNoNB7cjNp16F1d%2Frl13si13%2BrHSTetV6tNdKJKRGODxJCkzYucceGM2d2Heemany8kCPuWjnKLxku7x7jBZr%2FU6iYNZoRQtmqQaJdEPHlaLV%2BrH69XJV0r%2B%2F1rxSifV%2F0WDiLjmC4zly1AQNzNb65iIZQy35Piq%2FnBDUXVT3W4He7%2BxIkKff0ZcSMkFRndM0IkcTJWENkLxZPT3zaOPtc4MJ7NWXXtIIbLJflpa6qUSBrBBOSHi5GhmLK5czkRGx6tfw3PXV2wtdkqDfGQ8u8H5EH5FRmXvM%2F3V%2BX2jxX6tJ6vNdQ%2Frc6BJqoIvJv7hZBJtVUX9coYztxEMbAdUsJe%2Bp8ngt%2BKIXNJBIL%2F9V41aoBwkO1%2BTw%2FsLeAy0zXYUEqE8A6p%2Fu5FMA6OgQiWO9zRJiC3e9Nik8P1DhLAoyJavjt38piUJgwnaGypfJ8y%2BYguhg9DyHvQ08VhiwaRySMNcaxivJW3DLNLjX7BKVshHl%2F3KFYQundB54U8PvzyCoc3bD%2F8VhkhS%2FVIDAsdufnq0eKT179cp8%2Fy0btot3SL%2FNG1qqqLqLhqGkCJg4l6%2BJURIozXPq4Xzk5Uv3Oogiqtft77DBaNRoidAQ8EDWwaTWsyrFGClXsPSkix8xiQEC3lSFEDBJ6NElcr%2BnTBKUE3njItRqyhVbvwZPL7tkWvehKUE%2BchqKIoHeQO9SzcnYdOfA2y1r%2FQH2XLt7GkQXdN7%2F7WW49QyZAeP%2BXymRln7FUK4VZVmrmA5AxcfVGmr7CsYJCeZvgMdfXUGZm43FhHr6sLeTwUrvDXaKXX4I9zO%2BwrwfEhYPGyFuPxAg%2FfZ85zr7xOD0%2F9cprWXxN%2BtXv3d7RRlCYqj23htFufsTAYp4N0sNbw9n0cS%2B5T2HMoYDGcK2UzKr%2FYIyvQIgrMMNgiFwO3OfXKHBDBjXkHrxvvr0jWc%2F1%2F1kituvXuvDnJY0q%2FkITbsNl6Y8M7fwifZzn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6WuEP1i%2FXVZNaRCGobPqItLJTJi%2FDlJLXz9vrSwW3dLauz8EXY3c36%2Fgi0i13MXrJVXoSVNzv32QcfIfl85cnxKDYoL5JBE9bwVSB0PfJih8eu9MAyMJaaFRKVyjPSPTyegm16q93fJJdetbenrdbrlPtSX3pLxQQ%2BBtH0LKaXgAEiFJBqFBwFgoFhoJhUFhOFgoFhIFREEQmFQmITve58e%2B%2Fe%2Bm8Sr581x61h5ko3cF1wNZ%2BLt%2FW2nyOWB6F%2BncJeSpEqdbt393x74z%2F9%2BZhx%2Bmzwunq6e6QZqV%2Bo4THl9r5wI4PJqjDry1NVKPp%2BP%2FY6iN7UmrsJZB3WI4NJqXaxd%2Fi%2FZ3HlfYA8pBXKMKJYgFJi5M6%2BOiS1odp497gCoLv24XuHh85avlnKI5aFOFl4aaJCtDjWE%2FVEElTJiqvCNhLXUHABKBSQpBYMBULBQTFoLCULBQLCQKhQJhEJhEJiE5nHLX9ddbq93W5c1zJTjVXjJAmh2vRNI9nqr%2BtqkaF93Kn6D8d0Lqq6OQj%2Bd1aT77it7dlW%2Fju%2ByiPIGHllW7uCtpuAxoz%2B5DdHwW4Nd2ar%2BZIS5pR3zGturE5iE3k2rVoJzPvanylr65A0HivBbVClPDq9%2FHaJV05JysbOt4yiup7NPqr3C9Zvd7PhNNK1iN7IyRukQmlPvtrUQi1sEl0qpCfDkBwBJhSQKhQShQKhgKCYKBYKBYdhYShYKCYKBMJBUIhMKhMQnZc3U%2FT65lZKZJqcyXmtVKFRDyO1fHUXRHV0J4eK9rX5urZ8tE%2FAbtw56t%2F%2B%2FZ4Gz2%2FChPP9u3k8DgwC2L0tmE8mS%2FXwNeoMh6p7J35uDA%2F0DzRm5dZsyyHamnjDh%2FSstS0zodi3v%2B4spGxjCqHWGIFdcL4oTH7mlS3c0ZKEWseUVdEuCngR0r%2FbNgyTtReZOfCWgKE5pY7WkrUmphhVCc0RO9pg4AEkFJgqJBwJiIFgwFg0JAsFQsVQoFRoFQmETiqy%2F0%2BOdVurqF3uUcawqSpUq%2BgfJ1u3Veo%2BLQcP9G%2FC0fSMb9cpa5P6P%2FQ%2FDHOsgWtfom67iUYHifmnIYaDj%2F5CPvNe9Cpozbn96DDdRvI3LFM4r6%2B2i6S0JZZY7MwABOTCeuApux50VVsnq6Y7eUjctpyrRm3toOvgU7IVS6p1LQirUxeNLTyKNLgf0NEmX8WzO4K7kL1fJpY2W7ZPCvVW%2BSylBTu39oOksZyJp2n7EibjwT6VBwEeFJAqFAqFBMGAsNAsWgoJwsVwqEwqEwqETEERPWqmT9OqTd5bNaZe41aqqXRI6Gm%2Fk8d1a21RP55XT5Ofm35ZXbb%2F8arunm%2FrDfdHZr8k3p2yDZot%2BTLHdoH918W41889RmJRrefdZZbuMI895mNxKNpSUvykOLJjCrvcwI7pI1ic4tA1fr46abnK69u5uJSJzRL3mh%2BRRuhfVEhHhFfk29pkhgNKdUcOJHu%2BMtyyq2Tjdxzal7n0McXedY1nmTsihCN50APG1NKJOEdIx3iDgAEaFJBMFBsGAqFiQFhQGgsJQoGAoGAoNQoIwqEgid73J3Xv5vuYvOu%2BJbe9LSsuQE6G58vHw0%2FxLfOvlJ%2F38xfrRjLNEdWvlX66hZPSW%2Fbz%2B3SvyyZkpvufqgyQjwqA5puGJNSkEHv57p6Mr%2FpQ4dCoKxqJ6U1bzP4yIw0z6qMESf%2Fy00GX4GvGwpd%2BemOJOgXnb5Dl7ORqdGj0VI%2FmFV8L2D39fYnPVt34xZGO4%2BU%2BWU45yTAoyWtozATBNksZKr9lWHnNQpWqkE%2B00rwvWV5MTcZHhBwBJBSQLBQZhYMBYKBYcBYVBsKBcKhQLCULBQShcKiYKBUJBEJhEaVTJ8%2FWZPGqa35MmSY1W7ziEqcD%2FQvLROgdj%2FNer86ne%2BS%2Fu3l%2By09Uvk9WHbhmZRw08OU%2FV%2BqF0SGl7L1YcMTgMc8z8Z572WNp4e8j%2FT%2Bl4k%2Fnc0N7qofU42Bc%2FCua%2F6c3KVoId8gXIiJhyiDXPH%2FTCf1D2vYY%2Bz1r28rrymYFdh3g1c98LnLCMXilvp79eve%2BT4sLit7l9t2m%2FFeo%2BYlBABbRQ1wvaw0AQvDnQWZx1dFLB0Ys6zmP12QnF0Tt9impKKy%2FKepakXLKflsA4AAACaVBmhYFigV1aFsX61XS10Z0%2Fff%2FS9Kuu%2B%2B7qWNl%2F71SInqx%2BrFer%2B6pOjqd%2Fayr1q%2FXr9Wx3Ld16sc%3D&media_id=1254206535166763008&segment_index=8" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:31:58 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:31:58 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_FelJyAlU56dp0V7GtBRVeA==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:58 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786111869441376; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:58 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "cd7c339ccf2dcd883bf193cf30b0dad2", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19944", - "x-rate-limit-reset": "1587864356", - "x-response-time": "30", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "002a6a06000236c5", - "x-tsa-request-body-time": "95", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"IXMSCyGS6DMDMyQmy0M4YAgrNr4%3D\"", - "Expect": null - }, - "body": "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4I%2FPBvzEj5x%2FwTlj4yXsWNRpM%2F%2FHefoT2MiR7H0ryG549XxUGwXyZMZ5%2B9coUICgkL6YqhAPJJ%2BaLV7BF1WX6GxS%2BvdosXclq1eid%2BImkYjnJFRb9XNv7EmwRmvdOfo71at%2Bii5KuX0OirXXPjyLHY%2Fb60T%2BMEBilRuO5D3j6BZQHgukfNM3%2Bh%2FXqrXUrdFTWisFk%2FrKvJSJHLxHzTWiZXNe2QIU7LeAAAAKeEGaFwXKBXLaFsivV%2B1ftYpPV3612r8XwIP6xe133xPX9df6%2Bd169Vq83rV0twf8B9CfyqW6N6YEheAheWM7WDIQGyhgIeNcOAxQVXQO5cF2Kf6V%2FiGvBkYXsG5ktHiXbI%2BS0NerVztWlv9bBy3fgwEq%2F6vLd4kehRQfgqkv4JXi898L%2BKgs0RF%2FnQYznCoKNBUFGhYdGjQHENmjmSRfYX%2Bg%2F4cQvLhxDZoBxHElsHBfNLA4CqElh5MkyjCOS4pEobafrCyZAQESUJupDvpTWDkgO80B1zQHXNALb2NtpvoyUe8T84F0g6Qq2ptFuX7sOsF8MWNkAepacxJvjtAflOJ2fvkq2wZuycf6Xw%2BcAi0FbBagYF4rBn8Yk80QgACYR7AgACAVjfCNULGXCS4NkvrhKBdZ4gCwiBccMJGzA6GvYOJkhh4t2oNi8MvaUMg9c9I%2B%2Fq5Jf69KK69Xk9cpOlbtcq9fFrv%2Bw0ILy9ReJ222238IIRV3aa%2BHEWA%2F%2F6eTUuvbb6ZNrFlCBApnVeVJQvku4epqKemvNOqwbAiY4aUXlVPa9ZknxBf1VIkAQFDg9Ytie2aKtu3gUQQgb2NysmjeR7Cq1kvF1q4HYgNzu9bffAe4qCVW8I9xU3%2BBLRb3uklwzQnuBXwktX%2Fwl8lez%2BWiVerq1dd2K%2F1cv1c4nJ7FoQ4S75pSCt376ql8J5c9CYpRy3r1iviLuq%2BdXJrVysM0d2XwkzyMTCgSAfu4LK%2BZirET6pEbeZTeSLErMKnLBM2BSVwLzFOFIPXBSnRZ%2B3zQiHyQjZMFgu1OJhQ8kwWBiwCXQF1uZIAEOUvPOWSz4xTFdNssf7%2BN39VB38nTVdWgjV9rVVRF%2Fr3uvSX78mjy8lEfL5LSQtgnCBwfimAliVUfMIP8lEOW9cTg7mPfvuxD3v6Hym6Vwr6Trr1gm9ak9XnWJI40RuKuBR0UCgSD6ZfcSBZXcPiXj47T2SqvrbjHfFFYGXEcO8OIbl6CEoLwwjLcNFV4388Eu4Y4MmQipNllZ%2BOYGYf%2BKviTot3qRjCQzo6xk4j2BgkG5n06bzVjHTgZUpbUpNIhN1KaZ%2BO2LYCAvV7e3cJehrJMmua7vkn9EMeZXmNjwID7PXDCJBo5%2B%2BwTysWpvlN4h9H1vyda4KjHpi%2FDSWsir%2BeQVrRRLC6p%2BWT79cR3ET5QZ6bSUHe8pt0SPYYu6MlA4zRxNMG6S%2FsFlg4T8UkUDfcZ8ymgZaG59iZiCwdhqF9GJUJhLPd3ivvtHe9Je3g414CEF0vhbWDAQGwgCgU73c3OYgoKHPs%2F4Ji4rckB0WiIvr6O5ZPL%2BjQHbiGakFT2CIkCslYbdxkED1bOJXzq48hdVZSuK3a%2BCckkLC46mXfjZxkfCFRQVrcgtupZMIKaTh984UMSUJ8dDaSVQyuBfX6nTbmgoJB1WxnCxunh%2BGOHAVCVhPIbxVfxnvnYIizE3hwcoi%2FHyyupIiRls7IgaMdiSxrxnhe%2FR%2BqvuoIi%2F12kh4f1IM%2Fz04qi9QIg%2FFAsFXh5u20SGfNKV5qDAJcEsUGJBxeuUR%2BvqzoiBmT06%2FsUeAYe178v7CduWDQOzGMvYWKiGwOBJTivUKINKhB0jogxz%2Bnfb%2Bq1C5npW6HIu%2BhxxM%2FlBCJCNhS1Htl%2FbvBLPZxiW4bdJA06tywqIhC3d7nxBOfi1y%2Bd9YZljzae3SUHMf9lYiDb0KlsmjOy2D7cr3drLtCfVatxfd137qu%2FVvn08T4EPvWfdJH9hAcfz%2BdgR9gcMw5iuZbCBUcIfMpdx3jwmPLnYvNTQZPAOu4KSrwRlfUeDC3f6Dlg4ccb1JTir%2Fas99WvYJecgvlprbl13su9W0Lw4i8l4aH2ctNYbvdlfGSy1KH7icT90W92tdrVUdxl31AnFVjfYjmllB3vkaOJVibD6WL%2FL6f2U0bufZrpP2I8tOKz5vT4XPdvu6%2FaNSh%2FF8%2BaFKo%2BCmhls%2FJVkYkYkHptA9Er71v8FRBrxi10upu25Cqgx5qQWr%2FWX9Wx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k0xn%2Br4m%2Blu0LqvW6Tie%2B%2Bnl%2Btn71uU%3D&media_id=1254206535166763008&segment_index=9" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:31:59 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:31:59 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_FKN6UNo2azwUZ7xsIpM3Mw==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:59 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786111917305368; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:59 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "be6cc1c217b6c183817310b2812dbb0a", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19943", - "x-rate-limit-reset": "1587864356", - "x-response-time": "31", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "00bf3b38007b18c3", - "x-tsa-request-body-time": "97", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"xZbNPBG2NUIdTAml7fKlcdv1v1I%3D\"", - "Expect": null - }, - "body": "command=APPEND&media_data=hQZBMkeyRflrfqmQfzKZnF3lgu0GW1SpAMgO3TRLL4VfZAYBTpMWB%2BHebIj2QleGw2PwqepJzLkeWqen324rQsNobXRfy8vVwk89%2FEyjl9%2BtS1drF6qnb83jK2DE%2FjhHe8QsFggpEr9QcHmij0Nm9sOcHv1AudgMeyfX1bEM9qKgmfc3oI5KVtS%2BvR1q4udTCM7xDl45UN7m%2BBKLzebslDeletBV2X87K0t5f0%2FD8eKyLAGjNT6UKepmjXJ%2BFjXJ3drwf0%2FtBjloWmD3g74yGK%2Fie9RpI0QbVLqDtTP6WEI0vhp0nk1rQqI%2Bz5%2FTEy4OsuDVCRjA1utP8KUklMrmC3FdCvFc9oTqrnuvVsJdei9S71aDhklGREkJsgrwJ945y%2BXyd2g53RO%2F0mjDqg4XviOouMLfk93u%2FsExzEQ%2FPr1pFw965fX1Cph3SBdf5f6Pi%2BWr779wprVRDXFkoEOdaLRgv0CH2iWX%2BvBbxLBA7vMYbHlZ%2Bvjnsy%2BwgJ86TlwQcfhl5EaYSZyDNWMNX%2FmOk5PNbvBNFQbBj%2FFQSvD9tS4Nzrk9H67W3uvd161%2BtelWq1cHusG0F4WKTVZfkRoUGwSEEDhcEg8tmRVJ9vsjQL%2B2ceLq6rjhjw2mUBSfRUddByRRYFW3CJi%2FXSLi8ZL3wvXD%2BlaXnRrw4NYYUsRGpPaS%2Bb%2Fz9rocN9ORnxovGxYFyuCgK52g7dQ28DUUpXr6JYRg%2FyVfqwYJxG6k%2BVqvKBDJvdqo3dISeqdq7Ck%2B1rsKl3dJDdDX4zcKZp%2FBISVhGBXY0V2z1CEGciRPFNen%2F4JLx7%2FQGQ0IDJ9ObnhPmJmoQMFIfQd6kRSDgkEd5BcX3DHEowQzPluJlJLgheuahY6idDbglKNsnz6lyQlBtWgra%2Fx8ndgyKg4o49ULS%2F9fsnNgqulFE%2Bv%2F9H3LeC2GR5Kqq1gbAiTrjwePwRicv14DFNvEoWFwoKcV3FGKDcVi8H23dA4sQt36YKooMUbydVemfnEDch9NZxaQcPOLV%2FYeJStkEQ%2BghOnnBI8GfXNG%2FWuLn8n7q6jcGm2gsPz%2FTQYYfeMaChPEBbLrQvVgpJb6bZ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wYC4iCIUCQRE%2BZL7330CZrdyoRWTcpqaq8vgfreEcrfjzQ9Py%2Fe5vybWf1z5F%2BpqKa8OwuxPSewrJk56fCxsOPhZ4AWaa6qX6bAOstQ17uAXah4tr31R5wCVZm4uM9L0OmaZ3izYiwh%2FG7V1YXHW6YdzPvdKVtP8DooMVw0mo0U5SCgIuIX1Gzvkq2Y1YgExYZd9Ng2tRZiriO5%2F%2Fi0UqUkmCTabsguv3IHfUMrPU5TTJjsS7m8%2FcfN9R4GPvOHhrCgI%2BSqzV7UBmQ562Cj507%2FFGh6FWlO%2FrnUOo4KzrZuLAwvF56g4AR4UkCwkCw4CwUCw0CwoC4WIgWEgWNAXCoSGI05y1%2Fp7VWu5dSl0WmMZKvUVc4H%2BsdY6f2%2FNE57E9YnWXwOerdalFnbNqu839c%2BPnt8kTUdIprQ1X6Oo2usbPxnkjZsWY6i8Gp5vdbuweiQeWfOAf%2FItjCKacSOjugrCgBTWHTPrv1SCxDQBaZZyuFJbX8s98giFxTQBbLWmCLPBJf13Vc75WtEpCFa6%2FdSyzBrnMM9%2FYxfmouA33enKiv%2FPzQTqMVB0oymXO2Vdhld8Oj6Hz4c3pccU1dBfH7kqa%2BewVugwYTBetTZM3o52SjRkOFvY18Jc6Wrl6pP99wOAASAUjCwUCYWCYUDAmJAWFAWDAWKgWCgmK4SCgRCQxC5q9b339%2BcveXKlXV0l4qqVq4NaH8ftL%2F3%2FwJx%2FPfC%2Fgr9GI%2BVdfSbxgJZdmrU1tc0%2BK8vy3%2B7QgWD1h5%2FXYvQ2mQkmwX6M1sAvxfkVSv4Wzkf6C7GiUOcNbNaEvGWgOU1T%2FycUFEGLh8xNXs5ZofzPT8Ob7r0Hq1fMeQ39kiLeiAHP9%2FNla6X716jgBRdSUsIc%2BA3%2BGCyY7wC9OuycLp9NFqUzBui3bA01a0AqjLtqx7Db4NcvsgFqUQo9ZCQz0c%2FnEqye7HbS493%2B2I6UBSjwIIgTNItImx%2F34zBwAR4UkEoUEwUDAWNAnCyVCgWCoUCwlCQRGQRCYXes67r1rW%2BOczhJVa3LilMasidD8t8r9D578T4Lpzxfifc%2F10Rp7aWo%2FG%2Bb5qX31%2FPhz8eghzQIaKvhFv%2F3A1ujqcpPDGu2tCy8g8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7%2BT6BIJquUtor%2FS92vTeQUdLKk%2FP751Ft%2Fii6b8svgjpc%2BYV6LUvnEaX7U5ofIvwQi0GNGnVX6I9amMrB0fzca9Un5UCWAy3%2BdIGPMX66q0dnAvLWPuIM1rcmTX4T4nhsSXrLUFFWma6puZfVecFh46rx5aFy5d8svr3hGaz1Tu9u44v6H2rpZcSQ766UFBGpdVZ8wfoe36tL6tN4TM2xtpPuvJsb35yuIyY84xLNoh%2BG7Gfp6%2FZ4QbwJ2czn4fQwsFa8sn6399%2FirxhFu%2BRjxpn%2Bt8J7zU58l97JzWDD6eoNDUsTX2Xb%2F2Xu63IQG2p7ml3H3CzphD%2FEn%2B%2BEgQay%2BQrjCDYy8VvadIHvrqdt3gb2P%2BCvvbbMwKMZ3ymyJmcyyoW0Tc3kzETUqXhPu55UkvnIsY1T%2F%2Fdlv9FlZPr9eJtbzI52peWxx6Z7Wv9fvNT6kESpGu5fCRwYDArCQgWSEdr355frBIaDP9BWpLV%2B1y7Xu%2BE4h3y%2Biyievf%2BsE4nAAAAlOQZoYhioFf0hPfr1evfr1iNm7mtcrtTp%2BuVevr9alonl%2BKXuJ76%2F16T17q7Xqte%2BbFE9r369ilv17sOYh8QPOxY%2BJfxfgyMNFbivLUDzLxYMSPHX0nhtfyhVLa%2BAw2CQfGj8GqV1WaTgw6xHu1gSkFAch%2Fq5Z%2BlkJ9h3Af9OzmiW3EBRAwVXB60lODr1ngEsHkNOXctqx%2BvdEKW6K7XvVfV6t1TX1r3eIer7q8n5vgRQ34JwmLHXbJhP9YIwm4KIe1NmcGXoHDS%2B8yKuExOT7LCBQenBeUbFVhoI24bNtlNbNJHgRj7GLge6amWBEWmWo%2Bbus1aw6DgJkBBe7hquXW8fv1NCeCIwpRiTsLykbPt2JTVp2ID3gy8tpEdxWhn4HD0AwOUEl%2FB4PX1wKuu8dC3h%2FCooMFo8ve%2BQMhqG0xUfgzpCvqcMiAUXfu483F1l2cSBeAFwFrYg94EIqMPvdS93W6t%2BtWKWrr1af1yrpa6anV%2BkJGCrkVc8fL%2BEyDnW8FpgFKtdALRgwqq4s9cGZWGs%2BnNXhFBgg3E%2B5eWYpimKcY9x6w7mKoKf0zmj3Zvriv666SX3z5Aw4gPjw04BxtcmA0MMpn5j%2FrQ3L6%2BveHHkGi6Ngl0xHweBM53WcnDLl9SXshYoz6KXy8nUyFfPLi9T0KYsuDhXV5PH%2F7p8UCCCcVWta68hvpCe8B4AmV9ckmT4CH9U7d9S1fx9%2FrXfavV1VvSOUKDAR77ARGUzqjpTDD6%2BGE90EMmqejGPt0wSpkHIV2F4PpDll%2BWQemwpgDMFR42PFBeM%2FVMAONjZ1TbCQUwXvrjUiwKoqTA9nL%2F%2B3otck9SGt0aru16hWK1c3q0tEr1uif0SrXtsgxgoEI7%2BIZdl8bxcYxIoopA5g12pENVCqSZtGlH0f5EE%2Brde7v173Xu192pVeSvfa9Xr3fS45fX693Xr1%2BvSF%2Fdf0hJDwxwLN4xml7DBdGDG9hcj1OxihAWX4UBGGRQg9svaTCIgltzGzK4d4NBvizrGTITeSXCwLG1cZqCgA1iWCrnSM697SSrQmWK3Pdcq9dKvRPq9u%2Fvv8EQw3VKdPwQjXv17ksO2al6481EzveDw%2Bzbnzl9a8L6DOSvGGjQa6Q9O%2F0xkO20PySjfhzEtBmsBPGukMEIv8A8QYvy5smzDC87p1CHadHaPaO%2B69H6b%2Fk%2FVpLr16uJRe3gcgVgUAgOFcVvdJxR%2FAsIEl30qvBaJBEFwUCHiu3bMwlUvhoM4bClAtE5PANF0ARBC2IQOgIA%2BfavLmD5yD72%2BGuVj9GQkUbo0v2iwd9ir4rpWqfBJvbIX6s9wUEmY9z%2Fvy8PrHK5fkKNl0ufn0vghp52E2l5remRnTNjKGtFar%2FXv179ekwJYW1gEJAkAgBiLqLqqkz5gyCUiqqrX3jRWsGocDhATmcV4rFHftYkLhcUFOLi58EuM0L53WJHD3OOvPamAW%2BCswJZYAMHT4xx0G73TQkbJd5AF6%2BQXJXuvKRHjvl4VPjZp7s36Ngg2Q2%2Fr7%2FVuw4SrVfRGYq%2FBLBHaQ%2Bk7%2Bw072H4Uiykwwy8kN7nYp4ZMRWUHh8%2BXEn32%2FDNUXbbpvGFfSQMmVVviJ4ZYbTXwrxloRss7r%2Fa%2BkGF1%2Fr5vDf4jFL6aLF%2BrV1UavVzVfwh50LELVdV4JV485COK3e%2FBiNCk%3D&media_id=1254206535166763008&segment_index=10" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:31:59 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:31:59 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_T6e9\/VYEW96rnCdyNbk7YQ==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:59 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786111962776287; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:59 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "0187010dd5d3df9e9bc03ee15bc465e2", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19942", - "x-rate-limit-reset": "1587864356", - "x-response-time": "31", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "0099143e00f947ca", - "x-tsa-request-body-time": "63", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"IktNHEgIFCryrZKzCbTh4Ol%2BKiE%3D\"", - "Expect": null - }, - "body": "command=APPEND&media_data=FYo3uK%2Br9xWRf4YgXWycYqms9x3LD4%2Fc%2FvsEZXfI1XXirxRisHvljLy3eEwQ5bu9ez40XJaa83RuvMXjUqtcwjjXtr37KtZb77WCeBN%2BGtdet0KIR37wLg3IYViv%2BE57nJD%2FZTTQRQgDqz18YEg9R%2Fm0AiGKhdlhzh%2F%2By6if%2Br35tpjFHRQyL5OD3j1eP5uq%2FDdVoNfbPzDP8EeMe7%2Fms6br1avRWJZe5V%2FwKj5PP%2F3qI%2BBHBACE72rfoVX6Jh%2Biz936EvXnMrcPqV2HcsGXwQi%2FwqI3Zjr4vVX2j07f%2FFC7jTXVBAjcvl%2F3wQEy%2Bjga2sAduyAxPuagISORyo0MmEo3k%2Fy%2F%2FECxDPgCrOKHx2kvPl%2FfyCZaP%2FEYbZbb0uPXvLc5Pn%2FkuvBDyWk9%2BCLe%2BXdeCI8NoNnpy%2FdwYF%2BvIY2deEc10Aw%2Byxyi5Y4yxXytizbaOxz5k%2FQocwnPDxAZtPDIJ2X3gAE1AoTA81hNlt9g3lfdlWYiI2AWdE0p18VfXqMulaT6q5tZ4VFEegFxhfVV2lD3TLmPKQ%2Fmsuv%2BbKSkqsv0ssowqVqaRlkFPpj6dlVohxn7eonVbuX66RRmWBphBj51TYPsl5PNSXorq%2FgonpoEKnPXDanxPXM%2Bmbi%2BsEY%2FAoJ1OCrqyyhpPv0R79e6WX0R78Nc%2FrQIb%2B9L%2F1lT1zX3L4StDMR93%2Bhbn7M1f8gi0OQryl9mZjksYRyqIBHG4%2BulOpPySaLgtRZapfXef669%2FjLscy3CRVdlgsqIHUkbyPV460%2FGHGEH4zczIxa0rfnNA7kbtEPRaj5L9MJIIzhArZywN4clKvS3wLdxay%2BQppbKMuzWgR1mtcPltBWr06efPmh%2FululFYr1GZcX%2FJgoit3d4lwV5eSGOKxXpB7%2Bv6Zt50UTdNp3XX0CPg1pVXfa9%2BvV691eEcR4SJY72BhZDQZ%2BsX4ZLebV%2ByHL1L5uUxb2sX4kolzm1Jv9Gwy%2B%2F4je9zIvuCXhxgXd2sX4simzyZ%2BCIWgYcajffmJRxh9S%2BuuHrvfjTyiR9PH19s2tR%2BwQGyjrTCmSoi9BvEtfGimqStpy7%2FyTGS0%2FFQisunvvpiq76KYEsC18MhGcwKe74D2p6ReYQZo%2BUYlwV%2BuXfNms9xV68%2BN0ujjD8Q4XKSV%2BXFEuOF9OX4ifUZt8e8u83v7vPt3vWLEWOzvgf67xX50YgnmO5ltD6qH5vIZ0Df9am9WHya215DQtyuPaJnvG%2FeSfXrq8hy8%2BHyslQRnxDlvOhBGj5pAfjnI%2B8qCRh8uFBlafh3zU4PLuxJuy%2FE4SFRAwzu6Tv21Tbd%2B9msXqk2bLP2h8eT1qK8EM9tbBeQh4bkJ5%2F5CzMZuVF1Zfc%2F2M3DeWrdyz19Yi4rnw%2BYP6awVGyGSH2A%2F6AAGSoCYCACwGgVygRlljewss1ThHFh2S%2FSGrgVQVDQd85cy53eOctaorUO7nqpUxX3Lk%2Fq369dq1erhWilvbiXhD1m%2FmDUQ%2FgAAADABBmhkGSgV9oW%2FdX3NavNanSa7uqlaW5Kq9arpar1qX1rq%2FWq4hXGkNl8v4Go4IBXLbiGlmIyiqFWi0wHp5IdA2AlhPrRN6TYVerA1MGpgwQL4Sh9Lp4oz5Zi0KOo493fUR3gfAQBs6ULu8JaQG%2FgdG3eDC%2B%2FoTFXS18SvfStVyjlevCHtYuuW1burk3Xv1Y%2FXsn7T%2BvZP4GMDLGwVg3MIWOygW%2F0uBHDYRNL5eLozzTblHrDgFUBsAQRt%2BHvNyx3ABkktgMVhMXvKovHnOpsDbidzlKC7D59KEB%2BfXY1h7NN8kykwvulEAfij%2BKD%2BAMhNPwyj2oDvQ5fAihsLoCGcEpBvSuLyWWO0H75GaaE%2FSqvFGZAzoHyQuOHX8eut1jHM9UvuNGDyHh3msG3jf%2Fki1bez9lDGXb1hEZQT7TT2YX%2B4IwwG5qbisFhiWn%2BCELAjLe5zFWhdfG936t2tXquf5f1Y7%2FVr9WKEK%2F1eqviaJ63%2BveLCoodW97Z3tnHyXWUjOTe1wGKBEDx13H6U7P3EW3FYrd6f%2FlNDfcQIGmFYlx7fl27viGg86DP8BoAj2iftw%2FrAjyCAQS3WK2wXaqAqa7j7DTnc4CIqLkNtMzQaXS4RUdsBMFpk0LZfxVzV1H%2F0CznBhSB7WullRpeQ0DyNfD5RPFFMnFNnS3u8iP1i1Y2vyQ1e8bAdlgIwWqo5TwJSke0J7HK9Sctesp%2FXpPUqVxVPl%2FX1YyteQ9LAS31AYMTXob1evS647%2FS%2BtTetVcn1MQjnRVWxTjApG%2BGsydLSqD5fwzun%2BWJ4wFUXida4GUvlSjeFMcjyKNTISuuwFnsXMj5cakzJe1HhqYCTMv%2F8Gv6ucV1RtF%2Bv%2F0EdV6vXre7r1l%2BtRG61k9ySdMWKMafekt48ZgmEY0cAkyTgBuKBrYKawtuX2u0EZeX3%2BtX6td93Da5d2%2Fpau7nu7Xv2yR8NDnZuQYpd0cWLZffXCAqc%2FKxHd%2FYwGJxqBj7m%2Brk%2BlJfEzUXRDpqY4B%2FudoCzF2Vfe3GXtCf%2Fa19rWK5yflV9UkR5S7urtnQoVhpllvvbDpNS5qg3PCi1FKGWcdQPDQen1X8rHzT15PTk6BEIDdRFWH4Mh3aHnt%2Fr3qGjJIoxy%2BgQaaX%2BKlp%2FZ89yfT5%2Fk%2Fn9cnx%2F7Nz1GZfX%2FaEtJ61W697r3xCtVrL9a8J%2B79e8DcQKG3fFd33m4vhvGwNRfA3Ccv8EYPwQmGiiarWAkFkTA%2BivieLqBI5BGk2C6CA2sVdC9MxHMo%2BcVBHuiZ%2BXgzH8j4yF9fNr6PV%2FsFfvDZbggGkn3tGw23obYcHZT4rye3%2BEirXJq%2Bw4TgdTpl43j9iyD9Pwy7zTdj4QLsEHbkdyehj9O%2FwRkGbtBlFUmEpj4Lyz1802DWMSiV%2Fsf7BESTsFxSWi1dJwQ9Xyd3S1gIcE3glBOMqLqqqqqqqq0qwWgjBKEgkIPj8mxa6wRh8DQJET4JcP4fwS4JHD%2BVS%2BC1hQaBDCwEUYNI82Lk0BevueJcGuzFchj8H08Tqg0xYf4GIYCpQPMCUK2AAIAFFwfvAqsAUAZxOKFmbZ3%2BUbzf%2F8nz2%2BCUX5fxoPoaVvpMKG%2FJ9qquINbSt0b1LiD47EYeamTmmf9TsoJBGKMuOLlr3FFcHZyZFlJkWZMVZlbuJLQ4trZoWjPHzvPQ5j3v5P7d9mVFe%2FV4M5kn09k5LSregS8xFKVSj8uc4l62TjZ4zr%2Fie1bHd%2B69a%2FV%2Fl671V6wjy%2FgoAhwwEgR%2BG%2B8xAMKCYQiu0uK6w%2BgRCxFa3frcPAiBTHKN4a1nvKYghvLxHgy6bZ8pYB%2Fn0oeg6dHA%2B8TDUBc9dAn3su86u6niCl9lQY1pJ%2Bf4%2BWnPmWTKFERGFTuGdqlLjXfyeJf%2BilDhcP1d5FeGW2Pk%2FaKXobp1BkOhYDHh8sAG5c6IHjwcP5m8qtXqqf0qoQJiR8t969k3frdUevUvJCpVi9%2Bfb6I7lOVfGLmx9YvNRviNaorVKvVAVOT068gjVaisVBD1Xsn5QKhuaINxDkuAfBqHMANfQKr4AOAunoPcPYYSDU62kNcrkF6h0%2BnXkRYaUaxyUR0foP3NjXxt5vPQteFoKYSF4ROH8GqB75RVZQUNi0F93rh%2BFfGcItM6TC2UBL8M9kqZ%2F1EVVSYX%2F8hV1%2BCfe%2FKo17k7M95wuTG6VK0GKLTNT2gOd%2FyfPikCWLO9qlZs5PD90Zz8EHG13fVoPq3SIa%2FqSEDgAmmL2%2BzcP2kmvi32itP1%2Br1n3CqP3DP5hTvpXRhuXPwRCnGQeA1owWEv1%2BECUdSDgequzbHmsv0t0HywgxLKimARIh4EVY1vuqnDBZsn%2BS9wRypIH2Ijl%2BYrTGVjl95JJfwuTTNxxM5XoNP9zUH7n8E3NkaGh0k93TIm%2BhNBsgiZGdm4Kjtk79n7TRBND4wysqQlz7FHT00Ajw6dwwSgwAcm%2FiXj%2F5UUwnR%2BcHESZ7jBHfrLQPZIfyfrXdBgROu2QCt9RsX6kaLUUXrUOScf9hcSTCmeANmtZ%2Bxd9fhNg7N9jqL5xK%2B8v7%2BIlou%2FR2rm7yfn%2FdYTqky7vn3N0KEMDw6IgO%2FPs9feMiT9lKdJPRDovBcSAWNAiFEcYF976bUV4zS1iM0u3BKJFuz8IqBlf7d4muMKM3nPNvo%2Bt7BaYIF6Rbb6t0PYV%2BE7hqJAiTlh7C%2BOlmPiCxLbvAdWh0iMBvCv7CRkx0TPqgibWIGiRQeMZNcDHvFItFR7qEI188ggzhx3DIBe5pd%2BcFkj1kdm0qeyw%2Fg%2Bp1i3%2FUJGMKDu1bzPuvCFV0ynrvn%2FfKW8tJBg5Th%2BqT99xA8ec0S4JkogvxVDyjmTMD9r9QpZ88BD7YUphfdT%2FdEEeHr8XGPOusoq3ZBr2CMfgf3nmJjJN16biOR73kT5BTDY2DKa%2BJ11hCbB95v%2BF5sCXva2XHnxNCJYc7q4Y%2Fe3hYrb6YY64DQKgrWEad26%2F%2BJ3PPu1%2BEbVXP7dVl3uXJ6Xz1rNn3vQKZ2W9s5YOx7aFTC51r8E5B64tGGd%2BI%2Bvsnr%2F9mPcMM%2BxVK5BSICH5GC3u%2BX7gp4MSAtrR5bTpHlNp6IETsiTQO8g59Ilf8WsGp1%2Fy1o5EMI4r9NVnaYpm4zK7kM1FZ7vkINHFejL1yB%2Flt2RBx8SlkLPnRwhiqajr8A79vBcUqjd%2BuScZHbgecHAjuNT6Q0yduK6sVyze%2FnifSSd38s3d%2F61sWLpIj2vX2taf6l79Xv0WpP9fUohJLv8EF6fLNqcIBAJcZZp8aggCsNX4P8v1%2BHfLkv0BS6jMitEyzHEL%2Fbjxz%2F4KClSDuZ7vydhJ%2Fb7%2BpMkf4gpaqTb2RfXnMrtuVP6lz%2B25%2F%2B%2FwRHw6lF9e7IpLH%2FcVaa4IQdMJvWWoRM3GNDE6ECYvNP0h7zi8ZEksPWVtEjrXVh1plfu7sw61d%2BxgjRngVTpvyy5QfXFYJZC17Kogn4pq9liqkfeGI8x8FbLVRRWXC0y1T51wioKJCSWaz39l%2BF0adRl37UcqFUJcRxCu%2BsQLoKCa6kwfY5lerlxparYWNeU%2By%2BJ%2FhG0bAUmtRc%2FPHP3l4RqqrBhGstr6fuKUOixZkll0IgvsHZ3dJLc16GvXr0%2Fgi8NRv9v2wSmQtSWxDJMH4e7m%2FwlsxyTd%2B7cFZZGaWJUUTRbR24ejGT175AvEP9je486t2W1v6glyR23Oz9e%2FBJ5IuF5vBiqfCO8dZEXsZLR7fnvd4gxqB5iOPeYF5JnWkliOaalD4KXVXR%2BKkJAxQxOwgZ2j80EPxfqxvhUXWjB6zlyT%2B5ByJKJzD4022tKIEPbOF%2BSC8O2pbrhE0Zc93TflltNA%2FwfZ6HG0MLVd8%2BPE3P0Cf3c%2BWFvj9Iv0PavV69cpPXr9X%2FRdVuCIxaGvuOsq7feu7XXqYr6616oElXrU98S7%2FhcgilHN4XBd7eJc3NJpoSxqI4KtSDXhYfWLuNjqoa%2Fgb12D7H4Wcmxyy61%2FL4UMFAqG4M4KhCmliB%2FAK2WOZ3paiN2%2FALQWCkaGdKovWCb2F56ryLpIzEkqFtjld7ua%2B%2F1erq3e9X3zX6v9zF%2FfyFxk7%2FUgUl%2FyIRbn8Q0tAhCDDQmbGtMZ835MgAAA29QZoZhmoFf6FtfL%2FJ6vV361%2BtRaeqvta%2BlY%2FWpPV1WtV%2FzfSv8StfG161fq8lFKl3gWmBmYKBVK5cludM2PixADO7L48%2B8tRbFWFZVzDn2dmgzXHtY36BkggPMxAmQGq1wvV0iCxjQ%2FfnJEz9YAUYC1huDG9sJgGK0dqnX1uxn0DRDjmNJnq9EfuWVFscatUEn9%2FX4lUYr61%2BuUuhdUyI1XJ61333wCRDeYPXVdVA44ZfL31ekJQgLfED1WF5iYzFYDFem9uPp1ZuIwA21LOx3VezatUtgdGoGigttslH541rZgsYZxrJ5yCCgCHwfuM8HbEeIcLlg%2FItZKtxTr3L4ehYgLygjYfr3uB8ajMP7aZBok0C%2BT5NNrccvjzBEZJhik0e2e3j3pxFM%2B%2F8eMBhy4jcVTQnjI3n%2F%2BFQoHbvCjS%2BfDy2U7KZ9b%2F4RCwevt3fd3v9Ob0KWqrnsch9%2B6qqk6quvVjuTm78COJ3gjCbMLGW7a1y%2FQ0KukCUrTaeknSqaq3R4fJ0DDS8AxyQwic7CSQwiHyY5wVRTBqN8Fo%2FheGRZBoWEXbisViB7MxahUvGu8PPobRW%2F%2FJumngmjrxHfOZhBYMpCWshkR20fT3Zo%2F%2F6Bb7mRVtD0vKZGZcn8IlHwpBCeYAQkzEYZlciFisNd%2FFgqyk%2Ff%2BEBSyf8n3uwQTXn%2B8N%2Fff%2Bhfvdeq%2FY28TWKT17Hc6q9e%2BWrmuTdWrBNsnqcYGhC0PHFkBxrWYL81wprEufmiGJAa9L52t41IgUwJj9bDP0hUdDitLxpzx1fGj7YJUb6t8sbpgNohjD1Jn%2BC3Juh7zS161%2Br%2Fq3xdXVrV%2BtV6vS8sWK5r2Y81vDQiJKN1srWEO8IyIFI5a65%2FlZW%2B6%2F0Nr4mrv1r9avdaq5vWr9cpOX4ldcJQKB2HB5%2FA5hqSAA6FgDJ1TJ6hTg94DIfrko4zwAcJxUt9aZvGS1%2BMFszpdOz%2BGlTGGEcLIHe%2FmIvRxUH1BXos9sVhC70AN20T4uiJ1FrZ%2FBjUNjbODsNnzjBGSMWLP7Y%2B01kuFBUPJwSZTHrTmwzueHWnAHNbN9U%2B89IE2bKpNvyO6qun%2FQmYiPWr9ak9er0V7v9E7l3ojFBs3CUvzGLbgRNZ2df%2BF4ceCxgeB44%2BDkrEeTisVpS%2FYIBr%2BTyVLwQkdipb8WqsNEE8clEcUJlVHUixb723HDwxPoWe4HwGD8l5iRctXJUC2Wb%2F4ITEnKf34%2FjV6LqStFIOQ5l%2FJdRmo9NKOCEoRB57B57QVXMgxDrchz00MdZW4QHc4cu24%2F9Jtgg5SZ4Po82Vl0iv%2BT%2BMYnwhxl6QHEkjQNg0yD%2FtC3Br7RH7r11La1vA0BsDUXwMwsFAh9pdrtYCYuXtNcC8LJqq3ghH4wqqqqq1XF1CwFUwTZdnIC%2FMPGRWMj6SCAzTi1pjiELTuVi%2B%2B%2B3Kg9OOjIYDTlkh2PXCdPcD6EzEtB7oBao9V4Dfb6g9PcX%2FwuQw8EnCqBkHAZ3gPrSiRHF9df6p4wU4Bp1%2BX%2FDFyI6%2BVewOq4QlLOUoBj4JC8ZIJWPP4ZOVCu0MTicSN6NNynl%2F%2FBEda%2Fa%2BwQGjbLeJcLTLRCRS%2BOX8OMs6tfsnATb1b1zX%2FknrjNj%2BxVF9S7nvSV4VKUiUdp8muQk%2FCksv9vvGoYgy8YPw0S6OpTVsdu%2FxFC3k9Ef3V%2B79ayeX%2FMtBgAgIEgl6i9YZgEOA4gpMKMVtNOfBJw8OKouL9rBOJwSkPcLZ%2FB2x0qmotYPQyPBUCAm4Jv3PEgOB8FhD%2FL%2Bn5iJcux5oTgv4JQ0FShYAA0prAFAiLChn4kamYo%2BSE7ENTu%2F6MXxRbXnQ%2F8NC4VRBXoz37h5JZHdOH8EBIECD4ElnoHHn5QIFt5vcZQwGDcLpvIccH89fwQXRjw%2BLh8dCmHaI3kHVgQCpLKNogau2tGieiC2ZlP%2FBKUpsE9T1oJ34viS%2BfVtPBsOfg1rjDJ0xWq8Q%2BDZ0EA45KACpYDv8gnFf4LDWKB20yf%2BuQaLX5yqP3NOpT%2F6p11IZcZIOcPzdTq3GE0tpnCfE995uhWxozq%2FcFMuGkPEJgwRghDtf89PLsK0qTOzkH2fOlJciPqFebEdMhHX5dGzG5%2FzngYPWJ%2F1xfa1Vq%2BT5%2F%2B6uuauasD2CjfgIsJGJdd4pAdw0QVFd6xoiwXbiebu4r2Zf38P1FZRhg3IFLZrEglgAaTWpTUNotwecOGwoqDxA9v4WOAo3gf9Wb8G5Ojr1Pw6RcVSKHjKJgzRFom66C%2BFM7Hj%2FlYQHNftCDBE2HFUaGlCpSDBYMP3zzDAyVQaQ9Jo%2F8pzwfl2fyfN%2FRjWRQwG7%2FD2W8nAByLAY7a%2FAviC8tYvifHUFF%2FTMf77Idy69fwR3v6n5O577QnG2%2BGBFnfccecI%2Fh6npF0K2%2BfhMak8grWvdo%2Fq3fcaK%2BDQSIPm3rwOgUBCOWqtrAsghUeIB14DvkWqoHM1Dhgqvw9zl8JAg5ilBhLBfAXd%2B6jgPP42k9fnqqMrw1qHHJLHDGHUW4PsDvY6ddqIoLoSZL3wl4Xn69sOcbJCksK5kgeE%2Bn6tMd2Bj4%2BCg%2BP6hVMf6bhYxzDGL3XqzsEE5NJi87C46%2FWSFDiosS%2BSCPDSvewXiAQU1Nn8uZfZh988D6mk%2Fk%2Ff0iTYyg%2BaGUoSbBJCfjM5UP7gNxdqUvGJVCpytXTcTPiPlr3r%2BvZf%2FVCXNRzlQIhFAN3w3eCYyA44LnVe2YT9zh8rkCVPIDHYFdjZWGZ9CBZk4gIyS2KL1SIRvzpawJVl9zCQCb3qXvswbNkqy5EVjV0HBBlrEYNroY9YPCd%2B2ssN2t2H%2BidUmHBhF6FWd87%2FsF7Gnty0UviYIG86Q0PrQbhyT36J5tdY8WisCfHYzKW0KyscEB%2BkCwmHbKTF53MiDTlI4n3r4F7T44RtgVRhyJheMbBM8uLT8y75pPcpV8LiS08CJ%2BA%2F9q9r8IfW3k%2FlraDsxkdCx3QFTXUX3bX0Fu2E8H7En3%2Bvit%2BrRE135%2BX98sER8uINzU9BqOeP06%2FSNvifsNGBLsfDCIq2pLF2NupqgmfWv0XyeS%2Fgl%2BtOeEaTMXN%2Fgwt5QuPg968UupZzTDi%2BT9stNWPWQk3m9lWHThOYOpP0WeHsYzg%2BnYojvzvYDXJ7f0%2BGXg%2Bnq9KXIYOaP7BhLisECQfIICwKNflGcPyG10of3Nji6iUgMCfRyW2syRT5L8tYFdXYoxghCRnZnZD5oaKix73IhrEBMhA8RX6jDxBGPxqTuYLP44QwaCrKFrosXsAVbZk73%2FQ3rJhZA60ApFsbmhY4%2F%2BX7RGWxvPORR6c%2F4au0clE1N9eLrQWMX1e0MD44XRdxt1QkOwxvH%2BtxA8afHWobzWb%2B7IDOrl5M8mlEIAe9Ee6v78qU%2B8n0nYmGAgMsZVIXy9ov%2FVDOmE5laa%2FU8Qrda1%2BSrk91dOwxDGpJcmLqUjHTZxME4d03bhF6L5Uw2Nf7RDX3kXQ7HON3y%2F%2FmFM3vjup8ngiPLYJLMPT1eWiki37N1qqwjhAlPjDvh5rraVfXqFi73GyX%2BL48xt9%2FwrlzdrXw4In15vW28L8Vo6MpMK6uZfgY4gsCAOwR8WqdONd%2BstOoT07n%2Fk8v%2FfpghEk%2FHbsEhshMK6doJaIKDWl6zjjqfMGsTge0MnXUk4P0T%2BukHdZkQd3qDFLWhPpvOLfAHGDwyXPhppK6p%2F%2BHNP5fEh7tx5MaWcsasaoB24SWyu%2FxxYSgH9Y89Xy93JIjnLqsgVYkZxA9%2B4vsZ4CrQ03bew%2F3nCAiOuwAqCiiTsyDWNt8UIBZztmu%2BMmu%2Fx3X5ukAdZJr0Xe3dUR3%2Bh7Vk12tfqQHdWxF7%2FBJj4KqVUJk%2FEt6BRzSL7GQwH7n4VhC%2FQGtq%2FzMZm2PuSphgvCBpfOVf0YXzvl7N3f4JSvEBpbe8J%2BQxZk3RPtb1ejIcu9JoxM8HsSTEC6N9ARi7%2F8e84JCWbQ%2Byy1Xgn1lJT2%2BlXaGGafwiMh2FsxvlXtcWWclegUvtEk4m8YOg8l7ad5aIIgXPUuchyfPl7YqFays9xK48YVfHDTQNYt%2F8ZEGLgtZ8SnuBV9XCKmnwQ0%2BPKLiHC4alRcJharrR44YLq1USeA6RHwWL0mYKdjuQopbz74H1qBwGjK4mN4NbmfuHFSJmFE%2B%2BhIzStY10bjvoNrgPI7k9vL8mWQwsVB596wK8DTNjGCOTSrl%2FQ9u8U7MvosvUgg0o%2F2IrQyo2JbjinzcxmMk9n7bBBJrtY7o%2B3Eh%2Fw74x8aHGjRcL9e2Ed2j5PEbZNIPdL4vdHfTrSv1Ne%2BX9axRd25%2FP%2Fq537q2X6RewiTjRUE%2B9hBvbkkIHE1BGqGsnv7BkIQReHmJ5aXExHaTOnGeSdI15oXVGdy19qmIJve2n6vlxnwrNrJl9mEF4ZjZ6y3BGfB2wDG5bvcQa35PqytZfLH9cGqW4rlNnifC4HryFlEk3TiPOP%2Bo3l7vfFc2CsQ4UbIdtV7p%2B7q79D%2B4%2FL%2F%2F4l937I588%2F5cmf1i7Wt%2B6I%2BT3l%2FIeaVFV92i5d6yydb4IsbLrZQz8godZeleWSGcWzeUcafb%2BrHQWRLhmM2Fz5Ivk%2FCGEGXEzU%2BXty%2BKEBgJ6QgRFokRvH9O2eX8usEIkmDWvc%2FEGPnsyLfoe%2FxOO3eul63nm9y32rq1u7u7rD%2Fxnd69swqXwcDh4WDI9%2FcQOWl3jx4VDJd1wAEWFJBMFBMKAsOAsGhMaAsKAoEwoNgoJQkMwiIwt7VO%2FHUynXrW%2BqRUaYmVWpEq%2BBtHClr6J%2Bm2D4bd%2FOt7%2BUTedcY7sHkU%2Bb0odIY7deuL0wNnmrab9SdVXvuS6N9vGm0K%2FhiMgGC6I8OyUI7hkkWfHiF%2BLkvn%2B%2BRkpFLB7xnKbCNSWjl2eZo710j%2F6f1j1kn7bjydUP7j6jib91%2BVq5z1E70D5TgQsEL47DVzIqimWT1Wa7xwPzqvLcIWdXZ9lw16u6%2FdCAsZSsVWVMyGdgC%2BLG0EHJhZOinvssKy9d6xrVF44340W85iDgEeFJgoRgoFjUJgwFhoGBMFwsFQoEgqFBKIgmEgiRmLrnv68THXv1vVS8JLxNxJdQ4CbtHfttO8mLj9e3dN0%2FNW9D3ifs%2FmXl41GpCA4ftr7KRjz5O7zYqMpS6r8Ou%2B%2BMyoy19xpF9k1Z2LywIHcxUaQpa1LANu%2F6KAX8G3%2FS2Y7GKNAQJRJJ6OxF%2FPDPBeMzBJy7M4r9BnvNki2rTWJhF9R9uUzwjfV3ynzsqnE%2BACPkVGLL%2FFbxYC%2Bzr9dsdHCHr536Yqhpa1FZ1pQ%2B9P2JWjhm80utCwy0pepbQ3bbIz1MOqtIwLfDUDgAEiFJA%3D&media_id=1254206535166763008&segment_index=11" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:32:00 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:32:00 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_OlVOT3PpnsDXW8+jRQnJcA==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:00 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786112011814142; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:00 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "a5803d45371bc562d610913ce19e1c0a", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19941", - "x-rate-limit-reset": "1587864356", - "x-response-time": "35", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "00b2df0d0046bd40", - "x-tsa-request-body-time": "103", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"quxPlqWvHj7qmOL4DRwvu6AuXFM%3D\"", - "Expect": null - }, - "body": "command=APPEND&media_data=TBQRhYsBYNCgTEgLBgLBQiiYJhQJDEhO%2BN5uZeccvPrqoqYuCqXJlyuhyX%2FYnHXesf8dG2r2p5a%2B27v4s4PZ1ctHGqJ6E7L38WYMuiR8XNbBJrAdVWrU0lpdo30fAQgGT3YtOMMYU%2B68%2FiqVwvZ0au80YsziUONFAispeGlbfh%2BltXsMW7TxTz8b%2F6%2B%2BEFT4cEdTN13a9XmViDVPqM9fJdsdtHHfpvHwqWV79RoQvRWkhB%2BhL%2FUPokvjzRT06H%2BKXNyvSlIV0LSg1osrGkdyDHT8qxPwvSmfpn6iVpL13U0fKYOAARwUkGYUGwXCwoCwYDIWDAWQgVCgWCoUEYVCJ3eszJvftnfHi9ZcUvJYmZdolTga1%2FGfsf4n%2B%2F6t8iv4vF7uVGqe40uL%2BMR5CF%2BT5WP4aMMFDw%2BkzvqZvDiyfFn5mmZ81lkQDs%2FKTAN7yTe%2F5esKg2XSYShJIAV7fhPNMRAh275KPd%2FoRbz%2BhdYOjHcK%2FytGJvAhChgKCC7lO7itR3zN3NeXvl34Tse3Y26kALr7eh%2F5FKvjtuHyfhvmJQuZZ%2FeiVxDJPVjItG7xa0kUd46YtAfnCkZWM13N2VRlpxg4ARYUkCoUIx6CwYCxFCwUCwkKoUCoiCIyCInO5rvOZVZ166zjLq6xcBzeoJOBp31tO8w4xsycX9XS7e2L8c93h7PgV%2F6zR3rEr%2FKXNXRO%2FM%2FmLH3p2yJYRtX6N3HimVAHR1eWbo9l15Kfx2j%2FWPz9Y1HypObcPGatgtkCQn0NHynmPt5nEv2%2FhJD3Hn6%2BpU8Ckaev9E0disd0nhPJyzcCjl2r6s8ujMceUT6A%2B5UQPuPM7Fw0ioz7Du1VD5DjqrCDGKIkXLYZ0k%2B8Y9Z9UXwvJSm%2B1KqqVHWGvBFA2ecDgAEeFJAmFBsFAsFBMKA0GBMZBMJRIJQsFwqEgiZtMc5rd749XNTEq8nFZJW9WVJOBwn6bTfQuOc0%2FK7sP53%2BpXy4%2FC7Rv2ArcPwYPeGEzn3C5pLOiT6qr7UDXRynri23xHoteaGZdtpSOdNku2Y9NpfxPRdFfVYPo%2FQq8SlF7L%2F1QIqwmw64ApqkQn7vbqeubwTw3iuXkB8vt%2FonO7tys0LWpKodPUERE8%2BFcffVcRSUZ0CB3OstR7NquS2FZdxFpyqUZ%2BuI3NlhktThrgYzcLTw9c1mPjT3L7spP6Hn7UsLVdosjLvmDgEkFIwqEwoJhQFiQJkoJgoFiIFguEhCEhGJ5973HP7%2FYzKuFhLxUrNRCXwPzD4fpvuX0FuRdyub8OvuMPt0NuH80VoMPJqJnhseXq%2B3Kzv%2FevL0lp7x6NtD9WSXRu7Il4wIn5oTXtZ8Zsdc2PhaVUx1bVyH9t0TTn9W6KP%2FNd8FqmabpDpNPVf%2Byftvqia0mWpK5u6eiQEMmilDobla4WOYtRtFAJSnTWMCcrZGnKYYuCi5DvYznezcx1JzfYl%2FueYEKLuVFqLvnfL1sq2w3VsBJENLnTBybSbC9MLfGGOvsMvXZYYLjPgg068adyF1KavX5vcBwAAAD3BBmhoGigVz8T%2F2hPYj78CAI7xG%2F1y%2BJ%2Bu%2F%2Fv6%2F%2F%2B1rv%2BS%2Bf6r1u%2BLqjV6vX9VdF1wh33VPc%2BT3%2FAsCzGVP4Fo4JCD0pxBknrkjrArFBSYMRtldvadIKTMDjFgwbirriehiPgqWX%2F7Q3f3WCrPSrSCzL2hqXm%2FVXu69X%2FW36t2rzXXN0TV9EyUnt%2BBWnGaKS81fmrq41VfUml3dTWovl8YABABwW5ZY1%2B4osd%2FMy1AZ9A8dLFH1Ltsc%2FFkwT9MDtkNbftxqu2eX5KAIQEQHoHQQcD3eOGwdKAypWvLeMGpygrNHGtZCwFKTFWSnWLa%2BI5fTCgQAnmCsPkW2iTenUfz%2FlwJg9P0jLpdpm1pI9eICQf3MQchEWmaZCxKWSlCLw8s2fabqavkHB4XwYS8UJepD1g9ZL5rNWEc8naYpR5YD1lwesZnHAkZTynuORP4paHRor%2B7raVv1ftX%2BWe%2B1iqZvm77WvA7%2FB6dZZlQBU4%2F5IxKnLSkbK%2Bm%2FAyB4DkFXG1ctmxnU77wDIiAYsERbMPT7eCTCI0jiu54%2Fy23eIbAstevFgZN0sGWgVVMaUnq2qUdUpay%2FLySCMyqzKrCCtxfYTfXyCK61jXeKYWxHoa8nrVeuqFLfrqpibHf3prVrk9Y%2F78CMCcgQFxPBurvBuMEglcVR7aXxX7Q%2BtaBHyZvRMt4pauT1i%2FVkjfv1dXyYMhgwIQJd0CsqkTKVBtvvvPC0xu9yJlp5fIGmQTLGcDdyxl3%2B8CJp276GHXeR5r14w0qo3FwxM3XP6CL16tVSymurWX0r%2Fr1d8BF1fZvADtZ6varaBQIxCfACQFmEwRsstpwADaLMdDo%2BjEsonOcongUJ0x0cUQM3XiKk4cn1BYsF5WCCD3BJlh2VLWNftFIP8tbPBv%2BOiS698taE%2FOr36tdrUvq1WrERauJv%2FJ3dwYdCE0QLlGo%2FZ%2FAToWLZZfbyWeAO7bD%2BbuTuryuiA5cBVCxaCXguXBLLS1d2MYQsSiqXBRJ09apTRgLW%2FWH7uItrLhRdQcEyuDIlBV5h1sLqqqZoKCSFn685jyC0i80WlwwHAfd9xv15By8PCAhYEASnIgENpRtL3YwltJoQ%2FP4DbqhhMpxEEAl38daLuGdN%2B6Y1%2F5f%2FLGDMvsSmJVMKo57FHDFXhDpc80TWtDiWmaDNBRnTNanzXoTqrjPVyJvyeKQMGopcaKIPMWVKONRE1nZ1%2BT3racb2TgbsYUwajz74A5blJXZ7juLgUwtxLllJoYKoBgo1IdLrbyfZSwh4VoOYBs4eTQAPnwHDxw5bxFwIqQbuWXeoZjv9rW9glFEwKuwV9%2BfkHa7cOhEY%2BiT%2Fk5Olm0jxTqXRfkbz2xptNm37hK91P%2FCppT9HPJSwSxWn%2F8KdjhlEjuYywYNB0bO%2Ft6uFu9OgkDx%2F3r8OL5PL%2BS5Ych5PlxFkv0KmOSXnj4RtQK7sTCXDzjTLbbfGwTWqFlkCFIZjMaRUtYu69Hi%2BT9elwjr16vWKsDEE%2FAxBXwKwV1ALgcDoKizVqq0uBigsOtarSqkvt4Obgorri4lI%2B2lIdFMPBAVAUp%2FBhHCXXw2i67gaDVB4TOX8H3eHthuNA6MFaEwIvY4ajLcQHi7T%2F07eHPfHeSEOGdybDl4jAVXh2cJQCynBSO0ZERtXvhRcM6oVukv73%2FRd9TUPN6goRE%2F9NJ%2B3Xhko%2Fl9f3j%2FbMJ3mgRFWvsnv%2BpicKqYl%2FfxsGciUGrBwKHFN2QfcTv7klm4BrLS9DpXgrvpPCDH1ai4YXHp6a%2BaPiI4L8FBGIQ5C4oPJ3fgk6r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npXcuT9fkUxcOoTN%2FCQgIXOCxAHpNoIwPPdPtSQ3uoKSGg%2F67ZRm1WyfeVUlRoCiNMH6j1J8WF75fhGGKxnLcM2fq6uiPjNpMephfpIM2%2BpPqH2EuNGFcMuhxrdZnp82SvN9A6ZL2MvcwnGBDAXYi%2BCt5wdoLpqOSnsJN%2F0g%2FgDqooHaADbrcGbJ%2BokyKe51QeBCudQ%2FNjWpho%2Bsv6wiJxHctNmvHiQUXufN3Y16l56JXs4oTr7kuo39C66NuL1a5Pku9Q4IjpmWG%2BMCQtF%2F02lr2wyUh0gJ3v5ex3qy%2BGcfBM3eo3sizIG7DaSN1%2FRgHfi3rQPLouzFlz6ghqS5%2FmBXiiY6WGhZ4fz1%2BGn7Ugp%2FwXk3ctC51yacn97dDBb7wwmYbR%2FVU37nwmTTDUfyjBGzL0Czoy0ivupGJuXuETcYSNBsRwpzaA3kdmDUby%2BFrckdhiPdM%2FoZ5BTkS93iEjcsWPkFjz5ZXw9yp8739xG9TYzBjpOgOR4OXhqLlxYjzjShQxrZiguWOaNGw5wf5kzpr%2FeLyRmriXVo9NA%2FmOzCQfD%2FM98QhpXdq6CuXQ54qPKJXx%2FKkgPwf6vptLbSeX6uJBwERh6peIPPjxRXEEoyXWeDGCzU2dJxWlCozDnL7yiwhStcKublf9nxLyMWKcDMGOHFNT7SxLYxMqSlumlrQR7VbgiMEXucrmv1v8FVMvdm7jNSgMHqH9Hf9p%2B%2BtLBBtO7vjrJ158f42IEpbK4q%2FD8%2BPyuPJh6HNEE7cOcz%2F0%2FEnJ5%2FqCIsbOKdG52au8ny96hKnKxTb%2FrY37gr8ZUn1ze3FXisqKbxqkiLg667CBK6XrfRnwltlNUvkI6NnX5IiOen4D%2B%2BvyRHZu6qhidIOtV7ioy0w7gb39%2BT9UQTcT0gzGQ3FyeQQJvgk4G2pb7ZgnE%2BYxeBf1KFXlgtKuaT3PhvEh%2FmWuKsQQtivy4Dt%2B%2FAzhMZzM3qpujG7vnEJB9gryUGpuwq0w4wJSYKisQ5UTK%2B1nKSFCCs9y927tuSit4MG8206XJ3dof1Xp%2Fj1i%2FV3ffurD4JSHwpBxDQKPu%2FqCLu7ml%2F8RS1lZX%2BPugkm%2Bq06ecMkLq9fDiY%2BZL8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" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:32:00 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:32:00 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_gurFzRo3I98bH5Cajp\/tXA==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:00 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786112063432381; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:00 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "80a14c7b56c780c8df4b9b9f7ee42b45", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19940", - "x-rate-limit-reset": "1587864356", - "x-response-time": "32", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "00f5c4d300757685", - "x-tsa-request-body-time": "94", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"Qa0fJiTl%2FtQd%2F9THMPl2%2FuAAAwM%3D\"", - "Expect": null - }, - "body": "command=APPEND&media_data=OsNU0m5FhTbTMLsyqP56m7L%2BmsFtjrTVcXWFyFDMy7ixysOsosZI19c%2BX9V0LjOoE5mypI%2BBKdxp59db4UihQisL5ESBuLEPW1dFW5fYi9oYQB6uTNLo9rRyILD6cKvoNM45CplTCIo0%2Bf6uvd6M4ye4N8Xn2CO1iJQaVZMebgiv3IIXr2S%2BICpBrEFQwpcHci2W9S43AduMMejXWwz51mOijKugprO%2FW5WeCUeP1st33lVArxmoF%2FMA9tcJox9w4jHscS02uwmaveESqxwVCL6r2f2cWJ4Oq6lzvBaL79X%2BIvu9%2BcRZvvQR8%2BYjV%2Fx%2B9wO2D3vCAIwJx0MgR33dSyBjAGegEGoD3Je%2BvgWeCBs9Z8eQI4Vd4VhK4gf%2BG3K7P8igkeo0oz1wfJJpTMJ3e8nzcKMB0bDSEPA%2FYI6V3SHqC6%2B77uL92VKP3f%2BKMMSjfD8J%2B7%2FBDlrwy%2BvqE5%2Fxxt4i5X5iXEYQfUgvAFI2cuf5P19vCZHGjGuO%2Bdey%2BCTO5%2FfZuETfmGCNBBLBFMa3DBzH0iV9XIWNsJQRFIYUH9wyE107%2FoI2Zs4SYl%2F0hHRnhO7Klny8sLEEEVjEbrZC7fl4nRpKHzQUxPDZEzGp3BdJxHc9RvEnBPM2UcUxE7gv%2FdI2%2FfqMqvzcXE8pNNwmVdRh7Vc%2BFlSStNAxVBSSxECta5L4hXkFj7vmu4WVXEfl9PR5QpVX43Fj%2FEuFys%2BQeVN44pChgQK3ECxpYjBeJpPVSCNX69fdWvev2CUR58YeWkXFr3G7EMyufD5qSww%2BplX0jZmVp1fX4fK%2FHR5zg%2FKfoY9to6Q%2FVN3fWEL3zUDT9TFysd1P%2Bevh1fRtjr3CPljd9a%2FBHnxj2HxRGrN6Fe6J8Ur4I4VUGvpLHtEsERGcx7ehFUWZEHVH9LBUXLVnle7wWSEiGxNhuHJGvM9dzhiPgye5oggnhSWKtxT9VUESg258ru8UQIdmrQ8OQFFRRhJkzCYLKlvhIQLpLtYx7jDAo43U6HVTHOLTKmsQlDVo0NRVtp%2F6YKshc8vaFSrymaxb8yGWge%2FJG39ndMuIdUwmos1lBbwb3McRch4VpDBmUDuSpBVR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6%2Bb2gvDbW%2FL%2FlecoDB4kWTAlX2N5xhrxAVHitqC9Y8M%2FnXGJuWqhODaf9LIlEQWz3s4xQ2J7fvLdRL%2BrUdOhLUxqB%2BfBdWdjafZ9HOp%2B%2FM%2BZDL6XagoJVy0xloWiC1l9XvD8MsskZoptLiFdf6i8NIjmhgpBh4asWsJ8A%2F%2BG5liifo2pkVkP3uSCMkCR%2BnVfWGdhvnoNyLww2NZLw8p9Xb4LSoGD2S8bLLi2bYZqm1vwlefShmK9QLa%2F1D1GwYaZYH%2FyqJ9IKZixyl1rM%2F69Ue9332iQd8I1TdrUmCofwVBOYQ6PtwIY8EZHerGX9COYVXe82XgbQjCKJmMvhMJinHMgIDrVDEAcBssg87LSal8X4slCbdvcXaCN1aLLpKuV%2BgVYlGJK75wdBwq1fX4LxpTgdSOaRHeHRUSdFpat56MyjBgf%2FhQjkrDcboIbGXYU0DZM4I2jd7N3EGQ2b9Q%2FzOlCEv7%2BNjRfLC3ePNGWhmgjbjFF5MBbY39VmGfLfOlP%2FOLDpoIrQWc4JqkzCN4PdiJGOIbUrqwOXyfwrYwnz7pMJBcuL084kvj%2FB3qyn%2F0YbfjSifwtXg6u0O8SwycsM75SrK7L%2BuX6fsbT33XGkGk5LS95Ocu5vGjQRQaDNZr8E0NrjsfSkzH6kzBNKOfc4XKMH3FPnXyVIMpfUQIDTvKP3u1spGHVth6cPNR8Hbv5SwsiIS3xF7%2FPvgctye6pF2FrieopOa%2F5DDAP%2Fmw9LiRLeSejZ00Y1R8Vou8Aler%2B%2Bfk9Po0K8DttR3IzrsFqXWIvLLNda7%2B6O4N6weENet%2FiZP8YXwUreNhLvBHA1h%2F5BoqlQgbSqxHXiE6Pg1nAkboDJQCpFUTsO8rIXnuHoxo2dJiX7WsPwBxfUB99voF3SoKF8ohz%2Bo0TEA0veIBnHGZSc3vh4rYeXCCs5pHzB8jhhlNNpUVRpt1v9ZfnF9%2Feob7n4cMpSRgtGqDwgf7f%2BNymLeS1O4tM5XPqbronhUyoS4yen%2FwXGvd7%2B31hoorPy9XRazT%2F2vdmtDTLyfvuIhwr0DSTD%2BD9Ewez1%2FDDNa7ifyI5F%2BjaCXU%2F56Q%2BHWBPgBDqOXE1c7%2F5f0V1Jdaw38Xy%2FHJOv2IFHcdGizzBgSZ1CpwTul%2F%2B6OGZ%2BAGPSGJlSeYv%2B15duo5%2F5Y%2BC9tUEDMv48J1o0X6sK9MKl2Bh%2BG9FRe30wzvrWNm9xlg79MRAtunzFTu%2Ftl2b0yZsyi31E9tLdj%2FCZJb8HZcnoUVCwnLdq3KoKOzbzWHmBECvSccbNkIgsSyr4O2fgg5rysb96txxm9YhpBh6dTfw1OfGBjPTWWaCWF9%2F4fzaQRZuF2sfClQUY7YcaVx1gW1xF3pSb89n7ZUzXheuI8CfRXrpauJ71C%2BQ3Liyr8LnsBztmpd2GlP%2FGf6H8NiDYeGMA8Cps5ZXeGsAjqJTV62HywuoBuEPXB9V4uGnJdhkCRL1OsgIKrVQLlAZ1cBpL5MjBohQth6RwtjIz8%2FrTaFlHReWCN2TReDgN3%2BqvsUWUlaCQb0Yifhvi3d8OFR42JxMXy1%2F4bEakXfyAuEVcqgYUfxRy%2B%2F2Gy4cgkaSjxIfapDNx6GXX%2B0Zm98OCMi9frJDCWFTitRLnlw7GHONFq4Zb%2FOrk%2FF3oRJr997vCIkjLt0rxnDB%2F%2FBBfAnrfeYuEHxhoAcu%2BzZeEjtVhE1vXU%2FZMZhUyeklzrS%2FVWKhgVYdVlMMUnR%2B69LV5f%2FhcSwYMZp8Owed%2BDYdGX5F2f8mQyHa%2F9xtChgTLTnmzg%2FBeB1oJW9RQiMoTGWvNM5mCMqGiOgeIWOq1FVUvcnVa%2FrohcvfY65e9it3032KuvsKmegYlw5wgTHp0yfD4R%2BOj7tnbJq78EPGBCacM2HIOwXmCASBs4wOMs4B27fU%2BT%2B5utTJhf4lUxUVzS%2FrHO%2BHTgjFRZnqGA4dSgHJ1BH0wgo7cOVPEekwHL1dBnpRuQnfKcevHyyuWHzkw8cx8n112CCBTX9pp%2FrNu4mhkQJ6k8UOsJ2LvBaX91KFdSA14qHvfu6fGBD%2FnBQQbZIU%2Fr65D2YQ0w%2BEZgyydbEC%2FgIlZQ%2BgAPESKYfWXv%2BGCtzBFjoXF%2F5WqCIIBDQR%2FGmZ9D7Yqh9pzeN98BrUVxiJPo5zXjbHu0xnr3LGXMlBMxJu%2FVcWXQAdRKaY5gofbuUj5hphIybaewm9l7u13751pAPesPhQuUZulGfozrH0NZmb5lY1qosqfjZcaDE8mkpCvvr3wjP4zK24Ga7pfUvw46X7KCAp85CfN9Ohdh5qgJP0%2Fmlf0ojkrswK%2BnatY0wE%2BJD0sBRsSGznZrjXXGzG8atV%2B%2F9%2BinL9E6vXUgr%2FVqy%2BK%2Fb%2FZN3RPJW%2FC%2FZDsYrT48Ol8ZfjstmtEl1D1BsCaMGGPgq68Q1A%2FCdYJWQSm2Bw0ha%2F39BLAu%2Fi%2BlrIDr0wtIL083w4av6oGgw%2B3P%2BTz%2Fz18blvRfqFyysKhTMpsNTiysY67%2BZZkmtR8LRvHqx8cooIRp2rc%2BOtHhxyf29KCTQ1CFgeCy0W4IL295Xt1m5dN%2B%2FRBpP77tTEMpvty9vCAMC9gESraN%2Br5%2BAm%2Fdfn3UKm3Ml%2BthAqHCsFZdRuF7Rluq8Nmrd6jmMvrdYyb7bdqwJegmsMeyechotXTttbEbrWoOb%2Bv%2F%2FQ4Txmfl%2BcgRmkCmKO%2BHwGOmc4cEOZMOZYMRnelwxx9xb8hwh3bPh4wdxnaYK0tqT7IfjWGAgdOjAm%2FB7BS05fZMCYPGBM1bkjRhKZCI7IQY3bkQ76oQTZgt6%2FlRHBHKuzBCJFxOgnlJRcmHck%2B7wwkcX1F9olOcSilTXiKLFwHsHN9LrnRW9qu16TUQZV2CpFJWuovPmUkeVHJ5h8SjbhfC3DEmJB2P84u6DDB%2BnW4wVdJDbe0HdG1wDNgu4IRD%2BD91HpSqDpg1iC9qobupj%2BNiV76t%2FspmXvsVsdrPik59onqITZ1yczgKD5YrdOyy1B6OVfbjh6WHnuevjpB6andV3lnv9M5F%2BfV%2BpL6BhhMpPMv1FSmO7Mxm%2BUWRWn3JCD2UW0bGOe4LiDg0J%2BzH%2FZdYUva3Z0tvDIvSe0q2CAzYDlRFJ%2BBpDDsoYsY64qrLXlp%2Bo99bVKnOaTk%2B2IpKhHS4QfZU4auTLcvsgJarOYYFjPKU2RROb9QSxA3h%2Fc8bNX1nnBPEMZWWUvwVEanmgp4ngnhzjL%2B87Gc2UmZkx8eacTw2Ur7wpFxfB2w2kyI2SzFPEnHZl910cYdt%2BXJsy5bJKt9fj4zGb8etxej%2BLBR1Uvf16FixWXDMI%2BM5dUE34lWrP%2BSvWKr7WtXZCBrFCmv%2F2wUk8XczHpq2SZeR7TWnVfh7cfMZfeOslvt9F8Z5XZ4pfffGnH2KSSxv%2BqPa%2BREIWJ49GFEiRMRvHWlGmTevUNy6rd1QjMNxvGbTHkF9pe4JrabpvaT1%2BGuaVfkrLDuEL3vdZIGylfdIzZPnb3RZjJ5S6eGJIbUJtAbr51cj8no1rkMeRp8b9vhLBh5MJOP%2B6m3b%2BT35BmzSkQyq3k%2FpJCMIRdY%2B%2FqSnUQmLsGWSPG2Q%2Fp%2FIsWvOxfCR7gdVMDuvdaWXxr3xlppSYFBqs5Y1nwoNS%2FoKXdoHnyZLb5fxRA8KvPvwlGEq6U33FdlwViFktnLPIhkUWooUoI6eHXYsx%2B11J1NmdDcruX0WKptcz4nXupatwSmc8Ny5d3qC672d793k9n9fUNXbI%2BNfMICcanU22%2BT%2BW%2FP18KU%2Bh%2F0CWJcTtTaitve%2FR4v6J86%2BQkPo%2FxkNGZ4TNS6kTf%2BSC732Fqhp5%2BfEJPQKnIYR9QkiiKS6Vd4VKGSgqNuN5%2FFN0fl4VGglEExVnyOPpaizCgfZaxZcEslfDF3HgBoWAZOHI84WAZYBnRErqnQXfFL37Sy%2FXLlpJvdrFRPn%2F29V4axshfD8M7P37nt9RFfvXrUn1hn2iSu94NBAIiAlCBPph72SZUXa419%2FLgAAEF1BmhuG6gVyX8T%2F9%2FJ%2BhdfrF%2F1%2FX3d3clr1X32rJaEVZ1YzL3u%2B%2B1euIr%2B%2BZFiu1er14QC4YFYzV1o1y639aCGU6rWT7B%2FWNCAsEesCUzh%2BG1vJRe8EgjgJAUDAzBOHqFWorEOPwon4IsyCFI9BCg%2BJMOBGCQI4W7ZLsa%2Fuje64mvQ169XJbviVaT17nVz7XKql73MMMy6b9wWQhC%2FX%2BLxcXUXFzIU%2BUUFM1DbmwL0Ma0aw7DYXl7sdheXjpHnpAgmnzYpeLjiuwvL3%2B2ZInHJ5giFggEBUgdKN4s0fDjVpRlsvEnxPRfxhb360hVnUpxS0KkooogPwYN6p4kcK5bYHXXKoh1ram2v5KcROJKNyZ7Vx6cyQ%2Fmk6ob1WencuLTCD2ODZUiNSSI6n5hTL9stfMgu7%2FLrcqqun7ul1DbY5BdFGLgKLFdhtEeFVTYjx9ffxNcRe6E92vdr133JRUvLVr1V%2FDGp%2FL%2BgReGRUXqEAkKQICUhUwWQK59sGQOX4QRIH6GqqBjy%2BPtBzbwksTIGE0rlnCZ58yOkZ5fg%2BKJxQLgvTsTpNW4QAEI5wQACO95QVLr5UnLvzOuwmq1XOpa4qg2vH%2F9%2BkbAOuBCM0pa%2FN%2FgvICYh4Gh3kzfd3gXYL97iGhaYRGihAk6Q8c75OBNO8AzAWHFizB9YjDxLCS5OL8IeD34RuWuJ5V6QctrvnXqonpL31sFmQZA7NfeCMEKYZkyp4DnF4AHwffyf1%2F5PiTA6dj737qxV99yfVSsTUQuUnrl9LUl%2FJd7yoooFQQjZzfHhf5bgb0NimI79TjWbUQUEHyh%2FBZpYCAW1vvxeCg6ujZbQk%2BkXUFckasHxs5qmndvgKxkEX66u5%2B%2B1%2Bdrl%2BrP1fgT5PXCW1Y7ktWonl%2FrFwfftCybhndGB2a1cCUAB1GmpPTwUcvpDXW3N5fnycUKFXIlZzs1yf1ELt91lE8slof3ck6u61r9eq1b9e%2FXquW%2Bfwv8cguIu7cGpYNA89eMd8vg1CgIQsEA2gQjTO7WPKm3SgETwFsJzBE5o2M8IagBqFZ2RyE40QBiQUmzPTtOO0fl93XCg1jkkOoZtloh%2Bw60TLHIz9Tkx15r9qVoKYvkO1TRhBCO%2Bbem4QBNQoxHb9166996WHc34adxfWtBzTafuETNOrzxrFAqM1GvQTL%2BSeSCvTvOQaijPojNhdMt4zV6vklR9fLNzfNE%2Bj9vJcxOEJ3rVqVAgJxpkCPZeohT1cCXCmiVRkJgULYb0w8DFcZ4xsrFJj0GNCr9qDd44O53rf0ZpnRlocF8O2axNg45M0pxfw%2BlD1d80HjAZ4RRp0X4kAAIDme8hgBUbMNhLgQAMDMs%2FiwAhFqAtJbPMmJu5KAwBp4GAwg2GTEQQGlb1uYAfiXYQhRv9BQTuw%2FO85xhL8CHiJoU%2F0kZqcI36glKYPAkOu%2BOCm0yBf2T0dfBCIJPnU4vbbiI%2Fzy%2BTEoEkenx9g6DZcTx%2FzJvVQK7Kw3G2gxuaXCXyo5NDm539gg50phnRg7WgmZdBs%2FpGBX%2FHKCHKSOMVfovbQ1u%2Fm7qmRur16%2BJU90%2BT4%2F%2F1zhYCwCPgIYIr2v%2FAnOng2tCzcLJk4oywYQIaa9o6BT3eUYIJexVPCo5V9A%2BH4MJwQFvIGkOcMBW8Eja88f8Pb4ZqwpKeyN76E2s1mXyIGraAvQ8qcx4Ty4X%2BANQMGpGD8PfoEata3bCmpbl9JOQn6FM6MddLnuDNMRb%2BvjOHziWM5GCaKssU07RsSDVSZ9C5p2u9Uzlx%2FJ10CzggNo4Zl%2BCB%2BejWeSyBb%2BNgvIWzl%2B3XGyHbucQzZus8IsK0%2BTB4HvIfTHN46CdThyODXP7lwnx0uFtEKVj8EZEDWFKY1vyTcGMZMIbPDRxkLCHPsvjGTTb%2FqbwqRfYnOMjHoc1GjOr%2Fk%2FV%2FDNHePdSDM6jXP75%2B%2B%2B0Viq%2F11WLfa136VvwFKP8DyP3kQIaHZYhSGPCoRMR36xEJBIaJWLrFc5BFDDgWEYvYLjMxG1r3xjbO56nj941JjYoywHTLwdeasY2ITWjg072A8htdROn%2Fzi%2Bj9z%2F17jaAwwiyA28NxBVhA1YLHWlw9kA7ceNoQQjVmecRsslQLRGwwaqnOzHRhDPuMelr%2BHSYzE%2FsBEugY0RrQgkC1j24n2i%2Fk%2FCP3BSUhYwxJFUYsI7mJSP7d5%2FwoSkscuVnd%2BZPfspWqeX0%2BnDHTdxqlTZ2LEZ8sv79wtomYaqKxiKVJnbGTN6qRsZ7CG5v%2B%2F1fU2VhUwTdelmIuK2iFXUvoIRI9dpB3BEPB1W27yoHxlaXU0ziAt82INdJQrhWwaBnMqHxGSI4uo99QF7Vx%2FkIR2d%2FmQrjjNc1fSvrbPCvcSHWjcSSl9hB1Oj5lOdfOvg%2BhXq9%2Br91a%2F7r17070mRa71icQhQFm6V9jQj6iSigmmdIqvDmb7XxpQmr9b%2BmyAp7477z4yCixLsDM5VUvnuh7m1Q8ThgOkSnHhxQh0DNFjXv1b6GOG7CkRDC9D%2BN5JOYaCL0Q4BOS%2FjoID2KMfQv%2FS1hupE7kV8f4KwfSiuafRlP%2F7tG9QmW7yoga2gDH7OPOSf13TQRsdZXSlEpuW8g3Ma7vL8jfjb3axyy2i%2BdINjW9Ss076np8JXdA6FYv%2BGPP5zdtcyseaP%2BLh1%2B4DJmkal3Kvd73Iwxqowhlx3moa8GOz2MJjVyvyQt42WZ4NZQOivIrDI8bhvmdf65%2FZ6%2BskKFcRdeis9Ergg693%2FX5xi2cJmL9f0siIHTjwsjLwGffQ2O1oFh%2BZBdV3f%2BKjn%2Baervgs5fREh8MShpE4YkI%2B6wUMS0GcTnVHpBwzVupn35EBYZkr%2BTy%2BylDZXd3FuG0YQXs%2FrjvI505PYpdcO8uWyp1HBDd2Pxs31fuzXoRTQvNJ236ho%2BZmOoFuzf8%2Brw8bKQT4Nx7MexjdLDs0xWqsCMVIppZn1YyUrW8n542iggjqvQ%2BdJaT3y%2FDjCEcO%2B0wWVLt6xvAGPiP1cXwtehv4zfGBimrDe1KiJ5HyJcJW4UMFSmHkYJTkPILZBX9RNEr9IP%2BAdKhfFRl%2BpLCK86RhcNPxsvaw%2FL8bG%2FMxr44h%2F%2Fnpl%2FGX9VlDdc1V%2FDUVq1MTPT9%2FLTcWfx%2Ffkomfaur8nk9dvX8PwxJt2hgJg%2BJ4sUmB8WVnLsEJyROCWZEpLIP9uIm4Uh5ejXqNKX4wMVyAgStD9wIVEtcVqsdjQwGoHTAGrBARoXA9DWPVcmVwl22BdK%2Bsn3L2yhuODR4BiHF4eWZ%2BCucxD6ZswXDiQj2Ps%2BaOX7%2Bhppv8O5Ao3M0cL5wf%2FB%2FwWdwKdMZLsyVZjH9Eqcn0Cnd4jHG6uEgpyIsgw6PXfYXGPUZ1LjdLQqZrPCd8kJISe2L4tho4qyenK5FswyjOnnV9MMx%2FKF1Fv07t%2FupQYCbtoCKDAHqR9%2BEtAoGMiR%2F7BZ8Jdu%2FNcAYxZySdb5RBx3LMunjw%2BwiKRxJvqQevGwkyA0R3wkZd%2F7%2FL%2BTdgqEu7w4nm0PeMh2xu9sbKPBfO5XrI7NOXgiIOgP75%2FbCrXxPqG%2Bf%2FRaQ%2FX0cyZaE4mX7dtdgo7ve8Xn%2BScrtqSnye7X4JOel%2Ff7DRgY4PIR1bKvJEnC2rb4J6TnFUNv96WGsRm0Wv%2FnFBw9%2FF2Bxmqbst7dD8LoOA7tITyoRw7g%3D&media_id=1254206535166763008&segment_index=13" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:32:01 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:32:01 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_Y+BRyulOrte\/ZJqLMDHlcA==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:01 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786112115560834; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:01 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "0a0021663ac5c2251e136bf2d5052f63", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19939", - "x-rate-limit-reset": "1587864356", - "x-response-time": "36", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "00dfae45007fa59a", - "x-tsa-request-body-time": "104", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"kOcvIIn%2BXFL2O7DNBFmfoPjiSXc%3D\"", - "Expect": null - }, - "body": "command=APPEND&media_data=gL%2BJLi7Kd5P7lLaBJg7qcpKvgllWOHNhI0vZ8t%2B4Z8IyVnu3Qiw%2F56tO2lAxF%2B96ah670Qjok%2FLr5QmTgH1SS45O30HCVfbJgnpMSvOH7b2SBhIcZ0PqRPqXFmw2pDKMGuWSeWq%2B98bwbY10MZB4DDD7TFCczIS3yfmhBsAhBQTnNbYhd3zZIxJotF85MvfePU4Bptrr%2Bt0PCIrwJzT1h7EvqKubjEOSvrHD5XAdbW9BSnrAimr%2BDTroM4WB%2FgmnIeVMYxUqAUS0xb4nVCY0%2F%2BDlYY1pzDS%2FQ00FKyvTUPrL8k31Jzb%2F6GcIc9HRtP4osHaoZLMDI5XdaWHy88kMIGQzMyyps%2BlI%2FpthxhWIaKUPGDb7KV7U1y8vl85N7WzZadGpu5cyk6SWwnySaQRqcnuQ13heeI68yn2j6NggQJm8dh%2F5hiMCQWmepFg6zCA1%2FG0Lc0DkUErYEDudQ00unFREr1UXxo2xTByycP2xsQSgrZ%2FBBbAg7lvb6NpHPZYRYQLMepwx31DM9uB4Zlq0jPsv1Tph3qRjHO9ItLaf7%2Bo3GR07QR4L1XmvHUa4StPcuP9wT7YreW%2FD1DdqDK9rh3ff6X4i8rG38bpewjKtDzsXcuWkUzv1BIJtNI0uT59uwubDE3dY%2F%2F7wwwzBwf1jBlL4RsdWCUYvdwu1rfr8guhndSvqz3t2eUwzxoZXcq0gPt6pNXYyIgPQWeShH2Nn%2FhCMUL1t0M8uFx66nujqPeDfQ3cWxn2X%2BUIF4aU%2BEOGpf5wfw1Ip7gr8SCYtNUdpiM3WsA6v519l9FZbxhCWkNnag2ly%2BkMVM%2Fnvp%2BgdaFpf2%2FwxVjw1PXPpd%2BtwQiTi0zxyadv1%2BLKqw41pViUmf2iS6IV6u5eX8Jmd8s%2FJ%2B%2B%2BLvcbJEIrD2Pl%2FbrBH2w4gNsGDFrvGlAmfeaE7v0rYi%2B2POkRHS9GIfqcsVdDCk1%2BNvlw9H3HkIO1i7r1pR%2BiLzMwZ361%2FBIVGu73BEYcZOAA9IPUnLTJ7v6grtPkwJHuvvz1pdxZHLnu924LxdsT9smaurNH%2FYZIB3iwsGN6j5nuoj%2FkgkwKPXJ99aZUETWEes4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SYSBMKDYMBYUhYcBZiBYKBYhBQRBUJhdmcc4ulVeRJKvF03dXjhKk4G09T%2FHP0fwv4v8P9%2F%2B6883R%2F2zl%2BAxJdGr4ePj4UcvxnLKTzkNr%2BW%2BWb2538%2Bqr%2F2cFXfN0qlsbijTbtMBx0UhyP8YE5pX33IQW1N4PXEx4tpotmrNTy1UFcRgZ1Jqhcuy3jG8aHGKHra2YuU%2FvhWrftHLf66hV5n2h7OJ33KF824Af1%2B37uU23%2ByO5B55h0Z0AA3%2BeQAt8cJSyyn0V61qoo30AAPyVdlji99BfPnQIIyRaQMa4fxGRaNhemu5O1UU1jqnvUmGOJ4KwRGoNRqokOPVf%2B7CDgASQUjCgVCwUCxoCwYCxICykCwYCwyKYXGI8UuqvmNU1lSVraomLkR5H8P5t8R8ufH6N%2Bn0YfcukV7vK3XNgwfJ%2Fl8dzpmkvN7Krun%2BU03PukrfZXRrhL49BHm3rZafp44ThhLu6pX07BTQwbBtoencVTjRTZZsEpFKynfadEoW%2FUZTdYJIIwsbsPOWzpVObwkIA9VFLy2htrspWhTJfF%2FwH4YB%2BdU6k4TjOqDJTNiNLfgpA7hJObHqhjEp5uoFG2cQsqk43d%2F%2BbqA56iULe%2FytMfetv%2Fpwkp%2BkAZGBk5b5ga9Z7TNuDJ3OGMy7ZgDHJlASlmWZTZelyk%2BHXEDgEiFJAsMwsKAuFhQNgwFhoFioFgwFhIKAsFwkEwkERGFSHLGqrJSSFWiqvdXWpdJwPn76j%2FHBv47d26zDoPuVT1U1X%2FjVUkj1SDfk6bSxpEufz0C6VCN1H4Wd2qzHKfXHO7Lho35RxCXqrCWq7DDo73Ft78MTJsLDTYoz15DrcAue4c7e%2BQflOJ5fhZmFEA30p%2BNh5qKWlAYgCnExhVuDg1c1RxfP2Sgl51lhYZ%2B00Aieu9bdoS%2BPIe8%2BpA333r%2BbfwsdVvIEugvucmjeFAIngoFe9Mw5eXXVRPNPy%2Fol1WXCTWMXnESt5akC76a77h7dJQJvvSSroHyx8FUGzb2dfxfX7QOAAADF9BmhwHCgV30hbF3331YjdXdIr%2F%2F75oTWKf1rXWr%2FG%2FIru%2Fv%2F%2F6V3xnclq6hnST2tjuwgoYZYyHeZENLpm2GHHWP%2Ftt7bfYS1Lf6OmiQSeFFcuAxBAMDM5wndzB6fTESjHFXB%2F4nWbzf6iIcSD%2B%2BPNAI946mEFrgoY0we9Bu8V%2FFcoOrQY%2Fncdf4FocGzkhbNQDWwlpc5%2Fif333xUg6fGUO227WOmvvHKm362mqp%2BJDYoZzZWt6PQ%2B2sqDGyTxos0nis2KWcvmRTCTUNuvq0zZ8QHBAcSNY8WDxZ06UkqQyY6mq2NkGYYXXd2RsY6kosEksUCb3FgklhYJJaT7nYRoGMIknPS2blZMh5YO%2BG06gmstNmicYA65z85pWGmWQxv24krqaWPJ9Mq%2BTcqwosoHB6B9G3njrrDEbucdbdQFYFZgI40%2FVFoTJGyzEpH1MBR7hSL%2Fn0H%2BcIFHYIPYsZSaqO6ycq%2BvNX98epPr1eXpbNIKzMJiFGXgW33sAD1rbAVe%2BMgHLweQ3y0G%2FBJkQVN5UBneUDetilu%2BtC%2Bx2cgyKqo2rXL9WJL7u%2B1ylfl%2BRkFKKai8IrxzsL8IIjcXt%2FzsPZlVHQuVgCoOCNxyAF4UWjgc5AYHP5tGMeTzhICThggQG2fujRpJFN6Li64wgCxS6abfHbmE6i8o1jkzdLdRlV9%2FSAygQFI9RPatxDsUvgaQgBpECv4FkYeDook%2F3eP2h7VoQvdzVr7tYv1arVh4teq1Yk9X7q%2B1lUC3k8%2F%2F9e%2FWufQQGhhWT1AfEQTA4TiFhh2v%2BX5Avhv8CYNDNVwoSECQ1KDYCzB8SH4KIDSYa7%2Bf9C4vm79rnmtUvpIjRe66r1y%2BIlJ%2BnGXiQeDR0dixgka2Db6U2SPkYAqoB8YAdAlHmXAuLwCaTx1mAUmcVTzC1R5rTmz5saLL7SXmXuRkE52AIl60M3MVxvhlj1xE5nm2XyoKGfGpqQqF0zwZ1hoFWH2XR32bpfybwjQ%2BX65VeOXFjvjSXdUtq1esX69XMr1dYLJjFxI5J5L5S4bQfg0GogkYMgwVSNjRMHgGBNUyAAifTGsDW9aF%2BYmC5unuP%2FJ5ff1oI9f12vdr7uX1S1dc36v%2BqcfEqxfq06woKcaO437H2j1Bj5RUkCdyPILbrABlPeWYIdamgH3m6Y4k%2FHC5jEUpMoOVw8E9PZvo%2FjN5AdQHQwAxlZsk1WxXy03t9sV385gftY7zs%2FGML%2BGOCXdmGyHLY4S4BnfIxX4nUGfr8QgiYpEtNEc0rMeGm7Bo7qdJJYK4LTmge6eHu9NLFhQ7qY4oGMMdfVd%2BhMr9erk8Je6w1VpYlXqRqHL79Wv1f9WrwSb2bH4XJtDTLwl0NiunLL5f3dQxh5ABSxslPMbeRKz19QO63%2FqCbVeo%2Fjd%2BCoQzd6mSFtM44Dy8YxzpS80Kj5494%2BEBKNOleVUf99YgQ%2BlOgx1k%2Bx3zYcv%2F4e6OGP0VB2y4%2B1Xw5Jo%2FW%2BEI7kHoNb6mDfyYq4WSr8t0G2J0fvs3xFXN%2BaC%2Fnld2DYNR2X7f8QWtUcqV6xV69%2BsX6xSCieiawEUG1rT%2Bn%2Fnzflk3vCBLxXxlXCgrZIK5e39cBGgNMB3DDKpcOcVThwePHacPDsBKHYSnADywAY7aSsr4dKXHHgeBfg9h6NowOkmMO41jvyp0P1RAjaj0nuoTnqn80FnF3bwtmZf%2BsnhDQVYqF%2F8b1dx2G3HdB3j29AmSBCdd6nICA1crBBOgTMdN94QD8LHj1y0qb5%2F%2BqX8%2B6imTJfy%2Be%2FggJy6hx%2BnRzsr7OMDamX9%2BQsMdH728XgN2xhmMfqdhJvXJhvsYbJtLjbfV%2F0XX7JjHtZN3%2Bi1VxDsSDsE8XVcmX7wEyE98kTvDwwDsNy%2FCMSDBSfhQUXnA82njhwADywACsyEHAkLAJT1C7TYjn0JljUyrnCt%2BFZYABeDZB0PQDVv6OYIg%2BVxXe8nwcUW0DxV1QvjhdG%2BPiAooUO%2B42vXqCqwMBSU0YiawOH39B0BjOWX4sjkL9gjbYfwqXLTGYT1GiJATRh%2FrrROy%2F%2FMi7Zf39Wfjpu56t69VnfJ%2F3nGCXe98QaGv3ien8EOZkv5YIFn4JbB2jAgC08SBua9%2FyctL9Hy%2FXqgh4VkXEfhnXq%2B5QXAg3xGYRqqfQdCO8BJwN4b%2FGwUEfVigCcie4XZKwQhmg0u6o5F2Go8kJhCkP6MV%2B%2FoTBHmfJA%2FYSwUOxJr8aVvYHoGHEM60Bz3x2TwWmi0eKfL7XeJuGCTdq2RA3b8J4vo98%2F5rmZsf3GDG42k9w2Xl6ZfiVK30358LMT%2BspqaaCgItUNPqhavHBDe%2BGhUNp%2FiYIdfpxofXxZ29tN%2F4JqAofRIbe%2Fh%2BC4xQwPGAUWVeq8NFdA3dQjwb%2B2mv%2BoKy4%2FeqqH2ev%2F8EhT4ZqsEB78MdVvHUwvutn89Uz%2F%2F5icnzRS6pdQlAd%2F7%2BGeN%2FWL8N0GPo%2BqSYzN%2F%2FC970DkEinJz6WGW7PgjpV7l6%2FPXFv%2B5MJfYmW69H6S8nt1eFd7uUMBc56x3tX3TEGPlSfKUwQDHDZ%2FBIVDHRwYbGT59X%2FRLvw2UqVDq77DYhzqa8g5Dl9N5Du%2BvBQJJEoQDzCUP3dcpvfD88HewmW0TlgF4tFZZTGg7V%2FPfpBlFRuU%2F8LCuPCA4IegwFferFlWqz%2F%2FR3H18BHF1VXo%2Ffr1eLvvu68JUiZcVum68Ehp0t3C89fQHMoKsvRe%2FJ46g%2BCax6N2Njfr8GHGh%2B97r627C%2F1PfhewN21IIDpv5YjwGxiQvfggMOmOASlIrfIiPfDwAXDrZcPKolSrSVWMpmqYoxVjWq2ss7%2FeRnuAJdw3%2BQvg%2B2jOT63VNjOHxoRRqFe4NU3JRHT%2FRrHPDLj3bk1KpxISCgjiH1dRxgRXo4cAI0yM%2FAVCD6c0ype1HUXmd9obaSOiVOe1eam31xlk%2FbsQF0JHl5ReosPcsrmsJUqz1DX5fBRleSY4oJDm7cXfi6HHemKrD5Wmb8EYvCUJwGVNen4ubz1bNf69E6%2FLoN3Xr4vzlZPQ8IakykxjYGvgmpOK5DLkNuIYvwYX2fAS75eeRU%2Fw5Ll%2BFsqKxpr9aNlHCF%2F5yL%2BOXMKrwQi93HbS%2BHjbM7GX5eYZexvy%2B2tco0RVABFn0jDgdfELaAXOEddAaBsr7Vdni8t%2BjDK%2BsecpyX5a2a%2B4wkyKJTk0xybpra8plSzhuoAtcaFEHmhwLnL9urS%2FJN%2F2M7r4DvpTdNLDXS9WLEM2Q63jwjX5fj9brc973o7Y4TBIU%2Bi5tXD9mb3GAeseSH3vTcaQtqBrrotGScr4jvplgXhFyuwgABtoTb32719mbV63cFEVlyfC5fh8y8sN8UYrX9M289Cyqy%2F9a9b%2F8TVv11dotV6sqcgh3sK7f8Lwyi%2FNeyjk72YZksJqxBP%2BaedHfhwtzfSH7IZLCwT%2BPyw57fZ3%2Fcze6X9PfDJIr1%2BVMP0XfmPda8E5HZpLAJSs2JPj1N9CzShlBQX8EJ1IhqilvMOjkUMu8XDBj%2B8JRqn93XQvIIoNPuUt9p2b4q1sv4ggt9X9DttRkZw57ggaPTRzOuEzsF3BMAxKHYQ0z28RGcQ4XD4K25uwtUYanuCGjMdS8twpd7pJO4hxuUx3zhV9XfSUSQeKPLbZQnVLbvWlQ%2BT4jU4ngceZn7Qvwe%2BJ%2Be9Kb%2FVRJQEvX6YhwuNkQRZbtgtagD%2F0EWfMiyHmko8e7hR0%2BhL%2FrLqvI6j1f25PDhpc1bYybQv%2BGy0d9WanVZLdhJ%2FVki%2FUjX4YJk%2BQldUKH1K%2Fp57iCBlncf3A7POtzxHE40n4wkL1ra2%2B4qLjsQuocZb1utS7z1%2FJZddZfik3aH9p24G%2FGWwszxL8vrawhy42c0JhysiUvI5wqvIdPOJhQ0zFbzd1LGFAH2cOCvLXCYoNh6Fyrg%2FO5kO1IETrmICCY0oAjLFhF0iKuTcZnDCFXR%2Bh71ffx%2FaK0nrh2uu%2FwQmaPnF%2B6SS5PPr3y5XktW%2F2Tn%2Fw0eNCLoUvkpTv%2FBV4NdWJ2X91%2FxgqB%2Bl5TLC8GqZWXVQfuXzVE3CXENOFGw7L80FfDfqssOBc4qPl4F8MhQh8N%2BjkODUOMDX7LCA6muctAokCxyjF5zXDAOoKhENolC%2B7Bryr0z%2Bk9BdvVFqpZF5x8pf%2F69XV5CbuWLqy9VfF5PT8En8Rxhr2RKQeX6BIMFBVhkeEG2wefCxgGq2bFnJogcl8DQGMzzC1X4JlgAADC1BmhyHKgV3dehPV69dqZMRzXiFcsq99cV8s9ov3wivfku%2BSfFfc91dYGEXXgkJFcQ8A7N%2FkLYzcV33HWorLmFFYbaYqgMCcGA4SAo3wqDRr1dqjnFQzlCnfNj51QYq6DtRaAWC7obrZWhA0h3phoXgQA5Uo2ocR3LBg%2FPske4CuD3gaAtVzT2OjbGO36uWRvqxV%2Fr1etVa9V7sGf4LwUDEistuwR9lZgKHBeCMFfLqQQv5nbqDvgDS4eBfIjsSnUFwmGILKKx6FWPIQaqexftC1L5WMzIanY1CgI39Q7YSKn3bQZfhmZObJVrI0UdA7UDvNQMeB2YiY8Nn6zG4E0mSRvwcL8dMDTJjjC78RqK92MxkOU1kHeVJmBq6oM721b29agQoRydMnaVla%2BemT2mH5wNawMIVA8kDvG820wFH1cLtS2vU2VBAq7hBZmDilSgAPXXcEbQQxBbtt5PEARCBFgnvBRlks3B9pY42uwCwASAxLETw9%2B4rzQEf1NX5xIS0QVbwlEXbwiI%2B2cdLyv17tZd47lpvV6qV5cFNe8SUSOFFneKs76ar8FWtWj4squYChwP5grqraaxYxHemLWPqWqXwMuMkAI4OC%2FqsB%2BSmvA3wO14M8v8GtL5oHHiGoBQ%2Bnh3L77jPAWrffL3eRgwSGukCEqxfBMvxN5rVVMcAQQ92v2gM8B89xkDVdDfUyB9y5nAYYYLgCGlSG8d%2BX4rUKHcGglUS6MHxjBHRpCOl0NKqKyywRVJy03wkSATtaGbqwkCYaDk3FLYVRNiLZgTUvE1Dd0n%2F0X5PxPxP6F9dq%2Ffasd%2FN%2Bvd3RE9%2FE%2BT4WDHQpWAtgwKCFUNa1qEhBxNaqqquAJ8D7tD8fQkeJSOgZUsky%2FH5a%2BX5J5%2FV3LL69J6xfr13Xr3uvV69l8fPNCcYOgkI4WdFdd8DveC3NO3y8hAVmlNpYNQFYiqpSP6JrDYxVY5DWtpoOmBgNGyx3UBwaeErmrbh405NBhe045KOY47QaCO%2FYVwwm003enV3%2Bh%2Fd1SL3ffRClXEerSer1d2r117rl4cEGNu9e9Gh%2FBDxdRXQwd7WddEHioBIPQ%2F3SU25uacp5kFf3GVU9JszJlhLExzK%2BnRNt4hOCnua5PQR79dfKvcT8vqr4pb9Wv1qTRlf5svhoRr%2FjZgwEInDimfTQDZHpF6Bi4geu8yPryRpFMjD7i%2F40hlGIAkX04EBAcPPD38VVhWexnf%2F18u%2BoZISlqev%2FeXzTpIrGE0isjszwtawHqzWwt%2Fld%2BomOtB8ltw3qwTmndxe0J1JfsT3W3fFrXrXq0lq%2Fd38X2tfnudIaZ%2F9Ec7N52PhefLHJ%2Bs8Dq%2F5fX8NCGMR5vyqPI%2F%2Fw0LYMPZbr9NIdl964LSjA9%2FYW71rXCog3NTLZhiGMSVRmpLodYj2%2F7Y%2FjsckYNQP7Fnw22CDTLKy5fNVMsb4aMPTzsM5dtrEwS31aZZEy3D7fiVS%2FBnsfOLsGbM2GSlLsHvgn6MFuFIt0ttt27xNqP6FozClMm3D2he%2FcuOojfqZO1qfVetYCoCACCHCyO82CjFGO2VTDf7y%2BSTSfSZhRU58Zw9uNw4ec4BhyA%2BPdvpzedV6roh5tcrb7hlWxaFHmpplpb44XiHNAYcLDhICbNV0NvYXoBsxsSHQGwo6CFVA0a89nug2xwXOyWaKQMDJ791hGwGw7OxHzj87Nv4ISm%2FY3rwXzF2vHSJUw%2FYgfdqGX96wmQbZKSJlWIlKRn758LS3EwxhLMrov7Rglzr%2Baidcjgj8K4iLT4go2yfndQOMvaV6VMjSCfM4zL9fMCWPt68uGA4Dtriv6qlL7%2F9otSNwKYY1gPECRAjiyKuov3gFeA9gN4GZCVVbwF6EgEyCXNiyIzeT3SMsf6bvFZcstxuXSAasCdh2L4PeA88aPcIR3Im4oGpH4OvB14usCQdU8%2FDjj%2F4VKOgAHgUEwDWeDvGuBVzZdfxlAd%2F%2Bcpb%2FoXWT7%2F%2FzEfC6MFd95PP%2BgXF6b0jdr062OjhxaMFQmah%2FJe0exnU39N1ZINXT35I7YVlntK2l9v4KYZiwS4YcAdq2RX6OBA4yWH%2BGwrUnG2SlrWthXlbZA7XEo8nOGOoN8tqX%2F7RXqQz5peJWvpa%2FXK70f4EMgsQqquq3kIBXPrBnFRBF3d3euGYgKbisVisViu8Vuov06%2BCuHFbzQBL8yEmB%2FmeA4fv2q7KUi6Cg0%2Fjy2Mpj8dOEFva8jy%2F%2FYvQOH3Jvf8FYm98nvpkL8ERnffJ%2BV7hem4P%2BcDgL%2Bg4AcoywGduPIa92%2F2EjbuK4rf4oqs%2Fy%2F5Oan692LLcuXnx%2B%2FEm7tbMRy0tfE%2BWh89S3%2Bi9iurWvifbXr5e%2Fg68DYFCYlzr3ZtVvAQA%3D&media_id=1254206535166763008&segment_index=14" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:32:01 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:32:01 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_cXKictub\/RibUPq7rcfRCA==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:01 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786112166875292; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:01 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "82f6b441261c0d2d4bdd3c7eb93337e6", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19938", - "x-rate-limit-reset": "1587864356", - "x-response-time": "33", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "0094c20b0055b7f5", - "x-tsa-request-body-time": "96", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"fvbzIXFf4LjACiFxQjNff3sJN1c%3D\"", - "Expect": null - }, - "body": "command=APPEND&media_data=8QR3xLglz%2BE57nx0H%2FPyHZExAv4I5vobu68JWhuOSw%2FOw%2F8l3%2Fu73%2BGSvOkt9CRn2bvEEupMHfW8lT%2BP0jkqbCd7FQxXVhGrH43ZFpUE7uD%2BXOqrYkhs0%2Fcu%2B7rzeM6O79eknRffqdKv5V6SKvBSEP1YfYhZxSryfv9foS5Vslql9FyrrJ44Q%2BKEPqQxgZgwH29V%2FDgkN%2F3moAzPlni%2BWDEuX13wQeWlAhrrUA13uRGEui4WzVo6WOjX9fQbFQ1eJhgd5fc9f4NY3a8Epy5wid%2FTu%2F6tPJz%2Bisfgi6r1WCK1SwfholiGAQLX23p%2FBRj4mPw0hojC7FF%2FWtWforfiOW8smbGK6wT48aO7s7%2Fgm8%2Bd7wfqUGX76wTxp6JvdJ7f7sJkxoQg4QuFEYP%2BEdnHQmHuD8rpFb5QsBGTwF8FkfPGqBScNMy4ffgs7CwSogNHTFvmUjK4l%2FfTCJPDcpnbbw3KCuAkI0C1io%2FUvtojdjDAdrQ0x1jgYwTm8iyS7E2lbx5QcnK%2BAYbm8d%2FGspPI6JoSIGH2btTjUsyPO2M5b0z5vgeamtoyC9Ph%2FjXhJtzHuPci2GCq4%2BBUSRaQUtjyY%2F%2FF3lAb%2FOgyXH9wH6DYnBVR6tfZRrLI%2Fl49W616T16%2FBFLiX1%2BCGS0vLspHffrFfosf8McYKqAN34b9MdN38EnZGUS%2FBR03tXZrrKR7%2FhoX3dU82%2Ff0PNOvXGMNKwEcxrYuxBgoAzY4yEd1irfu2VKABnjQh6MIVPFQO%2Fws5P2Jfaj%2BgoYkTjg87%2BnJEzlNfUcxfaS7M3PH9AI5k3NV0j7QJ6NB5%2Fm7%2Fm6fYyfuyHOWKsj4DW16YWZbUYP1W0RjDuG3WYSwE%2BK%2FQsGiSu7o32UdiBjo4Fo5tgfWDFXZcfPj9kDslfA2s9nsNAYogVrTIguSkreu26IDAhR1t7MGNw9gtRObf9RnShRp%2F4Tmu965n1%2F7J3foTKTbk9kd%2F5o7ERf4Iu7Hr89caBoL0f%2FPZ%2BSK02%2FcxVZs%2F1Ln6JBv3ebOXy%2Fde3v%2FkOhPIL31BcRJAZaXcpuJIHUf3e7lSQLGO4%2BMQImYcM6b20%2Fn7szBfNVTXX%2BZnSHYipITBL%2FfOAMm0OMfX%2Fi%2FcO0wevTNgVFnxBBDDrUwey5dcnDgP8eRPcrj8J8Bscy8VXwhBBd8S4IGmD3gP8afi%2FtF2%2FcKZYb5elPcFHiAcLt9%2FYUOwYrVr8JxJFTXBt0WCGPq7UUQAgQgEKrHmJDgnhefA6pauUQL7juQnkpsvlEC%2B0aarETFaO01yeQ13rxR8qhskavZL7t%2FRL7%2FCvdEnJ3XZBxOp%2FqY17HfWTMxy%2FX%2FOFbOOFhxqUtLn1aJf93iJS4h2Z854yfjm0uT20mzVg4sT3dzjB5PR%2Fxdo1dzwfwnk%2B%2Byx8X4cftuNyfKyifl%2FXPH93bm6YrRyXfpBElVNxWf57jdctzYnusVUf9Ucpe8rqi2srtTxpi6VdvpzMzXQGa3RHNBYnzbeMW1BZv66wVG5jI7eOubmwBgCBCwyPizPeWYePjx5ecPJ6CbSN%2F9er17teryS0%2FwRERjj7%2BZXiampkvpdYc07TPwy45R0XgbXiJM%2Bf1iv6dS1qINu%2B7vJ74%2BIkibpXUucnmVlkngj8scsnqpLquYyew%2BNRGB9BSMJKPv1CvCj5xzHMne8n4bI3QKhBb2nGh86TKktl2yCb9BWpLr16uJjL9ahImTFfDHxnwpRWPIg0Qlp6qJd%2FrHseHxAQDo%2FVYPeAxvZQNZzWx1goCa6qtftgCCQHY7MP4DYqi%2FAAALPkGaHQdKBXJ6F93KM3f5peliuilevWKWq%2FWL6V6tYuf3%2FWOV64V61Ja19K9dqZr3U6fr14IIJPEPrWB0gXGGBCQrwvV5OHQaSxgvGOKtwbXUzQFFjrARhAbw%2BTMSLYjhfycVhwTzzMBkCgbpiTHUcKjDTr%2BFPRJ4%2BA%2BAMgC4HBs75cICnOECqNFsonrxDUmOvwWOuLr0WKUd04%2FWqFeOXYmv5lftertYrlWK4DmGdIEWCKiOZPcbgjlaDQi96VYt8Ve8C0JA2iQ73LpYAzwAcKv4q7UOPEoOKY10MISOCLXLLpy126TkcFXTGiH6gxmoXmgEdk8JKM0OZfA5nDcG5wWsbyHXQcMFW2%2FNU9wqpjga9KPAkEnLQDOhs1CRSt7pBSaccvgtEBMJBMVh%2Bs1g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FNuCsDaHQSAA6DwfKIZgF7WQWcYOJy5FaUnBUt2fPoe78bMMEhBcA4vim7FkzNQXjQS6jYQ80qTJbSVWeOr6L%2BEKngsIFFoUtBb4nKXQt%2Fbd72eze1gpjWpY7eVgMp8voGrjgOm%2FELVPvUFPdXVE1tIS%2BK%2F1ZLf6xV692i12r%2Bq365PMItQCJRz711ykYIiDKoAEb8OYb7yPBLJwFSwd35rf2yCCR%2FwQj1QJbj4grBmI0loUfPnwRCLCNTcy%2F74JaBLyys1oxbeOZJ3L5OuMsnh24toWbt0hkYQ2xeYsthKGzMu%2FBRMQUXHMdoLt2EUCy56JF1z5aLkTG3EoPx3zrLpFpkDVsknXTrCOJfE99V6FzXWiRfrv8TVFq9zq%2FcrQCAAhA9D1vvEoDQP8DIP1gKYUJmEbvcBpD4EoCKFBKqqi4uLi4uL1FxcSHAVUZHSz34sg9okgAr5g0Ubj6uwhDifZ5gQaCWkRGmY6DmM7BVnEWb0qB12KaTVw%2FkuJc6nGoID3OwTdUDWmoISRl%2B52Eyj5tL4Plx770WkX0bPl%2F6wVZplbTYOjGh4LrhDXqO%2FJzRSvyzkVqWBzX1vm5eFGV8OnH%2FJkfvJIxek%2Ftxg1boM2%2F8QRxbJaWiNmUKxsuEa0fdxdBjUnUpopqZ%2F%2FR6uepVe7Xu75apvzdVqGhUB%2Fg%2BISfYvWLGAXwcjzCjfxJwSHOXKw2xwoEsVz%2BGwmEhMxawahMLgsG1S8BVrnpAakCHtDwJAAcAitsCHAquNF6f1cBoGBCs6mLYCi0thNxtMuljHeCkEVh6KAAegQikAUw0kVc%2FsnopOMI2fYCAomGKAfqcxYWl8nt95BNCum8n3%2B43uEAYZwwGAVE44Ou8ImFIR9NpfOhHU3%2FChBgKUD2aEfTjtBDREiubneSoHg7wcyeD%2FsrtDWJ%2BESbvB%2F6ZwOFssAGIByT5rnUh%2Bb7MSVkzEewQzBgT5t%2Bipgl9fwqZBCSxSk71qzdqf%2FURcfxaa65v8O3ZVAjmI6RqSIgZo89%2Bpc0v%2FD23nLYXSyD02tUdqrQab5%2F3EuCXoWWPjKRDrCVTF%2BixcXxPav0QrXn%2FrV3UwhvwECGDE1WT8iR0BvmxQi6586zwP4IncVtHzuFoPXycvAbLGc6AzgADuBKCRBls4J6FLYsOnYj%2BX6q8IFADjWug%2Fz6P9QG6oF%2FzfcuMLPs9GxoZ3mLdh9lvgmzUy9fYMLjHgJV6c8OH246S%2B%2Fv6NRAxmX9AghZU8cbF2OoHssXNGeLN3nGUCNM9b%2F4kx%2F6prk8f9Hy1fRf4Qy%2BSBaW77s2OqqMSlNfquJr11GCpVpA4ARsw296kgIh0OYyfmAjhuKQUEcKCotiAAeP%2BcAA%2B%2FOrWVsnqGAWVdh6eAMmWyJAAKklcpIWcuj3uresSP%2FsQcdaFO4lEejy3niG5un%2BEN7vnMVHiCzP4d21NQHbAdsZkm2dH8zfYEmS%2F4IbqZtufJvf4Ji3RWEjU1uFbNKSOSnVq%2F6Nd%2F2LkwmItWv5phgjXkyOrN%2BRL%2F1lL1BZYn1rubetWe95Pf%2FEEe%2BgOL%2FBgI1fjL6U4YJ1DL%2FUEioCmyB9zUqbCuUm1lj9OP9F6vIRLJn1gsnmv0ESVjoycsR0x10%2FwuJwIW%2Fo71NlVvsE3lj7GMzP7RfY8JHkv6BB4IWjPrII2XgDuv%2Byx3%2BLzXTmjxMFTfDSJBxm%2FYTFUd8d337gnOM9%2BNA6vudQJajjLkZoqXRal9W7r1euJkWmvqiufr35a65Vw7IQYBUpV7%2FNzZXmn8vQas5V%2BxxwwvV68VAQd%2FaXPsymOf%2FguI0uNgU%2B4e3TVmNZfv3BZ5MHfA2M683ROx854ZKFdpDCFj5DpivNgkgd4XiFjQwQazQsIXqkxEfYl%2FLScE8atywumerNWZTfF0h69uzrWSmNMC2bfsCorRP5p%2BzvoXYq6llKn2%2BJT7yYfUu4Ox1tf1caiF%2BTryfa8qOMPon1Aq1%2F3d0GnYz7yQ6MX%2BPs5Cb%2F%2BTBySe5dXjaGoDZkFgvfIt3UaAyM9RqPPovk6SBRFfMzb5gxzv8v1uoYkjYMbpoT7dGMGfCUUv29j%2BgUNzzaOg2J9cBt%2BX9T2rq1qvWuaVvHa9au1rlORTbt%2BSxWgkDGiIUxo1ex1E545aHFtvOx8JYaZyvLLLX9203Xorn4b8tVHSXsb%2F56%2BNIP%2FDnd19ER6Kjrryem%2FlK1RvbthMl5xAea8vq3qCklHIQX4BVti00BHVEJcZFkm9oYIa1ZHtj2aSMNtatvwezIU0ngs01Am%2FOlKyXxQMq277%2FHxWIc9pL9JJrEG8jOPuD5%2BzBE1isw9xnd3O5s3E2e%2FD59Cxh1JZiDvCVYKc%2FCw0Zuor6E6rcSfhw%2FtApxPssg03tMCzK3w%2BrkAQrJDlrbHyfAmEdYrqqrSw%2BCijkxdWu0ZavqxRELqb1bte5aT6vXiDHz8tFZec0j%2BCjKiGA0CyhzWLqT0WCt%2Bf3BCZ40ZbC58GF73fXQMH1fq8EQmEXd0dztksjTVbXUE%2Fn8Exujtl9VdwiYv1MQsjJQm4DGis6bjWVfxOyu4ye1gCgX3aRRo39bkVv2S9%2FxH4caUvdT%2BOk5x7hqyidmSaQ62R5oJDjl8s3e%2BT9wEaCvx5BPDYPsO5qLyU%2BAggUDOJ4bKRs2YdywZ3BT9YwgpBQpMXF1xJwTwQaFmbGRYYpZ8yeqlJGGHjJNs58vH6dVxGgUVOypFkofCjyEaP7jqm53m8yfckVbj%2Bc0Fea8S4aHykLPj1%2BhLRXktrrzE5n%2FBEWrfVeXdhJ%2FNQ9%2BoLe6Se9Zfr8ObvXyQkSd%2BSOvfIIyMYl%2BT3pPzEVV%2FISHst7yy9%2Bevb9wve2xuF9iLqayQ%2Fl9y3cJX3KRa6W38nzIX5aYz7sHuPJZnzk8V80kV%2FHufuPiXBD8lViHfKtM3rj8ZLhdLGZRp3OcEOLn8Nh7q8v4nmBeCAwRgK9B6NXwHID7VRLI2FtmYuAJ8sEV%2BvQ9pau0UoP1yq5%2FRouwRX3c0VX61%2B5jFf65V6L1E%2FO%2FV7J%2Be%2Fk8C%2FEsJDD4u0%2BpLJ85DPiO7ktLeXxcJDzwsCcbA9pRjAXrygD6n4oQzhzHozOqCRWPfLG%2Fz%2BWH0L6%2FV79ddccT3%2F7%2B6XxG58vjSgvEiZQ2IGIxP9N3rA1jRZAoYCoGnVC8HGB9XIPHVRy9AxwvO9wP3KEvMS987eF3Y3giPUd1jAaToeYEt3eS15mBTfFfAASIUmE4UCYWFAWJAmJAWIgWCoWCgWC4UCw1CgSGIhHM7%2BOStyIqTJqpua5M8qiaA7puXlaC%2FjdZJ9m%2B95e7sn8OGxP9amI0pWZw9RGF%2B%2FVoso3faq%2FX8dVkn799xtpUHi8%2FwypU%2B3vI5vMTY2D%2BSSXXIw7jos50b6%2F%2BH81Ck3rNR8n4vq08jymurtoMUPLtHSVEXt0H7F9n4D5rKhXLqHpQIBNo9hGeMpnyZ8TZJIX%2Bi5H5Bv9Gb4eS0rMsriqjf3mJEV8EzAGvH9Jys9eM4BbP5StuwxLs786%2B38u%2FkiUQcYS9DjzK4IDs7ZO4B%2Bn1JARzKwsP9q1tAcOXK16nk%2FC4OASBUmCgWCYWGgWCoWHAWFAWSgWE4WIoiIIW5fHhurJzWqElXUovcxrVI0LOXyven627l2j0L9Q9Vb626az%2FXuzLRxGTMylC%2FUf5Jrw2veS1xfVPVxfTV%2Bba%2Bz%2FNlNXdPo%2FjTjQsV3c44GdsmcboW1uyrKWkIG9qnOSeyvsn1U8pqSoKsaKh3779L9XQ9GG6Wt9coySgJ4NZnJztRqJkMJfU0rMrW9HytPO2W%2BZ5EkBoi%2BRbZ%2Bw6rSabvS2SGx6SFDURZch14aIvv0dk1%2B5p9SLwPAR7sA9vv9Xn89QkuZQz1E3a5SuYgu9%2B2%2BGsjNNGhkUoJllnkml%2FhQmA%2FP5TBwAEUmf44YwbLky3i5Tc10OPkRHnDhtweqThC8lBqXmmhE4lOqSe%2BsvFspHtCl5Eevy8Vi10%2Bq1Mm7s4%2BNF6FzKvjq6aeLhbq9HxIJVBBQMqfgwQ98w4pZ4Ghvucg80zoUII8Cm4jxCBqgaPHgPptANZcSF8LjKSaO%2Bm1JSXMpOAQ4h%2BS1s8iXtslyteS7nTgISSVLW%2Bc%2BK%2Bap9IiH1VTwItNIDTEqGOETsLYTIrLptkPPBHVNS2CWQuKFlvN8Hsux23M3aI4MBQJBFUAARIAACkuTgAHlR5GAGQh4woIzmNOqICl%2FT2Sp6hLVFVgzZXlSyM1zcl1NVhdwh8Tkcw%2FxcTTkeOcjAccT%2BTE7YfTqn%2F8wYcBwAEYmf4VGLRgoVLmlqqp50J2QukKWDxE3SSBAIE5EmmhPI1mNky6c3DUVaR7BzJWUnY2%2B7QlNRRKQ07s%2FMkE0pPvXqF6Pe4Vxkb%2B9TgnNZhVYVKESdp%2B9qeFtJVJnCZ6JVs%3D&media_id=1254206535166763008&segment_index=15" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:32:02 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:32:02 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_AaeYvkDvwlvvfZfANjUU8g==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:02 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786112215129411; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:02 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "86971508e6bd5be60bdcbbecbad56a77", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19937", - "x-rate-limit-reset": "1587864356", - "x-response-time": "41", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "00f065e400d01c78", - "x-tsa-request-body-time": "64", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"R81NXsBIQwxbgDXkA80UsxmAz4I%3D\"", - "Expect": null - }, - "body": "command=APPEND&media_data=mr8wMBUNwSGS4uS%2B5%2BGDlQMyc8LE3WNG0Vkgmq8qORFcA61nbecIL1Sx4I01XlFSYhd6ReYbUQNIhJlKcFGFsE2hm%2BCx98QLLDgJJkbjlWnlpK1LCTQpo9bGLQAYpgp0C5DFFMKiCnZR507x%2BOz8AQCsP5by61ZqF416A2DvHihcOKp4C3DUILkH3UjOE53WdX7u%2F45rKj61c9cpZW1cqCXO0rB7QGIA5OQMXIJxYMToF5gG6kHAASLUkCYWCgVCgWPAWMgYCyICwnCQVCIiCIhc53ioqpMvNVEqrzLrLcXUq9DXX6XcfHnX%2BnXpv0VeHilPm1vjXqmv%2BfbKy3Y6X79mrnt26o7%2Ff3nm3Ukbb5%2Fbn8ymOfZPRrr77%2BqpwNgg0D4Hq8FoXYFMUocdSAMwUEM83zufwsc06VlcJGhnghsRDX5Qc34naHPgkp%2BwFTq2jnaBTckJ%2FygBXbp%2BaA28nR2E%2BAyC3xhtBSpuwxAnMafTl2b%2FHhWNkt13Gv%2FxaQAeB7rPeWhwc%2FgcX5faV1%2BJC0xnt46sW%2BnJSk8ERFLsDlgtwrrnWLmSraxJht79PkWX5duAOAEiVJBsEwoFhOFhQFiQFhQFjQFjOEiiEwvHs56zvciZUq8sqyNysl8JUnQ%2FoX6r0NuH5vS5a07o%2B5%2Bi5%2FvcUrSqY29bF3dF3dXh12V%2F6%2FXhiP6We%2F6T7yOXr66PKQ6VqkHzsf6Yjrmr4Net%2FE79VaaVLDNQLuO%2BwgYt%2B6WuJcM6Su9kxKVwjWfOcsYzjaISkxMKUvw%2FGAdYU5XYWblgpHnKGgzv80%2F12QXWAAC0UxTawJ9CSrDr2TdtKBdi9skeQbLI7uV9HCUQuTwrsyV1Whs6n33W6%2FUSQOTEjqBWbAmFylqqG5J1i1SUnoQWUT1E%2B3YH3BGkL4LYPdBwARyZ%2FiMYjpS2rWMqcdAreUQSWPDgmI6qVZMYIdpbpJ1fGzkAixNefZTkYv4vXF9xULPB223DbwkF1y030YlhF1UjhVNhWyU2RqGdrfNhRWfV7ijwjSDIRWyZAzckV3UNpop%2BnSpM1xLKFlTJeM4Y7xKkXMBEW3pD0JOUEvC%2FHiYR4AxEGnOOWZwVDPs%2BHxu6sjpaeglVYVWFnhc1WFuA0itBxCcCiFQGThRc0PEisTn%2FS3dPvsVVv2WJcR8qPyaNOyugQW0jnBhYbIkddzek%2FE9D6Pldx%2Bt%2F7%2F%2BOhl7VafWt3ezLLW5riyAtBUpq5%2FnrhRhg1tK2OOFYM7asLtMySAkDEyBwsGLwD5eiAIsHGgOAAAAPLkGaHgeKBXJ6EsdxV9F%2F9%2FrFJ6vVrXy%2F99S5cqt2pE%2F%2F5f1l%2BtRHq3S9LXrUmBugsEKsN%2BrfnznHA7FD%2FTe2xPcXHnxkswbsUdl3U24l8nvgSIsIUHCAJlOn56mj6j%2BwqMwk0SxACZPrywsyK8JoCpRe1%2F8gbE8uBXoD58DpBy%2BDBKXL%2FyQiG%2BO%2Bs5FKxM3Tz9K43nDBMQ53EDggCZCASrAfB0Y0g4PBcDBiggqf4bPhE678Fm6x6Rxe1yvn6TtWK9cv1dhJz9M%2F23N667%2FV%2F1r9cq9e6pHgdBIdhcYfm7bvN1LwmGwEhfil8UXMo8IYr16%2FV5faXeG1E6wOhVTE%2BDeDAYqZp5sAQU8fjpzYrVZVeJhfR4tBLA%2Fj%2BD71%2BT6iQdBQBCnA7AxBBSNYG%2BlgdmpYD4liRD8%2B4upzB4l0RrwxSYlq%2FJlqOgisi68WaXKdlmQQ4FNTslW4uqTKy0uMeUYDBJBiUdNTWLPcjxNNxQeZfGDBgSAjnLG59EYOSKwVzDwJbkvWGW1lfm3j3zhYPDJRtxJ7k3LCJ0bYsNLTJW2pWbWZ4aDQ2Kvp5fHPRbh7vFG8Xy7bl2DfHu9feKMHIId71PaGpU%2FVpLm9X1fL6yrAQoRU1vCINQKYEsPDj2fMb998UwZFAYEMNCj%2Bt4fl1bfAtjg7J3urPRy2qrIIvB9%2FLX8wn%2Fw3HLTZ612zUZybiFmEImKEE7km1TgPt1yUBQX9iCNrHPKvrAWpPwSG14Kt7obF7Fe6sX6v33XrX6uCUq1E3XLvCOGyGbF%2B5DAFQBTBEKe1IJxtBnhUK3LcmDhb2bCZweyD78d%2F%2BL4FAnurv0EX%2BWrWqp79eu6qv1yq5rrASQWCgSgvPGcNPh1AVW6bVTApYjhq%2BNysA8mFKNY5mSkiaoWy%2BhkwbqO6mNaXAIlc36%2BmI7pPXXop04gnn7r0E%2B9V6%2FVlzq3fTr1Vd8vVL6sX6lpfMfgkeT%2FbwJQoLDhYSNSZxseb%2FFAGLIDGao81NEcXbLgfVKaC40EZ%2BMQIc1ApzwYU8vhiNwOd0hw30LMEQocQ8LMHQhXJgJc5xLXzVqYWNVEhWg24vYcQs9ptQT9dTV%2Fk8gVlwyg9BMKHgmJKAEYk3j8nrSIyv1foIucq%2BrpYpKde7%2FUqTDl%2Bu1LT2c6nhdfm%2F9nJwsIBTpYB3FlUN22cBcAoLiJH28ogDvFfWbdyd88lMH4BiwsWhUoF81X%2FG2y9uS8snq6JEe7GZuqrJAqAHbbC3kSkYrbk%2FgqJ3cKC6oncxCN%2FGqxA9Bvtr2T6NJdCqQrwHDkN2QInvuDXqP7x3ymEe%2B2z6rfnw6IOX%2Bpf9o6KXDpbWg%2BoUNqoOV6YjUNY7iAaMa0heJSyZ4nN0Ly0ElSSuc%2BoOMkISMm%2F7SQBKoyHv%2FnSXWbgbe9b9e%2B0frmrxFWx3dXr1erBUSs%2FL3V99%2FE%2B6vT99yphgiWHVmmGRsYmwPxbBwRPj%2Bx%2FUEBIUVlj5TZG3TiqdfSD%2FkLk%2FmcgSbxpUFmGzheaAakrVvm7aoxDmJ9dmXcKqOhbRrrGjRhyfCCS24VGBrdh4KsD9KjAAJ4PvLTyzBCJRp%2F34ljR%2BDMWnkmX38mDzRqt8GpsMDE6f1OoVKNXyzh3wlY%2BmDaTUM8X1JTvXCojJ9lISCHvWUVQ4af8n7riWM2ESwhHD4btUENF11zUWY%2BqDLf3Gy3AZy21pAh3dzDFZm8389CkdelQ0TDtDJ5%2BkGp8MXkF4aMOrGoLrtMhIeE34GZQvsGgYyMTn0ZapVrTTWjj0Bj2CvjPylBdKGTKNtt4y0XLZLoXMdoncvfa5dy3LgIgMr57esCVG%2FAUwgxsuFysDwGAci0fLWSBtMXiD1%2BC0k1p8aoP5Vs36jO5dMcFU87FdYd8TFi%2FKZXAhalsEEBt6gArf6p5JlrzzfuXtDMmSL%2BA8G6lpVatjeEA%2FZdB%2F7sN6BDA3XRdX0OEbBHHCLka0aM3cNqEC5AxM8L%2FCxW0pocZjGPzo6lx5fCT5Ik7LRU4fBASzkG0ORm3ALamrLhBdzLGasc1oJaScAcv1PzNr1o%2BaT53EcFRAg1qmAwd%2BNDaRoN8KZXMSCPFrGHqcRCPDaSrCAxPr%2FyL5P6%2BhMMYIc63kqme%2BDrx5f6h%2B95R4xdIMYlE4HtqPF%2BvRtzbmEegr%2FhQrBA%2BLvpgkfkd8rwtGeG7O9y34foxuzw2vKK9q7W8hNC%2BeGBf%2B%2FsE5OwZV7HHkwW5ZL%2FRWltXfrK9icvjd45%2FguEPuooaiQPI2uQDOFxZBIOBcV9%2BNCfLA5h9VGteq21cmF7e3yX61ZaLi4lkbOTeKtuT%2BAmhGUEY4EIwaVaQhxU25Yf6pKsHdrxLyz1Qoq1xsc2qfqrBLOPM6pjDY1vpJ5%2FowfWvMmF%2BtvUOie9vHROfOJPlzwX61c25rpyffl4QINxjYbTtM4wHgb%2FoEpbQuTsHnGeUW%2FlChG43B%2F0nOcudi2WNs2OyuynfeT0%2FkFE1VHWpmiFMlfStPHYI9x69o6F2fH7jipGYOSLTET0l1%2FVnzk%2Fd%2FGGYqznFHm898X3efKUnwXdYKpbGP6wZ7XEjUv2BIgwi6Rzduyfu%2FhXacuVy6HH19wRVST%2F4SoLGN3ff4a3KQyzqn99sEnxenxaKiu7%2FUqfFSWtSXyXgIcMeBnBV4CdBACUh8EuZ7g68rWsCGBFCYJWK6rsFZQT4kSQWyFQAmU8UAjdQGSUMhXu0Evv3%2FJ%2BJgBJ9V%2B7zfAa14H39l4xuNtbsedEOi6R6VDgjcS4l4yY9fgppEmG%2Bl1V758w0qEv1BwyRcELGkBHjZn%2FwWQ2AB0FgGLCLAsAzcTo%2BlN0HHpT0xaWlEmxTl6r%2BKLd50tlL%2B2Gb%2FrVVNv8n7%2BvUCMubGCbZ4Ldp%2Bemsnh12Ku%2FpvrDhL3X9MEt0eSeu%2FhnudIvjcXdJnl4iX1rtXlwVaXgRgjk9AKQLAOAIgLgKcVFouNXe9rtgpIe4d8Y3dlq0gwRIZM7kFurDpTm6EGXS0Ywds4Twy7GmrDFr%2F4JtLcOrWfM2y61ebMMU1I%2BN1YduY40sy0s9HU%2Bs5MsD%2F7uEby6r95dmu3ZdwTltu3m1tKauEASkMICHJ62Ul1mtHPoHWS7TUg%2BWwkafY753EmFlMY82IPbDdFD2uCjZeCeATf6Kvv75ZbChrC97zMdW6MdLP9hWypuhjpYdA1LFa%2F5Px98F3eO4DzVFQ%2BOejzVa5X98R8R5aK8u6OVKu135f%2BkjDuSVXiSyeaKA98TEdZzLeePyfv0kCM52c2db6wUcbXb0%2B1eUo6Y6isJfEEGFYys5PsIe8QW9m2LyGOpz9%2FL7f0FxOXJaBlCBxkFwKrkVZvMK3wiY18n9JL4Y00DuNUMhn%2FgULN2U%2B71tv%2F9PhEVd8A3WbGarZ%2FNTjRuT9y%2BgkJTLns3k9K%2FDtgZ4z0BN%2BZv2w%2FP9fXxgt2hyF%2Blel%2Fwj0T3%2BsGX%2F%2Brtar6nr5K50qtFf8mfNP7HmzwLlEbMHrF995Pb%2FNPgo%2F7LRCv8VlZt1rL9f%2FTgiGoPTWf9gmqvk3Hy%2FPdYSgSd%2FWXvaGa0Bob6b%2BwUGmlmM3SYexsuU0MEZI%2FQERoslj24PdAqyr6jsi4a5MDr1gvrIdsPGVZtGAHg%2FTX5xYEUC3OAxLEgHLzsW0TREa4s57ASFAfozjBz%2F%2BT5zsilGyeczfUoCaNzqxNsBzIsBoFTQGOszId9z9F97U%2B4ZWIf5yXoShSnnkfKkl397%2BK2Px7Ne0hmxn2e7bwbvH6La%2F0yvUboytXIMLYwD8zLKYMMtNlPIt8RRAgsdMBZtlvlVpBiHXygUe6D3FWls9461QACuMby%2Bg6QLairwRjWfQi0KzyXV936nCr1j%2BqM9ak3Nn1Nd%2Bvwh1ave77vDkhocNyDoXWx2AlT%2Fq8F07wj4TM15WgdxCwmd3Yz8EFmHRrTnJBOaYKyi1iCeRaZjDa8JPc%2F1r%2FnqF87%2F%2FirO6B7IufC0%2F%2FjgzL73W%2F%2BxehpKuvwRWNCeUX7Epv36QLjW4HutXmWHYtFMWtVBUQdMqnbzlQjVSSEzzdj5BhhCyw%2B3XlilZ6O2QsQrMUukfWIyKwHjjZBbZC4F2NSQbuvk90IMPbcIyA7DvIJPzRIJN1N5nWhXB%2BY40TYg1tN16wI9NLmgOeFsx%2B9GrKq1nrXZ8WT6nLMF3E8IH%2FFWyjnu0QPbknvPvYnGm4sWLtvxP7%2BWCMpI%2BLz8n34hChAsXefc2FpX92rYp%2B5JiVr3yfT%2BCHzmES503mx4x%2FibvOIDDgQcrX8EJWZ8H5%2FU4%2BCB%2Fq%2FwyUbZGDg2Ku35E%2B0pENPYIjDo6%2FsfZOo8RJPsr8tcN7dmJiOGjd0CkW2WXb3dr8o9MFRGjjBymLfRmIKwhdXhE1Q0D23i6IGM1r2SaeqBlrxflSpY6MX01D0EJlXJtKftyy54%2FJVa2%2Bo%2BNM7u%2B8imBLAastHo0vZa%2B11YGLTCLIdWdihR9cx8wKiNSlSg6r1zzg6sdl%2FteBICQK%2BbJTSite8%2FQ2fZfXIZGF2opi7lgJ0jrLiR5QpjO5LVRUnPELFoYeKnLH1vnml61Fo8MH%2BXA15SDrKaUeXNfTHbqbdT73cMeNfDr8rxSPuaKi1S9Mucc7cno%2FVE%2FKr161L4rY1WTmf%2FMQzFv9ddl1vvsxHZ8v9dgiLELHLdeC3wStmWs4nkJueiGAHvVyOzt%2FyeQtv4jiHMuJfLJXLe%2FMg5QMD791%2BO49aRWImpj%2FstlpWEW4Qv2p7fA6Z%2BMgR3N9djewCKEyQQZ8y59Wa4tJfUXr30PtPiRgH7UN%2F32WTOkaEMZ5saLpRntmTc%2FhsWbik9swmgK4IwpirskxWSG0B2NUmYeOCj7MvyuyCgejSY5O9h9hgeQaja1VQdsOeKaBVaMf0wfS9X%2BhrX65fouX6sq%2B%2FI78ERikXfF3zj9x3JuG%2B7v6z1puv%2BwYX0p92PuPGWPaInNPL%2Byhb73f98%2FP3vOc8Mm0xrLCLf%2BTzLHJ3VzS%2BHObKn1tpqbaVd5qSXVZjAgjPouRINNHue17n0u5NapAvBgYg8YmBgPfB10MZV4HDuYUVOHF%2BWs%2FJd636GuTeivfkyZ%2FVOpfrP%2F0Udv0Tqu4MV15KJ3%2Fa5alGdeCMMjzTXs2da0OT3A%2FhcDyPB0NBMLBcMCJ1KKytDHC9RL4myeYDVD4DSAS4JYHYFYU7oy6wRMwfDSMV49ZQw76xtZ7AAAAp3QZoeh6oFf6EtXqx3F3V1fF%2FrF%2F32rfq3jKt3qp%2FVfOf21Yb%2F8E%2F%2Fl%2FXv174mYUr7XY%2Bl6TzeAUWpzOD4LjRGq6qHPIAfkxR4mU1d92AnUUuQjID7xWuFpofTAE2HBzpAXppd4ZR5LToAQTAbIIQ3JegLgCxkAIgNyicj0uC0qhY9ZP33JQn4jpy45pwSBDTgiFBgdhkeq2nXGjQ%2FcdNDNr3LweyIMG9uief7%2FoX3iK97f6%2FP17FeOxX2O9hpFgk9W7Vu6uy%2F8fq5865fq3yr29rC5lLvifHnxcePqO24YhhDT6aFZlILEo4PmD3bLb7%2BL7JHdqBoEgaA1k5WElEJMRgKx5N%2FYsR1Miqe3zCz4j8eg0QvNsS2NkB0rI1wr9vgUPKEi6DXMAxeJbLTIyoavsMzBeDk9cX4a788D7pADOO4hG%2FfrCPptwGiQbDk7pH3U0GF9%2Fye0kWApwLYJRo0mayMnuZ8DzkBdcsOLxZk621qbvkV2huUOdVLCP4Un6D4cNIAhhoH0gQ8MGq8sJMQOAc%2B1Ci6dixxVuEBwUmzhpP9oxf692BrI2nd3zG8iRwp3w9z5LjbJpB78PnfxAwOnPmKxXSnyxWK3F0EOSZdKOqCZm1YvB4Mqmq8UtehPVMSvTctDF4XRf6%2B%2BI%2B1q%2FU9WNGhoVJeJkItAypZSUvx%2BWOnv4CVDIVyXgfpQ%2BJfECyEBdFIjM8Jng6HoXE0%2BYqjcfpA442Kx9pUsW7Tn52KVynpYgjQMRIVDBj%2F4rPGpa4vwLYXBTey3jHuK3Ej%2Bju4WMAvBYF5d31UCQACIQCgAiwXGHLNsFONyx2SyHiMxa2YD7O%2FAd89wNCgUpyiZCLRSpYpVz8quWTsv3xNVoT3d3jnLmrvuRc2vRFNeJNqX3YCGighBky973AbAoAkAMYyNBqjKC5d9S1e9tW1hBFGcBTRhKaHIgoDO8f4WDR%2F9C6pv%2FPd9SxZf%2F79cKojuvVpvWKifX%2FXr3V7E%2FHd0aRkUcPbjoCSiw9uY0zVx8oPmUQpKhbGBobKSIbWobnhycDLj0E9qoh3vEBMMQoSGaxOAPZdaGdCQRe%2Ftv3fwVup8lcmJRvv%2By6Z4Plq%2F0E67muW15EaiZN16T17eDMpkCgVhR0CqmILLTOYsfRbUCzBVTJYcWKxP%2FndLwpBQUaCDMJwm%2BkJcXOFt4VMVDhilmo4mHqPUbU0kdjdX%2BpBPvde7Xqv7W%2FcnE%2Fqdri6v0btXO79erlsn54g5xAYJxzAOlgKgBBUw4APEpMEeOE5dwwAKRx71eBNGB8ZtJjOG651EIpEj8XGbwuqqKzItJn%2B6%2F8KEHDSleM30RJ%2Bmr%2FoJIlH%2FuIpcJIR9v7bfzuoIDPfx%2F%2Bcq%2FlMR0uMvllqWCw0lWXLz2NtWDIFVHTlt3O1BVpXOw1hYoiCu4tVDXorAGR1NP7f4F0H3MMHKKq%2FR3XUvc0r9yClcnN2sHYJO5bY%2FRGMn3iTeCCPKNcIbMPMI5OWhA6at83NZRBtEByVKupEiMEskCpZ6h8l%2BN2aw8DPDwxWuePoYPbJZFgxFHX7wEcZMoxW%2F1Ej73uUYLV7rT8seTaMqYQW2o0PbVJ1pfcE1tqWqCfR7r8VZ5qr88XSSQNA0pSO%2F0LcihX%2F81LwVC1rwIAIUZmuE6FdVrS4Com7vwPHwffzcQ4GQel%2B68b5544GgdKujWMwIDQNftlnD%2BaHERlXO5rtheYmZKv2eZmm%2FZFS%2FhmOvynEQYr82yyvfF0GKZ2CQ0MJIHv8t8CrJvPnKtsfdcC%2F4mdSssH1%2FRNV8lES%2Bvd%2FSLF82%2BcT9E8iFCtJ7SreEBgE0J7wbnAwhsxtTZWC04Ig0CYSqi8HiwHllcDw11j7Q3KGN2%2BcB7VBEhsv%2BuQuEnmt4wa9MNlz%2BvmKkUMr%2BFCIeuLrE%2FU8OHeWAZYH2zUp9N%2FonWX36x8I%2FLjFqlT3%2FEIWHSoST95fJ%2FZO7Jd%2F0d%2B4i%2B1arp%2BMesCaJARoWECBLj761geQmBPo3fh04RhJKhENAhvXR3eEgJGEA1nbskcAAQDFAxJsCZdhF6XpMmEtTkflgi2MhaohW9zjVN2rf%2FMY9C5WT378Et7HFDFDJjMg%2FZlzXnPL5q6%2FLpXXr36LhaZvuS5LV3S%2BXdE8Dj4f%2BCo69rDwIshne94Iwhh4ltZccgd%2FocjJLYE9iwHqOIjhL%2F9lvXt8vk6L%2F6mJaf8kiLa367%2FEHz3Y7qQnt4eQXX4LY5Vfah3%2Fs%2FDkyllr7lITK%2F5aQY0DwHB%2BX%2FXE5dugO0OsvrKvll7v7J4fxHBsQsXd2THxKXt8Eplgweh0Hkh2T9r8xckq9Yq8ol9%2FhoRxwwvjokI6OvROpoW4eutRA8%2F2ZQgDvYeXljZfCdRnG%2FN3f8xxloh48Pj8FGgWBVsbl4ij3fixHAHZ5JuO3DXf0di%2Flu7vyFq6XxF33d6v9e%2FXrs9ffJV%2BbNL%2BCfu97Xq9cpPIIKGkqLlYD6xA9w8QBoOUJ7eD%2BIPFO0Y%2FJAACcsESnAD%2FyLBXFiDKVDTEGT8EhMFFpBKaBKh3ioax9sVfL6K9JDZNM6%2FK4rMJjGCAmccGY5k0wYxkmlHZtpJR59imr%2FMvjTDjRjdoIPld398x3JWUJJ%2F5PXJkix%2F2uDXaIZSZqV%2FGFwiap25cbxl7Fe%2FJVuEPk5CaiHa3j8XLxopKKmyh8qofFsovLQuLLm%2BrXv1fvlMS79vttSfn%2FbvFUQ6Fln2iAuFV4vSY2zUYf%2BtfvUaZcvr8n5pZWd%2Brq84lfVqn8ERoyIV68vUhg740SZdt7fY4kwhJmxeelDrza0rq04VwAwL7Qom3nWMLud%2BdXye%2FOqggg789wIwGHPPj4cSecQrfPxculR%2FXcJhTSaKx3x5WHfDdJ%2B9CQoeZkZUtjfqvkg0qSKaKkud98vcYRIh4mdhZVFE7wY2VjNNLPsJGj47o0dIv5c5TXb84vu%2B77Fnuld%2Fncn1TfoTUTd%2BHCVLTXyiFBKZTf1Zf71r1r83MbMil%2FXaNhQW79wiIw1nXHVi%2BTAbL1bCSiLLYML4VdxUW%2F3ES2cDS0XIt71aEUioF%2F5tfhVqrLfBLhxJLH1L5MeuPIIaCt1Ks2NJJdfhG76TOexVHyhMvuMnx90txW6jsLgUVqOW%2FGFBQ5mr9YSE1Lb9JvH1Z76sJxPrnxEXiR979FBcXVQfaI4FQffeyi6myTMB7YuWGe6xOX0dp%2FfMIC6R1k%2FvvC%2B9HerP40iIZDKfP7%2FUCB6fnvu3nuIFBtqI%2Fw76s8XEdF%2FRJ5HG%2Fkhy%2FuW4SpEGX0n3%2B9zIX4W%2Bz9N%2FiL3pFN74qJaySFR1brj4wfxD87bF2hL5pdIZxPB5fG8Qe0uo7hfVl9awXDwVkrYzZ%2FBjfNn6GvV%2FSvV9osXCa7LtWC0r8gh7SMnln%2Fr6uHel59eENryyEe3pXCVJ8NDIc18vjpomJjpYdlPncTpyIT44vLess8sF6lv1uCMSNIkTbwTPJTctAF93pCHjw8RU%2Fi9v93Jd2h%2BUnr3d%2BsFXL9X333%2B85J7rEx4tiojnL46oOwuBbHgqIXlj8VWIcb7L%2BCAUDkIgoA5hQmWiQDNdHFPi4pwivHZCwAAANC0GaHwfKBX3VoS8nr3gbP%2F%2F%2F%2Fgaf%2Ff1l%2F%2B%2B%2Fv%2F%2FL%2F%2F%2BvcCz%2Bv%2B%2BBf77Jd9XXoqUFavZPX%2Fr1lZf%2F6uoC3r0R6J9e96wMcDwGQwbELHBFNWsF%2FTOc%2Fb%2B8D4GSC9%2FHm5cfASh3gmMYuX%2BCQQGCXSDk0xWXLfgRZoJSeUyKDzGRTrwZCBZmDeeHH6YSY1IC8CF4Kpe8OA%2B%2FEIvfemn6Ee6tXOicUvOr%2Frkvcl9okuiZbWqHLi%2FWtvhcxsZAdVSx0mS2Dm9v%2BTK8sKda47vn%2BsU4k8sMUMsDFDBZjAVxphsLDhuu2qFeYaNyPywxQxQxQywxQxQxQxB2IGMONpUpPheksS%2FlgsgEzXabXfxJwTwsMsMScBqvFhlhjShJqT9JBKLA2DAIYkKGxVPwj9InHx4mOtE141oAsvgWZoIYVY3EOCpP4mfVplEmQ4iwsTx92qUBtGzZHV1%2F8aWOLL%2BdAaRIBGo3URoFmS65da310LlX3NuEABHWwIABGU2nFdlS1mdrqzl%2F520jZ7X460cNQ9RrG1S%2BjNySgdUqRyVmAmvB4EFECSII6pEe92sr9aqifjVecQtXJdv8VVrWq3yQscUEiVgpoaYPBbtg4g94QWB%2BgMMx6WVVL8ugy5fhJS4HygZmWoUVl0KFc0Jyt9dBzTA7rXF%2BmWH3TCDbggdOGWnMgAZss9gOSxM4Vnm9hNXUTVVXCCHCarRszwC%2B3B7IoOhQNQ35ouYaezS02jVLwIpgTGKQvIAjbmK3GtdiaI%2BT7nAbC8K7M%2B04THDCKkwA%2F43kXCr5P76o40So1mrG2Ulcxns9h%2BiP6LVrl9LUtS4dr0z%2BJov%2FG69XEfESDuZqzbxMUMPqRLhGcYTOIfVPrEggOcc%3D&media_id=1254206535166763008&segment_index=16" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:32:02 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:32:02 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_DEEMVQS\/UKN7dMPLBztYOg==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:02 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786112263731147; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:02 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "271299047b9f313afd5f048c7cdf815a", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19936", - "x-rate-limit-reset": "1587864356", - "x-response-time": "36", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "003cd36700cbfb6b", - "x-tsa-request-body-time": "64", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"SX0iqSmFPKfyN%2BnluOC2ctTe6sQ%3D\"", - "Expect": null - }, - "body": "command=APPEND&media_data=b33UPy%2B7vMPJv56DRT3P3CQXIFB44LBoysC%2F4KgwYdAcX5P6wTPzwFgE4jviXfaF1VEbPu6tflXdq0mq4V95d33U9Xk%2FUgjEopx46CVinqSXTqngGgLljGGm4ADKjHfJtRRHd7xjyPraBPy68WR%2Fh32Q3%2F2iUyo1LlAfZzim02J5dLnvvS%2FEE%2BP%2F9BFu1Yr1rv439Xk%2Bul1N2tbzyDQwTbADnswPG%2F3sQ0YrZgkFaktxv4N8v5PTxNy8LwMaBRnTxbctAQYXzM98LwnCCCgoX1Gvh6NMZY4vGLloF1I30c9V%2FofY9ZfVj9av5vX5fzrBrLC5OCR7ANRKnQMAMbDoulC4CUglCfZqwyAR%2FNuJOF2EY%2BbBaHWoDHqmHMxKlBhLwzxbsZaJjB%2Bs2dhcENTlb5U8kYSbv1i5nC8M%2B8FDdRoEAQggpcB6Pkyj2dEGwqQKDjKt1nYS%2FT%2BPE9DhNac%2F%2FvZq6NpU9je4QBFsIHQOAUA4YuzGS61rVhFQEvZNpf4WTNajSQbdJWzD%2BMNPnRgPbWdbwZs3WnhnHQxqRj7%2F7KsZjGJmfl9QwcvHWWwk%2BgZo%2BpoZ%2FHQcLT3eT65PbltHquSX1r9Wr%2F19Rf%2BJAkifCdXNZbggJogdsaKIU9Rk8xwRPrKls46lf3DndjSv5xgmqNT1Q5y%2FulQZqtfqvg3T%2FQm0NgbmQxtoQ%2BygABAGs9PySmgcN8E6jDBqEfgld%2BHmr4u3cJx0DSqoC3yWDt7bapAP4S%2FWDSF993%2B4Ksf8wbLrtsIfnKdlvhqckO3kG8m4UPoM2ro7ISYfXwwZ6%2FJ%2BaiZIyWokjVdkNx0d6%2FJZKYTq1vir%2Bo0rU%2B4K%2B7ZKsh7p8FrnTYZZQhergslwuQXOZyU0IKsQYhsf4XSZ5xJEodV4UVVvxGyx%2B3Xwy0Ny68n9%2B9eidfq1d99r3dZ%2FgLwEJRK1S4CgDKEd8K%2BuuOKJFidVXeXw3AswPYYAQ4KhYq93FGbRYdW4RjOKwwCw7%2FAbsNnO3L7fH5Pr9wQYP8Ai7ln8fQGGWJc3YnGhgcPotUuwGDRxIf8LkDjQL1vZjXgvQhvJ%2F3ufHyXx3rwsNafb1vv7G84cTNUV1JhrxEyLqfgs%2Bvn1Z2lMGu%2F%2BAVsWwT6ugTH3LuU2lzna12CjVvVUnPUFZLMogNkTYr89eLTOR8N6yWtXE8claVFwP%2FqXJsZTFS6u12pCoGKs4tFi5PdW%2FEERZfe%2FBjsmEGYCMSl%2F5MRZlBxIHxibcjT93dYaD694CBEm7S37PiEYNA1SYf%2F%2BtVVdakz1pMf005fAkw%2BILKhpdXijTEpBEAHBlCYSvQuq8BO6l9rC1i4l0PxNaYygdtYJgQtjYgB6QABqi%2FfEHBrrnZ9HyKfxolQDqZkySAmX8v79FOYIBjMr6iKwYOn6LPoC2mcmf%2Bf5I3qC4hs%2FPBmt%2BEzZrwMyyP%2BymNjoVBX%2BhhODWoubaqnL1VVublj6gpKB1vbDlD6HWv1VtQ9TMrSC09K8MkPt6%2B0Xe1ywrhNihMGqa%2FBZiYXwl%2By%2F3EQb9Bz5alXo9UEmwO15s6cvraZUHtMZLn8NDPSFlOl5xfbB2W9OHeiT6B2JQO1RH93UuhRQ2v9SKyuaTCFY%2F6v2vVT1dF%2BM%2F8PDEZvEHROzD%2F34VEjzJuVW769rnS3%2FjEOCysWvoaLHT5I2Q25VFnIwBBWD3oJzHqoS6qzPk7N5BqQQGAo0ccYGq1n4fjJt9U%2F5jz1VVmWiUzGKoPX%2B6LiErUNl0ttEYXg9wyMFA8ZcjYIC%2F1wg2KOkCX3PRAykr4tf%2FX2Yt1b9gtnSxLLQtPlXituR0PNa0fwhZ%2BPu929TljPv8nnOVfx2XXfuCgz7eeBcZu8EMV2m8R3UE85Pv%2Fr0d7vgWgi676BKKVVIxZqgLLfeIhaOv2ZUtHs95f78PQ3JjyVL393s%2BwM4zCJn1PhC977vb%2FJLsT8uX%2Bv%2FDInIxi%2BuXV48w61dm0UZJk5mIOzGyysFB3fu9xYZOESDxw%2FiHN3%2B%2ByTpMMpFfUF3dmPhAT6Mgb1TMBXyCpy4frdeYz0Xe3ct7v9FuPnOupZbR6fQoyXz6UpCEl8QwpvPUYR%2F%2F0Y6MMTz0QEY6th3kvgo1d5jWyiNeJxuQZP38UYFAiJkGOHayeyvsv5OX%2BzqTO9VPl9OEvDanJd%2Bi%2Bq%2BX9ev3Pn%2Bt36tRfbqrIbEOdm8%2BJd4TxfSF45MqxR5oy%2BOoN7Pcfnxu%2FneOIGFpc1gvjhn90BSjS1jgkfv8QQd8SshV%2Ffd5PPqsXJgx7sQpqI5XbjSFzgRsRp8J9yiBaKVSNdZlM%2FRGCh2afnBeBD4g%2BWxuT%2FWICaY21DiRRlUVMxhKpB1XC1SB3NKEa3OEjBD4ThUYDM0HY0cbw4uNxIC5zBnkzYfjdSI0AGQwSRiAysoxArFcO0h2O94sJFQwiFa5SqO2KelTw1bdRpKVHAIa0n0uxk2vr%2FawkDZk4FGC%2FVJk68mr%2BPTl9tZwdBIaXiM69kVPTX3IV1%2F4QjeVV5fGzH5f78P8OpmMnE2YMf6gb0nyDy%2BXUuX31sFd9%2Bpom1RlxT%2F7oS1%2Btd14ikuPSv%2FRO%2FWL8naafYTsO0Qgu%2FsJYfUrOieT3f%2BvBOVAZTEcVfjlJBMPqdq9e139s59fk9O%2FIazaZVMkvk%2FGr3IYrI8wTp8WhsfH1SpDMYAZzj%2Bfa6yESkPaVZCzEYTHNwHaZfernwaeAnCAaZBVRoV42%2FTDHdN%2Fu2%2Ftf%2FsgwjcS3x%2BK%2BDYqq0tYGI8o99CQvS%2FGmDfKMLbLenhccNyxAsZlxe%2BLZTUvseMzSbFCaxRkX9x3I9nD6PFGKOX0JriB0XA%2BXisiIVieYFFez2YYjSyQiXxPUvgIQ5hsL%2BNq%2Fjev8vxOW2hffd7XRS6%2FJ3fd%2Bvfku%2B11mES%2F3k%2FP%2F8EhZsrlJ4Z2T9x8izcUv%2FWGuqGvnkMmz%2FokPerq5p8wlq37hMhhLd6VE%2FVy3CJq8k2jBZAIrnAdZ%2FigUMPpfjGOLxGGr09KhfTc%2FiBHBUhfIzmcro62SxFc2xUiVw%2FgrEDkB0HfhqIIXEn2Uf2c0EOVwji7QO%2BYrFfXhEoID0o3mIHC4ex3xKSUfEwDllptH9su8v5cQYNjYHfWkStXxzOVvWfcsG5CTdv%2F1lkjytRbLWa8DvKD1hUKGQ6ZVX9C%2BruG%2FOwZYakXKgUdIzGAPU5rc4wDxx98v6vXovfrUT6JX6sN%2Fq9eCTVA0VVYIsdmfr8I%2BNRyelQjcFY7%2FBEaWD33EhWNyEMYrj%2FPipE3%2BlcRwO16hcG%2F0BfBJGnAul%2BnG%2FKgxaaa32T5dT%2Fk%2Fmq37%2FNzUTl%2FdkkLz0al%2BikPcRWsQsRuZ98KAbQ2M4ubY3z4TJxf61sIlGu%2BqYzuDXU1XxDsanuM3l9PSIcFogLeR098XXXaGxTevfVevVavXr3u7lpl9Gd%2BQ84Qby%2Fl%2BrX6LXm14i93pP7%2FhAZwO67d3Pb8vluIki5qDK9sdFJ%2BpHRpIy2bPnjzfNDsnLnmRCSX14JRIidws8UDB222vQ9rFbr16S5II5Ljd9%2FghFHw8c6a8EoR3gQx5EHiZNSjmbsgIeYQHQBgDEGwC%2Foit%2FLt4AAAArcQZofh%2BoFfdehLfq93J6v7NfrFdq5LdWry2tV613Pa4Xa9%2BvSUy909QO%2BvhsMdJdSQwP47LNTbNiE0ITUnhKAScEIDZHwicqm1P5d0npwCVBJEi4B3g74ATsBsFG5ciB8aOuBkCAKCOgYUIe2Y9kzPMvkk%2FgaAkCM5824r2n0diQcty7v1SY7c4aLEd2r9%2BoaEVo1hpSu%2Fl9fQTC8Ar07%2BV1aR4B8eqQuXml8fPol1cgs29GxpD7ThX5VWdILDYeYmQeNmRfIeaZA%2BGktMsfpLk30NLq1BKeuf3B6BtLCgLSzqF4yNpYKQZKcu9m9Hk1Btt%2FL8hhgsgK40RuWkuEnTDzXg93uoPd5E0VD%2Fq2VIKus2sMW05ncVBxVX1q%2BUDGY1P8Qgpi3lTvsaC%2B8VYzuuS18So39RmiotQGA7gcBXAaP4N6%2BXEBzSquKaW7ZhRRdyVTYBcAcvuUm1IK6eqk8szoec20ZTZ7jzfPcW0ot%2BPP2qCqk6AJMEp4DWknZKnZHa4D%2F%2FYW69CAd8mw4d0wWP2s117jZRUgZh1KBZpjs4ZbYbExIGCqHeOF0A5sCAGB4KgzY4hYBUNJ%2BeR4bKXK9%2FtcWATpXywJK1dcTju9DpXe%2FXL9Xl9Wpdavd%2FN2tSLayGNpc%2FEBWM5S%2B8XFNSYIFEIAugaDGZYrgaGzAsrwghDO5QRTOwnGeEFkX29JL4oYHqiTxzyzw6ALjhE4Kgoo2IgkQqNY7eIBIhAEqA83LR6l4NNLFvUvrBG2Fg%2BVV5ksWsxwdaCsRCSQi11tyb%2FmVYu01rgoLLjc1WjI9cT85uFldcrdCmYgOSBs3hij4wUTeGs%2BHdFYrCkBxgdwLpASn7sV1MnDNdaaTJyxTAaQ%2BNHwIsO1uDnH23279bVwYAI0QAAiFkRZ75yWlAO0CpqkOeOqoj0WCwlu2y%2F6UnrXc3qSx3YkvXEQqYY6j6z5eA8BAEQu35vqkwqZK7pC1cR0RF0Zl8Wx6X5fBQX8%2BdKVL%2BLruf1c136E4fEr1%2Br1LVq5FWuVIDYoMHGigkf1gJzxEA4v%2BbHYpI90OlaK42sVK42AAIBn%2B5ugDdABH5vapZzUKSSA9gIk10uS2KXxV82NFtjYgqTYWXIN5TnkAL72St680xrkB8iLfHQAWwpnH3G2wK3twai5Mw%2FsWI%2BgqDB7TBY48u0N6q1b6XvCmoXv1qrXu%2F1lju3Teq9LeTz%2F%2BiZSffrmIlOSPOX%2F8vHvJ9Mn6m7b3CTuFKxdMHApomYzRLOozWB7UQRhq5pLQ579rQuTvu9KvRfckvdr3axVoR0R0RLdeqdCFrnIv5LLkvhcQGxwYEhQaN7GO6SxN97yV24lUFgptCBkHHtCGDvDm1QEG5bSxRhJ4ITVD3qCoMqkuvsUv6%2BCHTHl6eIfH1B1ohwEo8uLWL7Xm7%2FwwXKQQ4DLZzgH%2BqVfk4ipl9ROjwYGhN%2FStQPNlAJckP7zVBNQssw7LwmapogVbrkpqSPdo9VdUsR6uS3KqL68ME5Y8A323ZYyR7%2FYJr6NgLlyfF2T577JaZLrboPX1TgXUOS1pwJyzgiLCUzKKElPD9SmxACnRwEEeo%2F7d3%2FyHOCA6X2IxWq7cfjxaHPMxS1bTRymKXeTj%2FU8Yt5RqPDB9KlnVhd5fLe%2B0LarRJXRP69KvibFE8AUYGOrDQINXfxYvqq68HBgUF1VxWTlvmU2XGROOQkiuXHc4fE5zhcHj5w8kVOHAsX%2BmY8Mu74cUpfWCm7g8HhKA4d1crCTMwHs3Sd6fL%2F9mnz3Xgn8Mci8ZXfsJsnr30J0DvdDNvs519hRgEDn4LbtUXu9hSuJu%2FyX8IESXY4Pv5fV5ZGenRqCjApxmR0H9Kmx2pbvsENPb4dr3LdovXs656xGrWrwnye%2FBHSDu9CBBWZa7wgajbu%2FBKvv8KYrJznnAPLAAZMCo6DwU1ktKgZm8u3s310pRyF6hXzUuFZYABGDa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6btfvDjr988yOoSRDWh4%2B33cM%2Bx9UKHSfZnnLCTFq7KnutpUaadd3gVMuy0JquS%2F%2FDHaAIQU7%2Bc5Ax%2FoRQFGcab1yHDArpQAb9ANi3X569%2Fz7MG%2Fd0Bx7B9YAAQ7QqtOdS2Ewf3GAOI59X6VbsJfCN%2FiCFy%2Fq3rsilLw9qtE2%2BF5PFQbHFGnt0qrmYfKJBDbu2T90ogDgLAcbAutYQwkQC9jjFqsnWvmM1I942apuszaV%2FtpA4ABFpn%2BHSZwXKEy7xLmZPOhOHRRSkI%2BJZSOqCd%2FTl2laeNCLexdtttPvQw2DJMnahSw2%2FH9rsuwmdyTVhFpmckfAKLVzHMcpoKq0FfEzpAUMM3vCaxms6XmDL40VH3ZDLHMUyyVtnyq1Zfy%2BHs00vJ5paXe9V7aZV1ImenGZbIsOz2VVmM1ZbQpm6vpuPG6l4xtna7rHDTWQ1%2FCb06Pt2WrEgyuqRwtZDYVMskupqQ3zT6C3cOVBRBBiWxbShnkofKGSi3Ga63T5eauuw6ocHs%2BKOfifeQdpHVrej5XITh4HJ7%2FE4%2Bl5sjXL3A69ZZcfHOtAJnvJC1ljtCb%2F%2B2qcIpQQPMYz1OBual6nAEg1JBGFCsRAwFkIFgoFgqKAuFQsJxKEQkERGFtx4rjvchVZq96ycYl5UcxfGaqdDmf3P9FzX5%2F8o%2FRf%2FeTx%2BRWXd%2BD6v5b%2Bt%2Fqq%2FHfa58e2nzd%2BvLZC%2BWi%2Fh4TDt58f782Xkcmzypo3Lbnid1l%2FdnGfGteeRvcpaxlmFv66D0ArlU9QkVE1PQGjlONxfT%2BdSHPkhr6Zxy17iGkyVrgFqmBhCpy9fRKr3XG1dbIyJ48%2Fp4ITO99PypnsN6wxa4sNS%2BEUttvJAyiTD7jK%2F27b03ecSgOBl2XA5tXg6XG%2FKxtbLgpm9ZFdKRmotzw6tp7ulzAKE7KMRqoz29KcZtV6kDgAR4UkC4WChGEgWHQYCykCpGI4SEISCIld9bm%2BPn25mVdVqkulTVZKxXVSRwNOux4r%2F7%2FK%2FlHw3h5%2FZh%2B6P%2BM6rPfTRXluEKj5E41DxQl04ZJxo%2FcRul6vXH6k9330XVV77V7sGBaKZNcHQZIARP3MxmrcqKTDK4KqEiNo1dfLybnXu325lH3%2F5vFt6nVUxBvr%2B%2BeHds9s8P2wtHjqV2%2BH0sNVJAHOeZUAxNfdZL6ZcLQOfIqTwNDJy91RqmCH%2BfTfwbw4r3%2B8UiFBbjt6VKrLX0YZS%2BUVLxz%2BaclBtNBgIo5HDqlWdNQCGFIjRmE4Z%2Fb%2FQDgASIUkCoUIYWNQWMgWEoWKoWFAWC4REQRGnOpW8qpKxEqSrqa3raqmeahOBwPrav1buf5X9anZNsr2XUeRdWgo0ZWqIw3gX5%2BvYId03CZ%2FNWEnlz02S9jSXduj2ZjSf3LlXyTuWrv6lKcAn343zL8enx7%2Fd0ga2SDcOJdXmZY7pIZWIiLiXoqpklqQFBBTvNCQjiu5jkA60r86qIPqST5Yiodl%2FRWh%2FWZ45IiQclXlolotSI6XSdKEADc3p1zHnSjqpQneWqiibGITOfuy19OCkzzibleUfmwvLPXx5CuyXzrHKeAdanQ%2FRkk%2BmIwRloox9JP3%2FaAOAEgVJQoVhIFhwJgwFgwFjqFAqJioFQmEhmFWVdX6vEUq1NVFddw2vOoJ0Hz%2FffUP9ulv0V%2B67q%2FqGH0792E0myTMREGgwWelS78L8VZ1PBpCbQGCiPVk7pbB%2Fb8STUeu7Co6drSFfizJboQjDP8Y2zyv4CTmFgbqbjn3Osf13Jc8EXnjXSAuhvjpGIvN%2BkGfZ6XjXjvXZ00upE5ICj5wSAt7Yz1mZ3ZrmgF7EyGzKE0oXCu8sAMUzl6a%2B%2F5elFsqNiUQPyTeSzyucvZ6l8ChO4VlNhcCWEXOXAcZpTaj8nu1LT8ZKELDEUBiEkjxRiicLcZo%2BF3AcAAAAoKQZogCAoFf6EsXd8X%2F8n%2Fff%2BX%2F%2F%2F77%2FViWie19%2F9f%2F%2F8Sr%2Ff6u7%2B%2F11Js3daJfCHfRF%2BvfovcAsQjwF0I8AQ0FPguFG8CA%2BdqsC0IKcMCi8Kg%2B4mkGsA6dgVAfbXgMMdQPR2z0KS%2FNqMqv%2FApCgR177qTj379DUpiuS%2F0TL9WscvVUikZgJ61fq2O%2F1%2Brfr3OvVyZPWgqL0beRthcRB%2FcIJXuhvlQoHXSLvYh6pWpPwhBBChEKkD%2Ffl%2FjR5iTjj8sn%2BLxUzx84xbf4AQoDoKbS6Q0MdxKKYp7QpinRqEn4DEflFA5Q3kwNPNb4GQ6bpKyoeSrLMRolBlJ59VHGj2iUlwKptB35a1JEWy7rAgAVAXlG%2BGCX4A7NVbfbbR6pjlsKCBCQA0PDQhjgV1GzEve%2BYIaUoB4AKPc%2FKurul0ccesQLCqG3aK0ArgERg%2Fcbk8Z45Ttl%2F7MBKQn3%2F1PL9MtM%2BExoK1lqBsO9TxUwVDOvWl%2FwO5QETD%2FGd96miHxqwhpleFCpQhDzAq3eYgONg08TewjN8444lu0gkscG4gN3RLgMGiKbD%2BgzvLaE6r1bo5XP1932rTer916t83fP8isW3f0wWmU%2FrqscwgjD7Vz2%2Bn7BDVeLWPEGCweKs1mQBztinT3Fx%2FKoiUhE0KLFXiSZWRPvcNCBs8sFhlhihlhlmKGKGfGEtAakX8M4oGBj1u8DNUD7pwXXU5nXHqriNa74SMr7416c%2BYX8TMgUfMEizxi2CM17Amges8R5k2wQQDZcVhNqHSu1O8KHSqcmN4oaZZpgqDXf0fb3Lwr9xuXyoPeOsnkhWf%2B6bvSDdJT8KjIWi35Eciu61RIrybojHd1WuvQuXjZqfFLz%2FCl5ignFObwWEun%2Fs1hjiZPHl5fF1l%2BaTtC%2FcA3gweLgoYB%2Fq2f4NeX9IGZLGPcACdA9FUINP4dblr4j%2Frh7dWtVyVasYomq69X5HluI%2FyVy7%2BX5AoIgksrgB1cmG4JDEzLI7aFZt%2Bt70en%2BZ9FoP5tcQJhSLgDCOiZi98Ghoqxdsm%2B4xwqWjo0Mh46kIzKAMoDOilwIYvgONMy%2BQfKm1z6YYH2YdMEqMDr6K%2BT9CarJk9UobVzu7xSvu%2FXK6Jlte2kqLJwSfM9%2BTLJMy1elWb%2BCysQaxB4G7C8DPuTWCEvpAU162Clqu6uuqT9FryFvVak4tXl9al0wSELE0ErbfVggzpCaW2ysgxRlI%2F5bJtEqSEG8fufd4%2FUNGBKGuttJMI%3D&media_id=1254206535166763008&segment_index=17" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:32:03 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:32:03 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_KsVcWiAHkZiPvRE5yVrImA==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:03 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786112316524788; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:03 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "c0120b835ec0cf3d4dae7d40bffdf65e", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19935", - "x-rate-limit-reset": "1587864356", - "x-response-time": "33", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "00babfba00c09c44", - "x-tsa-request-body-time": "95", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"37DTxBkueNUIQqQX7PWtEiwwkqE%3D\"", - "Expect": null - }, - "body": "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FIEki8xz3I8xPb%2FqCFHICT1imuW5PVx8FBOFExVcsGYt%2FQSvOXP1qZmtbGYh9j5T9BbwQIWjgMbMrcMdz5Zy%2B7via3RRbAbSVT8Z9NG5PdvSPG5fKw0W1FJhFY39lzDCO5jpSfEa%2FGZRixyZl9esbFQbBxfkXyYKC8Ykx8FQMZt9m68n2v1dyXQ6X0vrqYv%2Fr2ry2YnAY3NXJ%2Bvvhfy7lYThH6GZNydbogrN3Pn%2FD0YlF%2BPXB4y4SHMpjwkuqGVmaMbPDVMuUy%2F%2Bo7H2r68tB6Je9BnGbnTDJ1D6fT5QyvIh%2F5PD9RAiGxHiYTeEW5f23wVXkG8%2BQ6DlUDA30toOLXeC%2FdhAY%2BMHV0slmanpW3SJqYyRNVZCEhuKmv3%2BzArXRWGhDhHhPoOhbH0ugzmtgxiYXhQgnrCWpChjVvsxKg%2BqFv%2BiP4Q1Fq9Cl7V6v9WJPVitVytYSocCjzU1Sgy%2FNmsosj3b3eX7%2FCWY2NnlwgLBB5U8n1%2FTjUpcWHgV1KKuLM6YAZFfSEa8FP7Lv7q1%2B61Q0IPBtlJ6pVyhbbIo3LR6Tyx4BG9W4u41WxEPGH69RAL%2Btug6UqmX331MaTP2nG7eutYvUsVvZ1E4wmG7rW0Xbwef575PlXtw5GUxt9S6Y1S%2BT3vcUgxYwL6L%2FaH%2Bg%2BZjKnGXlQv5JeE48TmXu4%2BFSoGMe5TtAGm63%2Fb8NWZNR%2F5fX3EEF71XWlsFiIyOspfv3BVHYlY%2B30VtHbiDl960doS88938T8tPjgqyVWvCosQZVWqr4kSyKv4lE7XPWXxAXnOIOgUFFMenRhelOEnK4XnThWfGTmYsxBzCApxJ5RhiFL9QIjpFbQcXWKwBxnLHJ%2FSOCFWfqiq3xpEzz%2Bprf7Nz0lNEJYnvim%2FwpNi%2FpkpJ9r%2BJKziLZ%2Ftg9viSPu2m9%2FkPZXr2UNElUTM149%2F9uvT5oupFy26Qg1QmdPVl%2BNu8Qvq42dTLZRaGY2y%2BHG8H9z7Ci2nJ5fliLQQO5XwEckMR9BbDWejCM%2FO%2BFgyk4yaWwdlqUntpnJCQd4d5qDi5S067xjS921SDDs%2FSKla%2FJE%2Biu7%2FuEvX1l8X%2F8sEoguXd3eRf2CUzu93yJ%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cQ3BzRppOy9a%2BJ9fzEHIfNthlom8Vr0folfyXXF0T5%2F%2F1YZQ4S8TxcqIeJf22mDC9pkcVYYvPRpmSf687%2F4U1Y9E6FrRoQBhwxloumQaH%2FJWAvv%2BDCWiWGd0ZJ1JW21%2FUEfNmLe7heXL3shrRfbe8n49FaibgbnLOcsStVl0HablcmhfxM8EdZdeit%2BvdLXq3dzm8lLVTBATKPNcsSW5Fgkf%2FFYdILIgsxqOFD7DGUEAXgpatVYwYGuR%2FDPS0XDyfSv3lLp1OoI%2BDv%2BuxRLHJzdi8jPwgd7u%2Fx3oUljpr0vKIKQkP77hScYIanyvLwqIcV%2FjUZFDyfJy3%2B%2Fclg6DEcnkQKJBlBQfXB9iDi7ioXU2ZiCciOkT4lAw3vloW19OMlV8Sgh4cXistA1LUeaIoDk5q2T20fu7FLXr66re4WOi94WRRDv36gkvEDgrfJ%2BIvahKrMLzN9EgibUfphegscO8RDePf5zshMbd0qg8Ezpfy%2F%2BHqCTrJzVoFW9SmsdYR1se0HdrcbfSQGzZieMn%2FXxaNEl3rBiGKzOt4j%2FG9pzcQ1FUIhr%2BC2s9pWbfvwTEHl1m27JspGTt%2FtGXhAF4imwQfhkp0Ard3HnJVTpv65e0C%2FQhwY%2BQxwnKqZMk05m4Jf22py%2ByLWNIFtUjVpuIQ%2Fp4%2BMJAWHpCOJ0TSqwSOn3AN%2F7lrxNd%2B5cFH9DpmmeWHOEVzsc4uMvyL84VLBVf33spusWGNN4Yaf%2FD0EZu4%2FD6Ziz0SdUO20bL2oopqcms3%2F9w9vxxeg8ONAHab9mcVxCxlB7NBHrDK%2B4Y0XbLi6vJ6s1%2BvVyVjff6yvUEheX98oglVVVr0VErwjRG3j5y6iBEewj0mz41jhHuGdwZFKCWKMUZ45mngrQr4sni93QIhMIXDunsPjbwwMaBp6kZteGV9arGjlOPlIhmSoWMH2mT%2Bvy%2Fr44igcv8cIMAQdhhh2yJ0%2B91DJYA96t4WAfbhu6oefqCvazX%2B9vCxJL305WMsRu5%2F%2BY97%2FFE3bjqZrUz1BNaI4%2B9ZT%2BI%2FOVU0FN%2Fv8JmLzccn577yfC14V415a1h9sC8Gn2q2FX99YWjJEN%2FNKgon3UHrWFzIkGTWoq9wT3SGmRJffE9sv%2B0oV7iA%3D&media_id=1254206535166763008&segment_index=18" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:32:03 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:32:03 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_ZUua6hlDD9lPcQsr1bFN0Q==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:03 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786112371858353; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:03 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "de49e6924451b60278002f0d21941e4b", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19934", - "x-rate-limit-reset": "1587864356", - "x-response-time": "32", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "00986fd2001e1949", - "x-tsa-request-body-time": "98", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"82J3IwDysMO%2BYS5RqBpN972%2BMcA%3D\"", - "Expect": null - }, - "body": "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" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:32:04 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:32:04 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_btKxKQN4WSAhttxQnJzZMA==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:04 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786112426592690; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:04 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "16de19c500e60a675cde556a1e57ec28", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19933", - "x-rate-limit-reset": "1587864356", - "x-response-time": "36", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "00850af00058773e", - "x-tsa-request-body-time": "102", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"aqBW0PUIyzdXmrR%2B9Or4LaSuzhU%3D\"", - "Expect": null - }, - "body": "command=APPEND&media_data=UOYjhFRQ7fDQ%2FtcIB4KFwpqbg2vsEDh1AQdS%2BmBS6vTv%2FMUbOmiisTHST9hgjw2khY6g28plfQZMO%2Ba9yy9nSQ%2FnIvvI%2FJ8vvHAiIzwfemG%2BqZbjC9%2FqwrfGCXP7JDhE9qLjgwvC9PzX0%2F3wPv6FE5pvLNfQSNXjoJeVcFar7V9X4LBJaBxlvnph4Q2vGw%2BNjdmorZfy7IH2Mv%2Bbobnyl2UVKu3r1evV%2Fkum7kbr%2BCMt3sSSnEK39H%2FxF6ChXd7rSHzx0A7Tw3W8Ttoe6f1y%2FcnYXLWsEPSU62c3%2BnoK46ePDR6j9zo53vxfu7otSfrJ%2B9%2BNt7gNW9KA4jAm8YPBAtvZqjJCGVP%2FyYMKNAcbzgCPi4P04vfQI8N8f9xhMd95e2v8%2FfBqbVbK%2BsEE%2BoZ16VCNqo6zox%2F2s8z%2F%2B8%2F%2FIYNIQ3%2FxGOsvefPRKoy7VWuLLHG3XRsDf5P0J2TdK83ku%2Flq%2FrJ7aXgsJtB1ClLdGrNcNpAUA%2B9xmw6YeXiMGBswvfPuQQHglOh0SX31cEXYMBIj%2B3%2BCONkfVe3rlz%2FvJsJFnfMzy%2FKFNzBWHMXty%2BNpp3d2apMFhthlY93J88MnqlrgjG3ulDY81OG58fZFYl5Gcn93dFNoIeiyft%2FiTcc8OGX1deOLRqk477mY18WjbpeNSpDXuXu%2FZCnxr32Qx30iw338ylBXat%2Bvbvpd5hUJmCk%2BUE1vXHlN43yfjq3gmKCbJ79%2BVg9%2Bsnv%2F2%2Fb9%2Fyeal2oV7RsEc9fUaNBxnubvbqIOm9m8EBDqQr%2BoJCWpMcyeS2uI3OIHe%2BT%2BW%2Bhht3yC4JvGfbgdX6%2FBcf79K%2FxtmPMskqG0goHPnwuZsqtJP14IuTDjOXvTy7NqbJvVa5OZDWn10hbXa1Jfd%2BKNaPDXSXgnq65WN3ZZP%2FlyenL%2F360sXeh7o%2FxGeHpvL%2F9Be6czPL%2BuRQ%2F%2Bodx%2Bm93X0%2F8hIG%2Bk%2FPfDeW9ikvj7Ltf152ELO0oLNVf7o%2BJekOXXvxZOBgx9ht418KQSOO6j7PtPJ4139l7vsJbvva7XctJVxXouX5sT6P%2BiMy%2FSa4867x6Ouk8BPXq0kIq35BJff12DF14gJJt5c%2FcEd78tIiZAko3uxr1EXfe%2FUhr27v7Vih3q%2FRHIm6X0hJkiuL0rkpXfFiAhJma2v7I76gEcmf4LGjEYwZKpm0kyntYcsUuLlt%2FDBchgEQFu3H0xc%2BSd38zdUvf%2Be8paBMMWCgEHWljzy9553AFAmjxir6kqXTx%2Bf9%2FYoPoEJvripHPS21771XIE8d4oo1sJMQSVBhMkpbxiUkYx%2B9e%2Bx6bgCC5Ih0KRIkX44gyDuVvPIwEEQyuVbrvGu%2BwEm5w1d1FfOeinqybDuvFvd002d5KZTZzYAP033Iyy6tl9IIaLo4DLJIGWlb2fjfEFFaUochPr7pjT4kDQ1YHq%2FAgdTnokcjj7B1vgog6XyELf6v75oozAnQM3IjAFQ4Sm7jOIJ%2BTp16aWCwCwNSBWAJiQTAHt%2BWQcARqZ%2FisYLGC5UmXPK0rJ50EqB6RiHRjyRzFlh6tDisn6djdrLZWmZ7vKl%2Bj48zPPkjnI041LMR5NrU0cbfvG7kV%2F0aqzxXUe6f7JmY1aQIk1IVvS4PVRr8ds37fPkmr7uvVuJ5fg9GND5YrS3ShVf56jybYC6HEgGimo8zjc4t8Y8JS1ncHbw5Pnw59ePCvkDtnoCyaxOW6kNt%2BY2wKDZU7Vl0GkqsDLgNVFdFcoGqrwGdJyglOWxZCLctiPYluhnJ3ivr%2Fo7B9hv2DrMNg4OzYp77r9lHC9uGTwNbYNT2tg7cS1ZkQvNIqS71DFM6vdFAsdmNiB%2FXUOhDr6HBhLUO0HASLUkGoUEw0CwUEwYExYCgWIQXEwnCwXCISCIiCIXNdctzEmVUvJWsuq676ym5XRLrgcDorU3xfkP9U3v9MRw%2FX4t7bvoBfQ%2F4TXf85dQVJaf0SZPIub5L%2B92uwq9c%2BdvGa%2FnhffUPqBMCOrUERQWdU%2Fwfydfat1Qgl20Stuq07shRWaFQHEPfY3UAbwe1r5qsamrz5U15Ma1vg%2FExkoHt%2BLtrBcXycMqAxnKiVwcAF93iA9wtFlPtKpOte6PSRwa4K%2BF2O3IVKZ0AVfhb4e%2FySOAR%2BDjsxJhMRSbhHK8a0VoWzcQTKmzw3RI16Ufpdsjhw5z%2FGGgHABIBSYKBYKCYaCYUBYkBYiBYKBUKBULEUThIIhUJBETvWXzVdcmt7lWXSVdXVKTqkp0D4fP9Y645pttHvt5fO%2FiE9Hwa%2BfVYMwtPlH3L1XdXsx5fqTu88nfM76Cp6H0GYeuWm6yOUl%2FAsw54NIH3da6PwX8lrx8HGcTDfTsHA99vn4mjs9%2F2ya%2BGP%2Fp68ON8DuTcWqeh1M%2Bf8xecq%2FJ3CIhzgAMlNgmHkJ0yCkJsqT%2BB4gAEE8kgHNMTDSJ9Y3S3R8c6cfhPzv7pgGfub%2Fl3dm88A5%2B9StM0qKtcI%2BjFOuCb0eD2rqXmgjnTMEOkJjKZrx9IXEvdmBwAEkFJCsFAsFAstAsFAsNAqFiKFwkMRGEQqvdazdWqpzqpeSrmXUoqalXltDiWgdB%2FvfpOWz4XHD4FyoSnZi2RfCpPlrjLvLu78%2FJV%2BzFTlL9fvo8M6lB7OFH51WzdmgfsH5XaR6XBZc2MPTbv%2Fy765lcE99V1992fBmvBD6S1XJUJ1Uvopd%2FwdQ7Ozzhx5dMIc%2FpR5uzRUVx1BroIDlE4Csdw3BxoMCmpOZ2gJ5S98%2BQDdKFV61AVlAaEzwjn0ufs16gqeBhbKMK3d%2BF30docoYo5inkmoOhAVgmxhZWfHO%2BhIvCtdEp5ur8QdfNoBwARwUkEwTCwnCglCg2Mg2GgWCoWCoWEohCQRK97144yrZMrLlC81kuqC7y6uuh%2Fo%2BkRr%2FxX7%2BUzwf1D5P8GlPs%2FT%2F%2FT7x%2FWPbC69L%2F9%2FyYvptWJP8k8Ns11Fufl4YL%2FVuE13%2FY%2FnhXKahT9%2BFVlQeafD33ZzcQRUYLpInkpDy1Qn9a%2Fmu9%2BKmCgXFUNM9KOcNcq7fZSuoxOrH6NeE%2B1kFrpPB58MPVHb6LAncrZJK4muB%2Fpme0rQK7eJPzUhB71zru9rBTyj%2BnpqCWey7u00lHdRfAlRLbhCM7XOTQtwa0IjhG0L8OfKil5O2bGDgASYUkCoUCoUEzECwUEwkGwlKJCCInXPM47VMvKcc2QlLrJUcKuU4GsPc0q%2Bf5Pw17k6x0clr56Mo7aaC1bflx7ulPG6n%2B083hq9LyaaNlr1duluNf%2Frt4XzSt%2BueF91%2FOt%2Fge8TSLhboy9l1WSGZBq6HoDwv4Nb6N9tpQ8BUorzoC%2F%2BeoXMVclfXQIXjUhvI8lQzawAHfyX2X1%2BFvCL9imIr1nnf2bRng85%2B3r6e34YMzA%2BU0ny%2BBfBPp1%2Ffs8dbYEquifbCjxj4DL0fm0XuranfAmq%2FexGWDnyGraMnkO0%2FCDgAAAe9QZokCQoFfdCPERIuhC4QWv9IRuvScb%2F8333%2F33%2Brd8%2F17986xf%2F16yiqrT8sQ23iCiowJO0rsEY3Vc5Tulrn751Y6ld2tSRvdaSsTWr%2Frl%2BsVcSvfq5LqYU9r1BHz0Zy7779CN%2BQQsuMIWuRu0Jyq73Vu16W5OVXMQsvqyTWifN99WhTyWjv9L3xXXVosXP0lerVy9%2BxEvr0tV5asVa1c%2FKhndaGxUT%2B0v%2BRSg74Fr7Xpbv%2BHiVr9YqvvEd3Prd%2B%2Fjtc9etchk3rV%2FJ61GbiybCDLO8fkRtqs%2F8pJRiih2aUwrukQnCWjOerit1iryiOb0J0K0V2d9XgtKWi2EdG%2Fh%2BCauDV7O93rz19kaTfc9hCwZJzeOplVD41Z7vkRemu8fq4tsqm8H92mdhgiBDg7PiwJe9B8YcxCEnDXP5MOa3KL8xqHZ1K7pPf1wU73pO7uh4uvlBNe8Vzwv%2BCQ8%2Bbnf7EXSS%2BK4b3J4wcmfwxGJTqdq8h3KfGTP6EiwQWDHH2UsgZWWjBro0DWMxPXhqensIR2JMHDDabzlIJCRiDaMbuN9HerqMvXJ%2FXWmEjTRafCVmsnwm%2FgwjhZ0%2BgKO08phnDSG9Rx%2FFx4nsLzD0j6foZDQcQApWCBjWj1e5ZIUUTDo%2F27Y3oCgMNtfFDAe7FdFGH2X2wr9cU6UBMqfDh33f4fX4%2Brc0%2BvdY2p1FkDKLr2L4667AgGxcEPjJWRe4I86kinf3BJuM%2But2SOKwQZZr1Ywgq%2Fh%2BcYL2bh7lIN46WepLs%2BSun2A5Ew4f%2FkCZDG95B2KOICei1JmzYZ%2FgkLy%2BLzZEkE2Cgc7Q3nGclcRxcJI9313aF6yeH5UGKIZHzaC8owR%2BbdjFA1h8ai5tZIot4Omf1ORjSMBMo2RGOkTUwkcbX7DObLgBZkjAOD%2FlSnuKqsQUhi44AZvnrMH4E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Lm5OxflzRAxiJ7DhA5M0BqszEWKYuYYh9cH9QX5jVoPppXqTgGnTc2YZcvDRkpRhHwwwPqyFp332HRKBDzXjnIIcNrRvYIQ537RjUde4iPiR5dwhz%2BtFskxBMrf3k%2FMvo1Eene4lBgrBj3pt1M%2BNyPmwtl1x9scnRVsIaxewWS2NMgMb60Ahhz0OZbdwz2yVavtEoWgpVF1Qetmrup76FSMpojaRaRhvzuSei12vVaxWOJsPEdq181ernP18JVOyFDZpu7usbeS%2F26QIJJwx4XA8EflG%2BL%2FRdlrgV%2BFl44PmkXH%2FWF6a%2FhqYK%2FaEAUuZfeAgbP8ZPfufxLIF43V3DEZEBcvBQF8P%2FqzQ%2F8E%2F42mdPzKa4CseIp5yb2RE3%2F4s5WMl%2BIcfZLsbrQlQ3d6jBC%2Bo80TBt5JUIltA0goiE%2FOMIuao8sZ8L0ZWiAtt4wT8Fs4fldZPp93fmb3F23vtk%2FcJbv0xoIT8QWjcb0wm147CVbqCXt4CUNTJhej0oT5KSU4pSw7R4dtkO5BqHEzPVXbyNKZDzuo54eeCWqJ77XxJBh%2BEl4JtVcQofFKu7nzKP0GliFsgwj5F%2Bz1YauTXGz9hoXCJisQHR9%2FMqRspXI2M5jYZi8SdUwQbAkK8w8rdQvWtm6yHuXFSYvdL%2B7qNIHb9XoJhz1QCtp0z7zbfdTkcbeSJOo%2B57CxY6DQTfPJjL1GKfyhAFBF219h0z73drP43Uqzw%2F2xLv6w8RPXHHUQcHLthxpMiThDUvIgE%2FVOvXV4eKS2SCYQ4ZOuqqK%2BKW6v9fQVMGZwXQiZkws2%2Bdp9%2Bo%2Bq3ypkaNU1MZFdsDSR7jO%2Fgvuj5iV0x9I9%2FcNVjbU9NLDLU%2F94ioVvFHlmkGMngNpm4036CAg%2B%2Bne%2Fouv1lVE479XN%2Brlar369fq3DXUESd%2BVbehoobEBViJpSxA4F8ncxw2izGEtNCHmf1tuNKCUdj%2B6xHjZy3ovze%2F0cQ9Z06LkwC76lLeJ%2FnG5o9zkUrFIdydJZMYhPjFtgOsNKf%2FQSkHcGwe34onsh2HKdIMHpUEA9Rs8dROcW%2Buhl9BfS25jBn8UV5MszvuECapu8g36qvxda93pqgS93XbPt%2B4Jissx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6535166763008&segment_index=20" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:32:04 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:32:04 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_RubdtmVo7xLllW0nuPhsag==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:04 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786112477907001; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:04 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "c65b1cbc4ac20682c2d03905d057500c", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19932", - "x-rate-limit-reset": "1587864356", - "x-response-time": "31", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "00e2987d00c48b84", - "x-tsa-request-body-time": "64", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"Z0H0fP3xSb7nRUMGCmS3pe8r3Zo%3D\"", - "Expect": null - }, - "body": "command=APPEND&media_data=O5e2yDrPVtFMZ%2FqPrO%2BTJpO%2BvBaWVmbvWVi5%2FRIPzExpBHeFCZi4P8Fl8tKC7f%2FyxnT%2F1fL%2BT6sv8V%2FoveDHLlr3zX6Lqbw4M5bXMmWv%2FKWwMZDE6yWhPV4kzz52RF9J%2BCIZm3Yy%2BFvLho4rbKxrMGBQEoS%2FXnOsuziA%2F8XYMbON8XBC3U18orIsCRs3b%2FmFxksfL%2F9uyuiuwqEfiprripPfLn6K5%2BvflIfO%2Ffe2vMSfP4ITu7oW5%2BF9AUeVtzFH9%2BWMcu7Bbkk1kX%2BvUN33r43o2G%2FlPX3uzJ4oQhsOAG1jhIWtu%2BCmTLF9LNP8ooKGtbZVDqyrmHtC8QcLAzUPqB90gUlFrchxk7WmvpDLoi2T0gLNtesyQn938JG%2Bs74JqeifpL%2B8QJCAQK3ARf7ATC1F5f9TY01K3pYzgd87CEV7fH4777e1gWs%2Bv4I4c5%2FsV8bZiu%2BvXKvNZmGD%2FXvw2XUh2DDrFEKuNnlA3Efnr95IZZQB975r0%2FwT7G7BpmtlA7Kv8EnNr1%2Bcizszv%2FaGuVykGQFPrHUyZUca6svWLGGScgsjvD2lrxtRAZ0kN%2FsrzNPaP1mXl9UouJGe7LatqKf%2Be2zAV0nfaf9xWhjYwqqqHKpqbUambQpvzJHNR1ZR0QMqqi9oXFys7WdJWq%2BxmCoiROEY22FHTENmW4sWvAY08VTxW%2FIi935Fr%2Fe50Yt6Xcp9o4xXdaNcqLh%2BsHfcnnFKMjB3KvvwRlkh9%2BryeQiG%2Bm%2BJEu%2Fe%2FzElv7r30YzTVHL9J%2BC%2BhXuuA%2FpDuS%2BPmsdXo4iwZONUaLLF9BnGZfR%2FxBHULNWy2YO2Pd7lj5ai0FmXTlwa0HbH0vv8feWprcuBr8u9%2BOgh3epqk5pJNnL%2BJEIkQ7xxet8ICcS%2FWqqLi9e4QxzvqLtRdfYsRw48J4ot1vfoe0%2Fq1%2Bcy%2FCRZUP0L6t%2BsUvnr8qkYGxrwUWOxtZMyp%2BvqINpNaMda16i5CT4%2F1XraURRb7nytrNH2gVX9%2FwR%2BBinLb%2BpqOTPTKXmzsWQj71wmo%2BfC33d3Pl8voTxaGipMZnm0%2By%2BoQFvMECZe13tP36CN3J6Cec7WLvtZX6EZS%2BevuCyJBkoa%2BHP1EDbvvfmod2X1Xpy5qtE3qiGEXfXIusUTN4DS06N36CO7FPdzL4iX1tEXKvDEly5avyeJYSNR%2B0EQgIBIEEB7I%2F3IFQ0QfFxF%2BlwbfgdWx9kJYC0yU4lpwAAACsdBmiWJagVycShL%2F%2FS3Ojlrvvonurq1erXV3drXffax%2B%2B1rxFX%2FXf%2Fq%2BX9b9q1euqor9a%2BMrnWpbu%2BHznHSVUwI6%2BeTbtjcCqVgQleze%2F%2FAi9YFkoLgahwJOKxxmDt0sAc4cd7g91vDzxvaNmXIIueMLbvU80DE5UVH8ICU5ggSGOkO%2FyX0a%2BShz9hsXiHIsgCPINkD8JbXVE99osXL47IEuvttoURzq2OUvevXL9XO1JWKUv%2BvbsCAHgRCuFBay3ggCx4KrlpVjOzm8E6PsnVsbXFk%2BsUOEIbBW6vH6x3HMDbKFlanMiS1JLWoFk4CZahqMUNoG43womwMfzLqNWT9MOEDhwo0EHHol9ajkRlUsMqlm3jKpYZKlgboRlQYtJfNqJE%2FHCJJMHJ5iHjeb5jzNtPxFXlKTBZhuYHiQPehGPyJiQGNLB2rE4ytNkvhMGh0CpA8Eh%2BMZ2raEaeXRonR4Dy2CePxjv1PJ%2F9Y3%2FgRGHooBs4PWDdj3txYO8DgAEKEAwAMCg3qf3iHTnclKYZDhwwXI5PENGxAJIgLzzhgD5pk8cnHRxmnJKVVW%2FRaqde%2FX52pE%2FVy%2FXKrvpW5Yp0JtVyoQcWElWsxlHQh053TT%2BcgaERyPwWhyoY%2F2Te8YcNnChSwYoywYoxRiHBRljOSJXfLGKO0ImgzlmnESXquuNgfyxXUHulLmwNXDmVNGBRLwzd9QmGw5l%2FEcYhMv73%2FZa1wOByF66SS1i7r1cR3y7U9J65V69ZPz%2Flur7XXfeudQTjuJsy998vwX8DDD3gmIQSfAdefzkVIcl9obl9WhOq9a%2FV0nq%2F0vXfL5a1dxHrF3V1f0MCGVcAw2YYIxny1V8lfq%2BNx7XT82MKisYMhZH4G4%2BCEZ4L01KbgyQDtOTX866ynP5C67aietXLr%2FjuDYS6Sr%2BJQVqr6I7W1zr1c1e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JijLd1nnU%2BCvmwVQ2yZfFoc9tz8Id3dQtVo2hWMeZ5fsaJkihhRvuduDtjpSsLav0KGHP3qiXC0L39mLLzzzvezFXJEBCz3lYn2p3rfshhA0ZSUT7%2Bhvsditj9Zfr3atLd%2BFSSsWbZqffOhaMG18R67cvp0%2BTTkZ%2BvZf0nr8ExaJ5%2Fe78FGw3RJlwZ6rL9Gg33kws43J%2BJfi4M1Pz573H4iEY%2BMHeifbiKAay7F%2BeIJkClI7wYTiHZL%2Bu5qv%2FETULnntA5ff%2Fyvys27%2B2CMujHu75RBlXvC7lWj4%2FTvxDkbyvy%2FF5ziiu1WvooQJux58q1S%2BgiVK9WltFi74lS1arr9cqtGdXrWX%2Bnw3cua7R8%2BX6%2Fe6VE%2BK%2FJceufu6TR7%2FUhVui67V5PMKvf4Q93cBVnYf0Zmj%2FwTESNTtQaZlFl8ly1HeWmTeN5ujeqhu5iN1%2FTFuvDxgQbuB6GvGooh5SAGo9yHAFcARCtr%2BJeS79DX79Vg8%2BSpFZJ5b67RGv0WoryX3rwfd%2BSCgLbgfGuNAw4wqBgWjLWESglHDd3hvxZnaHfPHAAguAcAAhQqrB5M%2BkzjbLv8AEmFJAqFAqFBGFAsNAwFgwFjoFioFQsFRkMQmERKszKq3HiKRJe7qSsvI1KLlj8g9f0X0Oq%2BffwPrW3VHfd%2Biu1z9wSrR%2BOak%2Bs%2Bq4gR2v0wHTIGEtfPhL1dGxTT6Ssrr%2Be9awAzML%2FSswNvyT9cCB82EDPAjN0aJmWwelyBYIsBLQtTiQgFg9l90EE%2FOdiS4IP8nybVmmq3LVufbtxjz7rvt0gh3JcITtXfgixu8kxmI119d3%2BeB2wrz3zlPBfDl9ff2xZdVmk4MmND1ukFTXoIstrSnJSQtXv1qzVvfjo9FqRThvkysvn%2BgHAASQUkCYUIykCw4Cw0CwVCwlCwlCgSCISCIzCbnXPKZbaWKiKkJzWrgTgeD%2FD%2BQ%2Fpv3%2FZR3eF1PHVU3ZOlUH7o3fz7KdePuan46dE5efvP3cHf5rhjXclz5z%2BmpLUNEqBR1oRL5%2FJVNuvMIKnjO8ZTCLr%2BG4Ukd55MqBrqF6wCarC3H0fLxsBCY%2BLGjNKFNYx5xMTAlRIlNens4ciHOBhQjuSh4c4Sk71KLbJpuFOCBIABGYarlCPPgfXQtVHdss3MiOGOA6k3rr9q3V9CMgg8bRrwURiUlDtaCKmWzO5XdgDgAEaFJQoFhoNhqFiwFhoRgoJRIFgqIhGEhCJ4VeLrmSq1laZLqklNcouKk4Dw18O5tJ8tK%2FTdNzdfrlvXyV6h%2F9TDpZZ%2FGFXPM3Ojfsubn9nxOHg0eP4mldNvdLcJaKZHM%2FD4ev%2F4cyE8j%2FEfRoeTkNhPa0%2B66J07xNjnkbFyQ%2Fp1KyPkX2K0xzPp7dDbKeFV073OJ7oCL8%2Bz8Lie2ura3wf1rXvMfHS%2BOklgONM1XhFMABeA38unlD3w6u56Cl%2Bi%2FKFlW%2FkUFtWhRmYSF0o0NevsYX2X3ASp%2Bni%2BszVIWnbmgd3b2%2F0A4ABGhSQTBQTDQTBUKBYqBYaBUKFYShYKhEJBEr1rfD1dBWXlou95pk1zIupDoaW3jZVoHXCak66eXwP6htlqleh9fB%2FM6g%2BGWfl8j715LVtPwqb3Bdp%2F9PqHMeeQdiR0Kapp5x7kngnu%2B4T4pnJHZ8HN1uxn983bRsIxzXYbC9MI1zn1lcPOcS5%2FstXiPPk9fCihCoWDWymT8qgJCCQkmgKV3pnbjvtqNfPxx9wq6IMPnwGaANA3IXsIc%2Bx8YSupk90SslE2sxohG87WrhXJT6ziumhpvpJSdofxVBwASAUlCwkCoUCxECyEEwkQwkC4RM5r25bZxtVSZwqpKXMy93JrCSB8V1W8%2FBdXpL2aa7Nm8es%2BhPolwajb1zba7qk8vqLpVv7kv9PCd6u3yo3AbZP9P8%2BMDvkX5ZbCWz0tRDIgL1WaWx1Eg%2F26JOJ9P6m2jLPHpf6BxY2IvVer5YsyxwX5FrdCWutFY6Z%2BGZ5x%2F7N%2Fx8v5H%2Bb%2FvBeyGdDGeXa4qDMCfN4qALcCoCPP7XkFUQBbUxHy31bZi6BgtD0lYQM4o7RtKtsW2X1YVrxSvad6bopTdhbXH2X9%2F14A4ABJhSYRhYKBUSBYKCYqBYKBYKCYKCULDcKBYRhYJCEJBETC9by%2BPfVYvJV5apcbm7lyoSwfHm%2F8bjPxt1PV%2BKt0fl%2F%2Fr%2BjMdmRUt1r5tPK%2FvzpTRdT%2Bm%2FrnhGE2cfV9G%2FLU1ahCX4Puf33%2F78m3n5PaKjYPKneFa%2F3vt%2BiE%2F3vKOl9r0JZua44HAQgmE7Q38SMURVSGEO%2BBAEdEiujYPBQ6Y3dxnlmjg6P9zYL%2FM%2BRFOu2sSBmUrKFzFV5SW8WBdiAXrhASmvonkNflDeCaERR7pSVBNCQWy1imhQc%2BG7kyh1leXbkT2KJRlxQli%2FYs%2B2%2BYOABIBSYKCIKBYKDUKCYyBYKhQTBQKhQahYbhUImeruhrdYpN3YRJlXs4XkjgJr%2BVan%2Fe4bR%2FSaI2F6%2FpP9%2FcvqJcOw8h33FxH%2F6z%2BoeAW%2BEUy3ptqfi%2F%2BFye6canZ6ehex6l5lx%2FjUf7brgGqKz1hSNY2e%2B06qV01bZO%2FKL1u0R%2FkeMB%2Fhr2%2BbvSdnLmuWBm6cZUxHWi%2Blz%2BX%2FEwmJUWQbbqtQYizKtphzuKlTOtbdttI3qxVEhZhoufVsKnMGHAWpOf767awiC9HdHLoJx6woytjd0JoNrPFfAqdqaMIOAAAAKzkGaJgmKBXL0hNsR161JRPf9%2BspvXq9cv1y7WKrVju51udor%2FMrz3JdVXubwR77V44MBwVzWuXUsVRb8gKBOM5fGVr0KDffAuMPxmK3cBP%2BC84cFVFZiCvEJnhbG8CGLDGXAaZpG9ywLh8SFqi2BpXUfEndhBstK5t%2BBJFgjpGaHiAzgNAFYpcnt%2F3aFv01WsXz4SxXk%2F0f%2BsV%2BvV6vJfx36skZQeBYYY8rD7H33DIwk%2FOBZQ8Rbt5PwUMRImUFnj8otisuPb6Xb9k9BA5ZBBwWQ8n1qpWcVivFbxHTJ%2BsqNOGoIOSYDHvGCXUduBhdJkjS12qRi0c75P4nBcYDAUKTWOMrojUuiODjpeH%2BeSMhSCiHh9PpfyszrDCAkEG2k9a17W0ryXvm7iiHBvMDLQFTvED%2B0JD5oRv%2FzY6l2vg%2FyDgkAYhjmhazAjxDCT38Gw6rkuTpD%2Bmnr0R%2FpXrYiSZKWYJftBoU4r1EzJjP8eo%2ByAWBmbQMeXxmWWV%2FhW7vd7sPpE3rCQsaLDxndx2IbFeK0MmY7Ijbn2Oy78zrqFTquykCByYHI%2Bld8DnHnIvjKl9q38OMKSxs3lmX1Fd9agw8bfGCxxYZaWGzOs8esE2FjyTwiG5zGe%2BX0d%2B66Vjr%2FWP%2Br1S1cR9arKZ7SgnGXiu99n4I73u8R11BI%2Bq6FjjRRAdApkbfCN9L%2BXuTlu%2Bpev17l%2FViI%2F4zvf9F9%2F1y7Xv1f0wVBAOPEQoc1RUnSCj62MN2WjgNAwXg0CNgQH45ohAZas2ooj8Vs3vQvYEfi09%2BLwKs%2Fb6dKgBkPUrTx%2F7vZbLvqnv4GtBPXnH%2B6vUML3XqyoXqda7kHb92r%2FNd%2FrUnrXdetVdF%2FepNoQQuOCEoyZc%2ByDrbTMHX6ZzYVA2v0Pf9av1qrxXUKrB%2BtdzDlt3fr3c7lJCgS4h5cJIsAZ75fcdPH92r6DdykHhpCGKA%2F1D8r8AITrp5X1tZa7PSwGOfkc72D%2FKCjzZg6sHskXa9QWESJsrEbjOrwK%2BnH8bLujcboiApQVHbTxfgiy%2BhkVX%2BuXcvrFN6vXr%2Bn6gnJu%2FNFhX4Y5TqK7pr80JX9fcg59%2FwQhMg9fFufBFGROf78KiF26U01cdNH%2F5LPf3EeE27t4WZPjYTLu7VNBcbGc7DCNjMhPkuPFMLNjSDE%2B33WBdCOJoHC4txUZCZbDRzJO%2Ffq0XXf6tEer%2Frl8WYu5crwFCCIXy4IcxDj196xUCCekgeTApW8HsCfDAqr6lwGPLZUv8OqKXwNPAncFvNCBILQCNJqlBSvd9Zf%2FUVmmjiDEm3TxIPhlH5aQl4RsJGn1cLLod2ER%2BOfyZcJVBY2F3W3QzANPw8HxNfjgwNmJYfIt33t%2BcMB1%2BFjn%2BOexXy%2BPo90PwSab0vYc2TMIyycFF%2BUYSmqthAmX1Ywf8bTLGTRAb3zR9M6%2Bn3F5sibG7fwxvHknWsnDFfxDTL%2B%2FjintArxyX8aFt9wS3k4at6jLdDM3YJCU5P0toqS%2FXVcqsq7fgKj4Cm72wGoggIe%2FSV6rL4BFN1mJVfm18SC%2FwSD2HRnzWaq%2F1g%2Bdj4oGJA0e4wyQ0hSOcY76db5QkNbHAevjAI%2FUrh3lwoK8GYCGtJBeyNbzPY4O5lX9r4UIwix1ccZSgbTVDjurGE3cv3KbRNGe%2B6IR3vmwRC3vy9xRnVUpZINKkBsYoqVMMljb6nov9uk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_id=1254206535166763008&segment_index=21" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:32:05 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:32:05 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_BQ1RNKpQMadFzdL7MvUsKQ==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:05 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786112534681471; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:05 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "86275b5180525091ffbc1d111fa41085", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19931", - "x-rate-limit-reset": "1587864356", - "x-response-time": "31", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "00e6a86c009e96d0", - "x-tsa-request-body-time": "117", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"S9yq9rCkkLujG60WUu%2BOjTZUe8o%3D\"", - "Expect": null - }, - "body": "command=APPEND&media_data=m1LRA0w6w2V57hOoKvwOmXeDJ9v0dr9e%2FVklxPrF%2Bvd9qx7q17CxAhLr%2BFC7ulXcdiHL0xWWxWK%2FvnCmNrn%2BDvgrFYrFYrLYoxWKwAQXXcFEQ0P7sVhZiHLZUZS%2BUoIjAkgQgwCDg76QjFcumk1iRjfdKZNSjTMZlhXgpB2N4owuy1MZFkvqEFkzuksEYx5%2FGyplpgfPliqiUPA6CmhLVXjHJYrxuj10IB%2BCnjoxH8LK8%2BwpdJGQSrmJg0cnFfw0ddrE23bvcFlCTQH%2BrdxxQMVYO3CQfkJEIbPNwDBsHAZHV3K0tnD1YTV3%2BhZUxyyp2rVA28Cndr8fXXk36wV6tV9XSVLUqxWT0jfjSEFZacvuBaIAiuINu7v%2FBLFb4rFd%2BRQgo6yA%2FIDDGDj4DAfL4ObAaB0vzMyaq8cDrHG5bf4DMs5qUGC2CKCiKYR7heO4deSEyj1YAqvkHFlKRr%2FFa6jAQAUxzdt%2Ft6cvh4BZAwOCKEodKGA8UZnVrfOpZbnziZF01ebRDWPl%2FgguGgtVV1qGEiIIE8oJyBX0sJXNsJCAQP864ns5%2BHd%2FaLOfS9JSVzUKRX2pU7%2FWKX1qrmuuf4VWXk90gUC%2FCoSUK8u6TMxYhWo6vjS%2BuX1xEJHEiiiq4tfxFRRn6E%2B7WK%2BXtWnhWX1y%2BlivLri%2F1Y7q8xOilUVWAyfCACqiPsUzVvGPe7sei%2FfE8Ao5KQ5KMsRbdOmTPJ%2FGBkEhWLFDMFSd3NmogsBNbkz6AitLLWbhAqceMVxk2LXiSfXweT1hT%2F9BGFVEy2sFUv69P6vEXz0yRLxMWM4P6YGmdIHAyFHYDFZT4JAntwDf8GxREQz8%2FiSjMcCOxA4B49CtIMffAkAM3UXED4D08dL9obF8ZYpcv%2F8twkrUEg4vB4PxAPFSbwaBkRG%2BIHswm5QCLGAdLoDchDjIAxI8PvlqincDVXmwngwdmawQVEnguKGdWXy%2B%2FxAnMN1%2Fdb8kIQYGvlwig4LR7xBjuvjkOfhgueonm0RGv7Y7LrLxho9i75aJ2jVL0HG4PsE0otF5p0Jj3S7eMo7798V6vu%2BCeLua0J6rvwkIut69gh3u%2BYXUmZASbsyjmDrlnSDpWnxixGYf1zfFB%2BeWEpTCIU2%2FgcAoMAMAduThIiZgkoP%2BcNBvUsH8g0Zaw%2F8lE%2FW%2BII%2FPjBdUybUnp147o61p7kjw92rXsbXNVxduRW%2BXqQY5oEo7S4tUdMMCdzG0Kuldw3UaaNWWFf6TkbDXxVopE4xPTVJo90JYiJkjEmWwY56XcmO2OQmlS9aq%2FwSdxD2NeHQSC7vd3aPvAQYaLecOCuvBiJ14EQb4b%2BBBhw03gBoO9Qv7Lw1xcMvrwIDwp1EnFQSTRhILoRuDfSA60BwWoQd%2FPwRTmbjHoPxRDiDM8fAAxQ4%2B%2F5Z4MVhV9hES76d3fSXl44yiXgh3jr7cXupTYdplHSZOG%2FDRYtFh%2Fjuv8ce%2BOCPqZA71AX8PNNe6QViB3LLMI7f9yl0SfQpS5t%2F2iQVBLcGPui6q1iq5BX4RDBCP14gngbFvCpYrL9YFHespgNwkFgisTwUBhKtkOjq4%2BM5cvD0RFMSBGCbBoDcBAVwmJ46%2F%2FiBu7vGdOi%2F%2FYolSgrchwYlcvvdf0OJu73u%2F8EYt3uxvvBIahGY8N%2FQgtpmG3G7Z%2FcpBZ09fgqIanqviSfPl0eL1DsrAhLKfUfeReLelzkFgWwlYsr%2F%2FEdNymj5%2FwSzkEuUFUDv%2BKv6DsM8pmrCS%2Bghl82w%2Bcq%2B8QGx9f0ywXuvVRc0CkTwLdYEETvAsQMYrL9d2HhhTU2MIDyY1c4yakr6nQymfnOvsqPvH8I0cafUU%2BeYQGUNqswudi9XmNHfDeidi3KF5MVsO9jBysFLDNI%2F%2FfzUfQI%2FL21%2Bcq0ymqsujM18MGzySGdHyeM6%2FssMiKH8EPLQZLDHLnivRa%2FXLn%2BEV18I%2BCoI14gZq1JTtvDRxDlanQDi%2F6L%2FfhPxtXdp9hveyXOlDiZ%2FurCu02OGVObPiww4%2F%2F3dprX7Kq696UgwfhM1IxGLUvqoIxZy4kzO04znL%2FdJgsjMZ1Uq7%2Fe7m7oEcaiKH3yfvq42dJc0KZBg7Cmqh9J6z1v%2F4f5AUNfUyl0jzbxiojHYjnmq2TH3yz2ex9qnZga%2BIr7vQjShOK8uP1vhB%2FdGby2Le%2F5CQ3Jj39%2FjtZqPuH1hym%2BRD8ziWCESW3lvL9CmVy%2FnFL%2FGLsnnEhBeGjijrPd4Y5gw7uNof7BOXlgn3y09k5s%2FBZ4aZuwA6ytu%2F%2B0odBp35xgwGD1Hs5dixCh94Iz44HsfMhMU85uSMcy63UFwtyEuGrq9h0nGFQZaKgd9iKsiOaR7YKAjwKAjqX8n1dxX5a8EU5CFs5omHsO7vvc%2F8UYEfUDXnUTCA%2FnJBOozT9espPJHCwz01cP8Jcjw8lEfUf8%2FGKbk2r%2FjeiMvGyHpS4GWVjvqATNxdtbIOJ7tBI0RlMdYkJNgqFV6ck5viXyMkFLBN0iT6b9gshii4KK1wQvr2XzDW4QxnvU9kielsJt%2Bh5hndEw6LdqT7pySjBp1ArtMDM8%2BtclYgN33FtaxSss6%2BerS69mGR3%2F0ImnRCUxUmKOq%2Fbh71XoIceCo%2BFOA2g41Y%2F1CduTcvxyKLDDWsr%2FNntXk5pPRa%2FWq8l3yWhFfnqnn3%2FhfRnIpl%2FJHSVEvoCOEDGJdvvfJX4LMwhjfsPMTUBAVtuNRx9a4d9IzGejtEGrsBwkVf15vPB%2BuX5e5afQsdu%2FUE4wq7IV7JiHju1L1Vzx75flUSkxxhQpGsAxZE8B36E%2FgCdmuYmXeOIiqK7W%2FvyBUZZgvZdpZoF%2BLIICq8WmpOW34rus2aA2tpV1W1gNxxGJUe0ePY2gS4ja%2BHveXsYCumHWqMbmFrh1%2BVe%2BX5hBk4gFJX4nJSwdvmWCZ0FwKsuSP9WaDCM9fTNvwkIpekL6TuXEovMCM7uIctjXuiyr1acn3%2FyE%2B%2F7BQaWRqSans%2FBNcx5mEa2fiSkv2SSTtz50%2Fc9n42e7h3uFSXZ3tU6%2FLtOnxdsNZPm6J6X4gTLOzcNPelcEJEE0%2Fxsn9ruXqvwibjJDgUIzM%2FkJP2v9yf25eC26gT6xvVfaLURyrEenCnMUcnhUgIOCWG9QayxoDx%2FQGb228UIBKYuhHJ7E6C%2B%2BY8QIETZU%2BLrHPF8vx1m5qRMd%2BdiBhXtYGPc5PodxX9uLxBkFSs4SRx5aj5xWJHBvNjL4xpa9ih8%2F1PlsVhY1Zf5JhQD6NWO53aCOqubyYSuLv37sJNGXon7yPh6fTMNzu0uniHxxPsGfhO9Nt5WNfX4fu9%2Bfy99%2FnTzKQiwZaTxWq8n9pd15BEG1l7yck%2Bmj2Hlk8ZfKxnJ66Tpgny15r%2ByfLdeutzPL3uKdlNx%2F3XcpeIaAZzpVz4gjlvjrzwGwPEhRqZnr0LBVk0uK8m6q9fdmzImX6ha8aTLng1F12mmxoeYYKEDG5AAJ8WFbKslJaRR7QReItaiPROvs9fPWuT4%2Ful8TdoS1Ns05yWORV%2Fs3yfZWvnCSjRpdv%2BoSwuVX0gZw%2FiTHp73k%2FgJYbPDInN3eTwX3XMZPnYCiLGw9vckr8fUvODLf9zbGcdCPD9Yv1iviJcmXl%2BTomuL4JfCXf%2FhD5vjunBIGAThR3cQOFvSLkGsjoFXByHgOBHzBwCFwGAEdlqWIpFUyqLohP9RRYMFedhR9mgArddUNFpYN24te0PzxB2I13hYUG4AAAMJEGaJwnKBXd16ExYz5fEVy1uvT9LFVx2L%2F1axd3xMnEr1iibiTeEv83BOGhYxwvqV7dhbEOWsJNeWCiNYLVtu5tKN8gHCvDA0WW8bg3tciMRmHR1xsKhsTjMRmRXgWWjbwhLM45cfwTj%2FAuhspMsfAthmXiUd%2B%2B74R7WL9coi5Lrl2lsWKEOStHKPRzgWXfCY2gCBVh9WECLF9d4YcsMTK6hcPyiKXcQDpwOzC2DqP54avuC06Tw0qwcEkQCfBjcql6YOfkzL5Pw5ZIBW8E9NPYjfTJnEAAEAEBkIAAeAdS%2FHAlQEAIAXGFLUUWkn1G5fWDvgYOolX2zWUTEh7gP9jHu48olIumObFIxxnDx5EdiHW8T0vvWJgXQMA30bsw3P9PtotaD%2FJK3bR0d59PuTSbL4LhBBd43pXdxL%2BbFL3Y0Xi4bcTsK%2B%2BJaJ%2FnGDSpEOVPfc2F5Zi4uoupAOHpF6dV0uCHiucIK0fqx%2Flufu%2FWu6u7mHdioBXhvSGxPmrj%2FjoOGu%2FeB7IDM1EsKkK4evlhYRzD%2BFkCUgkcEjmKNL1mdVEJaBL8Q5nqUgl0THbUX%2FFPDAFTQOAUKEh%2FqyxisGtzuXl%2FAR0Etp7g22Rbt%2BzN%2Fj%2Bg7a3S4QgAIgKEQANwgVYoJzKwLNRgLYoOxDpzx7%2FN%2B44YRQK%2B6QIEA4akZjPgQbaPhBR1QMMYH6FoHNmO%2BDWx%2B%2BXOcAIvA1H9Kj%2BW5Py%2Bv%2FdUTdxP1aP27%2ByZf8BDgTw6EHDj%2Bsnh4oAY%2Bwobyqqgc6Aym0J7wYy%2BuUSBMBTxwCFwHAI%2BYFbfpNW1IJx6BAcSFJIJbYGqsP4GX4f6L5cgrmkJQmr9anvuXiPiP1qyeDAnFMiKPCQH7jxZnvBX9jsvMxiOYwWTCnYEbwVNBaEFJdZMzDJXXECx6gmLn%2BoLE9YOuTKgYtHq0tHTgpS%2F9LBIWeEzVqRjgMg1BiBGSghdKb87vg41REDTLGrScVfzNVoItLa4d938vq19L1%2BspLqzeAGxWGrM5deA2AxECwh5bRz0wZbQqW8wnKJzB1acSbXeEmE0FhBUJaHgAKkcJeOAAzgwJ1KgA6lTKKWl%2F380%2FE45BHFXqxwuvY7vE6rUzwqIA%2FAtBYENVy4FAckhDkZzhkVSfoEUOAlHBcBQBNAp401iuHD2dhUSqu9%2FLHiwbMHD8hgsw2tlJH2hdQ8NNpy3LfcEOYzuSby%2F1XgoheWSiRbo3NwJwJqSwwGW7t%2Ft5eJx04E4%2FYWUAjGmu%2F32Z9gfSULI%2FHcIej1Xq9Xe%2B%2FsMEzDEayYSPGwsLnMQhxan%2FYJyQOYNQsqeA5d%2BgE32LFDZwADwePA%2FHgOE6paiidX33iu4GMQjoWybTbPs3k%2BggEIqeNDwqo85EcCMAR0qU1nm89zi4VGO%2F%2FEhF7u8%2F%2FJnvXkN%2FaIbZff6n069RZSGITtAboZ%2FjHpUGTh3Lgdq%2BYkNeA%2Fx9uJUmCK%2BGvlshBDc83k9CInUIWUMSakUShxk4nD2CMYjrfktFqYd2lwbiNcaPDgR7ly7%2BbLwLYNAMoJNcJiCixT36i9fHlEvfXxfAIGHPABtEe2iBHPbLxzuHVFW6iyDUZECGtZa5PsLx3D%2BjXoGCSoW5DaLzX5xb6lF08Wb%2BT8%2FobZIBQycyDexBi2fx0%2BoVhCOu5d%2B84cETsR69XVArPd918uPzavl91Vwl4wMj0CbXgjjpj79lMZmXvdli%2BXB%2Bm2nuEjmEFJl%2Fh6Kf%2F3hx%2FDM%2Bciy0v5rr0XKuLlJ%2B%2F%2Buwe%2FGPL9y2z5f5bBEcWOXLz4%2BIcrCkHQsKXv1USDgQoxA1Y68zUYZm8CQx9RExkOBGaBJMbF%2FO33l%2F9ow2UQEaGEsItS42yKkJe%2FkNlBgfYQKmchk4wyr%2F%2FF2w4OAhVIOAqYxWswgYN6co%2Bv2CXHxhIEN%2B0Mrwkt%2B8H2FCUy5FHivBWNY0VJqSgKlssAGJH3%2FDgmX7%2FxdP4aNN6rZRxM%2F8EZXvqm%2BIIjpJWOOel911ES20x9johZvjyX1prEeRKR4g2Jkacn4%2BlhrhtY6WfNWEbEp%2F777G2Sy6u%2FRar1lNM1PYSyb3wCDIYl7zCqTNED9MQX%2F17WbItirL7%2FXdDdwHZtZub4loDFD3ZLOYAAgAh6k5cxwwhbl%2BR7xB1LP%2F7OQDw8g7Ht8Vx0lNGCy4BTCVbWIlGUetWu3ognJEcn2HCbuqPDK6T9VYKTW%2FPBwse6Xh9k7uR2WY%2FLRL8EJXvi%2FBIbg3%2Bhuol3%2Fhsry5XyPkfXrFXES%2BsUmqxbvVviqwJwIexAyK8mAVJgACa2eOSfBhl9uWIDyeLY9wOlj%2BGwqdAY%2BS2CtsLK1KSD2fcf%2FBHvftPq49Ak1NSe7BfZrhZGT6sNlnHf6XoRSPt939flLsiS%2BSTas%2FiDFwowe031eCg%2BWiO9WK8EcTgBumH6%2Bwru0jBG9nuqh8K1d25ajyD%2FG81DGN3vAyQgYCHdG8dgCx1x%2BKOPXoDDah%2FuX2hoy7nsfxU6xfz6z6ppvMJ3R8CcGUZyRN%2BnxIjJXTrsUXP5wwGz7ITjAgP0WYXeYoylf%2Bc7D6cauSeX3%2FhkRlyuEbR02U%2Fsnmb%2BQ1YyDj9F3%2FND2WXl18vk74YJSjJMAaMwoV5srhmpXij6c%2FRjsvSNvxZJ5LkkCGh9SJ8YXQ2rky8vk%2BlPxCFC0r3f6grnBAEflILDf%2F2J7yBnurh47fN03chf71yfbupNPhnIXlpW%2BQh8FfifxBJpbUggOn68F0kc4gI3CNoQbxHgg88I6DgPRNNEwybvAbL6RakHI79IIydAaHhHk9KLG6lXv1iQokCo1R6hTFPqBXNUKuERMGkY1u4G2q4g1R3H0FCMrrmtMnrRIgdGYwhOchdhx%2BxqNhk3ggIVqXBu1YOo1LwrqYhJ57iAqLDA8%2FSQNXk%2FEbBlsBumoUcXjpIzk0yvobOYwVFe0Je9SXSJ%2B6qi8nIIPc3znWHHG%2Fy%2Fqk0ELvZxASv0bmEIKxCBY8iqqNaKLGJM5oEJ7mG615SPYN%2Fr1LvBPYZTc8w0zQSJE1EMlOsMctK%2FRBoQgpclB8Zfk%2Ff3FY60F7aPCX8TWsvmr15qchzs9bmn%2FXuCQtK8WjoXUnSnVU%2Fk%2Bwnuy3QCEPrK7GGZr6I%2BLQy%2Fdy5qSRZscaavELywP2NUDpGpaUZMIlR9iEud2%2BskIjI0z%2FrAvARANIMxnl1LVVPfif2wm1%2BNc2M1g6mSYr%2FqlOVDR1h7JopqRSfC4OBWJ3QMwrW7g%2B8n3IFDJY670A9r6rCmQDNVJY9Dys2hOjsLR3ZUkTL4sIX3FxfNjUmVZ4KK2YL3F17J9%2BzUa7u9OostIDs1vcSwrwUDKv9HafW1dizINsfxmo96fER2x%2FPA7Enlv4WLafMwS41%2FBjEP%2BWTO3pN%2FhqlWwKZTlRfJ9FpeEybTpDr4%2B9uw5a012wQ7j1%2FzCaE7deokj3vKxrXWLJ%2FKu0ETV1Q8%2B1L6lzej541KSCWwi4Zp4J757ytMvY3pTghwGzdhfQEBiIA7uq3FKJoGFv%2FMrLzZWunf8gkEph%2FiU9kwvOSLad%2BFIuJ5DiNnEOeSHmvLTea%2B9iRnP0F82JrdItJmFOtOqT0k2wbGFFTBxuOLlsmP34L0PqF5vVUXVNvsaMnx%2FFYTpIqVDSSmXN6IxQMDbvE%2B2HWAld453DIj%2Bgj0V5CFNhu1H%2BbOY3k9%2B%2FVv3dr%2BTudl%2BQqSu38N6So3CPLUqP6%2FovyfizE%2Fsl5yWY8cfyREwXUzqcaZOvyfmb%2BT9PvwiR7yX2Y4y9bZ%2BuXp2QhbIuWuJQR3fy0z%2FySZMSVa8iH0grV%2BPxd7we8Jj75rio%2F1rWlibJinPk1%2BIL4eN8ToHTaWXOLf06ffjAYAgMfD%2FAyw%2BxDjb8xqGP2VFZaAjL6%2F2gjl0Ssv16b16b0RlPfXDnF3fLl3qrNtv%2BCaGnrdm6er%2FkLGgQFl37glswhz0d9UT9ryf0UoPXxn85zgpnuxfy%2FJYQNnyexLk4sjnj1fJ%2FfZOsaUrKa7tS%2BTq4vu%2B71j4ZKGKOkk7RrHRWu2XfXCMt5Pb%2F0fP6CZAu61V%2F3HPf3e1itovrlXku7vwRAmBYFgFnugFhBwtH3C9RxLD%2B%2BTi6Kcw9V%2FH5XgezS9%2BDGpZ2Xv%2FfJUKtvTT5lW8wUP6DQuqfGcssSJDRQtx4NZV%2FfAAACpZBmieJ6gV%2FoWxKEOv9taE3d7V2sV1X0vV6xVh%2F%2F%2BrDBr%2BvvpXf9%2F1c3q369J6ur1%2BODkavbywMYIhQp3d3BqsH88C%2BGgoR3nx3f872%2BPeMEOPz2K4%2FfgxFB%2FdN%2BO%2BRD%2B4YR2lXJIluOoKvpyy20mnmnC9Ie2O%2FxwGOCle1%2BuXyUOW%2BKV%2Fr3lqypV7oTyfv%2Brfa4rp69el9a%2FXV2rUX%2F%2FeCHoZ9mVQjqoVXkxD%2Fa711NgwIDQEG2xbE9TLxVnO4AmQFobO5HaeTcs8DsSzCgqLqswOpAyebbB2%2Bay%2BtwPgOhurGdieGwbMpYbaluItUeqDAP38fYilfTGv3WBZFjAMofvX6aoy5piDqghrOAEwzNV8C3FLQewUX8hJRGpyIvnMZb8GQsbqXG5aP440rebhDxeClA4nAUq4OmhSw1lLO%2BXxbTvsBMCgpwit%2Fu4uD1hfwsMVzDgpR3HBSg6VBSAucLnD9Ok58sqC0QOlTEmgnQ8Svqnb4EcFYbqmXx7qpyzDTsejXobX0rVfjtdL0Vcvrljv1fvkXeWA0gYAgx6M978KKrE8%2Fl8pGDc4MVBKKxXaJ4toDvgBmUXeVC9JZQ6ZA73ocsIML1bs80QsiAUBfNk7zOuwN74DCBs%2BB9qSCoSX6tgFcYQAjc8IAhbZg2uIEhYwdfBcTHCClczEyEdcXoRzUvy8l75ZFi9s8gjrEYanh%2FQ2q5ueX1wkHLKngyxPrVDn9IT8C5gIPLDQo%2BDS8ISMgpoxz5QA1fLUFQBg%2FblQXECA9Soj1qrrCIkYIRq5YBbPlgCz%2FrEgyKQLSwDOPZnVZBwo7%2F%2FgCSA47%2BGvTl%2FqQRsrGqM5pbXr4ldVkhQIGOAjFhTVQcYgAS1t5DA7MAFq%2FPROVoo%2FMkOfhKiXH4r0zsvmEsWGJYzGRBjqwdqVxPHNPbdDrMxaJPYWAJhlqnAvmImojomvQRatVr%2B%2FWX6ty%2Fq3693XrLueB0YWIwTgBh2MChB%2FZk%2BAwBqSsC5AjF4Oy%2BbkVahEJRiRpkqF6GH8uw6EWnvCzDKEx1sDgm4BZT8fKyAxYJvf70cQLsSHcWGvhjN6CMV3Zf%2FVWWKW%2FV%2F1ruXLXHl%2FugEWBSDAzNE3Cw%2BJH4Vc8ZekvQgACIZxP6YBSouybdycEersgSfGdBrBEvWWkjS8DVHYjOkDbsQN1y8CzAjs1ZNeoPRzrrBAYfBDpD3jmhJMhG%2BwS4viNJPGn9iVqf3esPYQgSpwXYLSEFRKPGZsNE9%2FCvy8YSK4UUwFVjnvnqQz0tIW8pC1nIyHylH2OjtvHxONCSrUw0JC7WExinEa2WtVluvQmpfXL7r1i%2FWXPPa1P4ITbv343xDwL5qaEeOfBx8cu7Anw9wFIBDDThibDJoIiXdf2Cq4dL2n87nWfVIP9B4iwABAkQxAAEBBkGCjSUNCwYKJYCBtL0egBJ0Ecc2ItAkGooRJECVDZXhSZHgQ9Np%2F1bFs99sQI4vsf6MWuHtM3JUl02rISKZr1EeH98zCCPaEvX%2BEd%2BvV69fEeBlCHgew8LM9%2Bq1gIEEHmxXFfWtBkymyvcqt4C7gMsSU73a%2BXit0tcvLRl8VZkDbeVo4Qv8VexIboevQlt316MzduCzu4RPehMNkRKZ%2B7ZO7T4KL6MynSeH%2BHSnMRKS2YenL%2BOkKA1QgypDf69kQNAxxvhiLr9%2FEotSF%2F%2F8oQV%2FJ8ecwyK3FHMtVXQ1T%2Fd3uK7tu3S3GmONO7t1bk%2BwxAsB4BRQJkbP%2FiX3Dhd4KKBxeBQrgqvcHQmjW%2FFtcQ1Ycv1%2B4o2yV9F9DT2vUpOXPhuXEEaGvkqSzKevUTcppg%2Fd%2Fh%2FHJGy9DUvRDow%2FDUlBUo49tGqd66Pb8EhtxpNd%2BGSz4xffMiMZf2rfglIkVjsyW7ne4jLH4Vy3K4fsOW%2BNr%2F7qPSxiMMN38Rs0kWM3338Ndm6lMjZD%2F%2FRSV2uEnrXc97%2BCsVXEPiAfL6AGOAoQwNHGEHBTiSFNNJ5UvWYpOwG5UO6ITbUQ4kelw5xSu2mi2c4W6jMBAHTNqaf8PmWXowMXRsPbpG0ZAz2m6IYmchgWxoO26iyVYiID2w8KU%2FiStRoy3MdP4i%2B9Npp%2BYu57%2BColbTnAAEWDwAeGgAFQ8AHCRweOfZ%2BEIOn54D5bffeirJdqT%2BCU7B1JmPNG%2BsvNSOQbO83719Irn6M4Fz0%2FpFeT%2FfWA2AbgLgHIgztZ8A76qeHyeYKAO4IQrKPECDYrhQVJCrMD41GBgVS8QEME1UcA5Autk46qQjnkHfhM56fDa%2BL%2FLuh%2FnqOj6YGFwm9H%2B17V4i%2BFHSlu%2FCRa1yZ%2BImJBppmEWXnoYjQfzGblUasVGCUr3dn0yxy3k8%2F1rwREJ%2FKrm2Ju75fQvtC9do0cp%2FJwEENXYbIioml%2FGT29EvLeUMBr0Ld%2BCIVmQIurly%2FycRulFx5DePL05oDQyf6gmKfPu9yrBZ3HQ0UcAX30n%2FedHCXTPRauz1ImWgy%2F1i4sV4StA1mXGxf5htX%2FPX0EOmeLc99r0nku7Unr1eid3XjLnZst3lC1%2B7lf1l%2Fu6%2FCc2Vyw%2Fvd%2FyW0uX2jhYlEFEwJjZunSvwwFBgj%2B0hwxudraxhCNWyKK5ClqLaVBwGY%2FQnA%2FEgiYV%2B2%2FoN9zfB7DlYp3Hl8d8M5fPQDF2DWFjm%2F13j4buLyCc3WwxqCdopbIWTdZHurFz3SKlBXjVyEle%2FaFiz9wMa%2BEi03bd9rmntWjvBESgbu6SwSTYnJLuybp16sS%2BSM4%2F9CXrsQKu1w46UC1twXnECCCx63uy2u0CV5jGI0oH8medRmRKwGwDpIKZ78GtTNWhb0s5iDl0fL5YhFLYw8N0wXRh5zXHbKnKAxBAkStsxmJLfcn0cLTmISCaJ91C99oK0d6k4D12NdRAUx2okC%2F3zurhDssTAxmcDggcMhirIhiAR8pJX1DZZOK3oyzXf8nyFLinr8p8G7FsUpqE9e%2FRZpbECuK7t96vrxR3QV2bO78hNIaiCl9X9FOr7Fio6y7cs8vpib5LB0B7vvUyxoKS74gzZqjfffL5xBsO%2Flx0%3D&media_id=1254206535166763008&segment_index=22" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:32:05 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:32:05 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_J3xEGjbdsps6E5LJ2GPSYg==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:05 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786112591786886; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:05 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "a10919525377c536195f280a1d89bbfd", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19930", - "x-rate-limit-reset": "1587864356", - "x-response-time": "36", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "00e2a00300525221", - "x-tsa-request-body-time": "102", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"YliYqSW%2Bs0i%2FSBzeyhfePa38IqI%3D\"", - "Expect": null - }, - "body": "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%2FhuvQhAFG%2Bv0HP7gv9w%2Bu8S9%2FZUiATPTofcX3PyenhAPY%2BoAfbjDvddizDHCeloV1FXUml6YlVp3Qb%2B4HAASSZ%2FjIVKFSJMu6qPjvW%2BNBwQMnc5IyIESmw6SWYgst9CjIkXcuxPpLqzFdpahKWa5QGOpHbSAPkIXqVqpdoTNtG6PgQgwmCKEAYEref%2Fu7zltBOqAB7vfIUZAp0%2BfAbZuUb8%2BuGbloRzR%2Bu%2Fs8Jm%2F7r9hg2H1qWDwtcXN8DvaY6bb8UZ%2FjFc%2F2nv2e3O3yfN7ujUrUojUuJLOpm289CXDxL1z8TEfbyKe%2FAmoLmuAc80Pisvdniq8saFZx1PNDZCcBrjdCYwYDSAeqDgAAADFxBmigKCgV9yeheUnE1k%2F%2F9r3%2Fa93d3dX4Q%2F%2Fq3fa6%2FWu%2Brv41fleuv16hi%2BxHVr1etV6v%2Bvfr2Tz%2F6gEeGdoK4HkcCAVe3e7Yu3FjKeIw4ruFwO4gburTuCguWOBImx%2BJRvy02a4gABcEiAAEg82A1Dl54B0uA8WvqUAatODSDAmISLRDcD%2Fa2FREB1scbyT%2FB%2F479nCTFisXMo4JBZB7w4Ptej3PnWOcqucCOvVxf6t34WXX1rLq65blq7y%2F%2F1dtXN4HxrNCckTcdVIHR23KpxKbDIOsNFGufgu9GoKaiZzSKlWMglxXvm7hj6U2bsBj5Fr2H352A7QNRl6vjwdX8brOODqjqQO4UAgDApag9jSWVNvz0T5by9Ulq9IpmOqVUX56kFbmd0zzHmsudFpJLZi1zVlpuygwgiwsIE1IKsMWBgy1voLcYqcZ%2BqKOT%2BBSLKFcFIRBBywlwQNCvZFbZEqvTrxj3%2FWJCqOFC4I9M90PNilWLNDlTqFZkPneLDoK%2BbE3SKTyFd7zcN3D1k%2B%2FyQUT5mqpLlV1VVUlCVehfkRRs%2BAiglriMoipsm854SD1O5qRltYty%2Ff%2Fxvu40grvVVV3aHlqKxrDgGgh2GJduC4YMc%2FTigNGUGkm%2F7vUQofnWBfNRp134Nwv3dqkGEISFChqTAzwwpNYsY1ugEdp4oRWwMOgEHndEkzv0KjLhBR1QMOQHx5jINVLbxA%2F2Ye7T%2BVEGjnz%2BoGBqAcDufa9R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Yjfl5PI1eQQQ197ZqVEjI%2FeY4Wj7lY%2FBBAnEWb3gyahYDgVXy%2BD4UNEgwQEwCNrHQ2DEeI4PeZcsxVc2Xx%2Fo%2B%2B1pVrHJ%2BPk9Bk93P4aoz11%2BHWnRf1RevkLd3%2BS763RHk9a%2FpRKC%2BT8wkCb9YIwSA7BSLCx8B08z60oZP1YEGEz%2BGaCr4AAADWlBmiiKKgVyehPSc369Vr1%2BtS4Q%2F86xd99Ef%2Bv6v8T7q56%2F9r531f3dXJOtXf0rOf9XXgWRfgJtAnI7it2lbV2sBOkD44abRq7s3xDggcPj8wHHYQxFIS17eJ1rwMg8MS0RlbIllx7FYY4ohDTbYjunLX2hpkyef%2F0IrFJutX614v3GXLRe8EUD8GD143l%2FA2AoGit3UKhVLLm4XZTQV%2BU%2BLoRkJ1BjLWxLBvVM9Szbn6rjQSfpcvVeq0YUB4Nqa8MDgtQMBWhf2BZZ9hX4KN4FrPFhpppqKiPwdldjJ4gcbShkmapR73VP95S0CCgcZgWTamYAzYIb48sBrJYESK7MXHi5lHIhWiCPyPbuuWoaGWic%2BPxRGo%2BDwqdQGA1jRIq%2BKmqUoNwtsUNaoufFWYoFgg3xjOWfTRDUnUSvnUOeU%2BiQfg%2BH5wA%2BFqKVMiha83H1uvhQeN%2BW8N4lI751agLNvTqzG0tm0%2B9%2BEB4YvNrrSbXgq9G45JjARRtaqq1JSUMaTVFqYrqANAF1%2F%2FUf8AjAOhxIHUgNbwMWXvA9PvdWj89esFVfrUl1quUTk8yLVNoQEQRG5f3hQgJhD3btPivmYhgowL%2Bg0VffXoJLtCqmvy%2BGAIN7XvA4YoGBqcYUfbz4DXlceEhohS9VF5FxdVxaBm8%2BBDg7PxaS8tWaSfGMzAF9974g7mjrWnTUzBTBJ7QpabUSOzfWI6%2Bhx5M0v3CjrAcMfAsN7BQBvokgr7YKhnpnbjjrSSHZ8y1a9Q44gkKdstZawYDVLyy2csvgmD4Jz3PVVKcQ8zBoVpZ9%2F%2FwcAkBAEs9jGrmdrH6ZLQuOd%2FN1q5XFrU%2FrX61Nfhv303OtcCMbhJa1%2F%2Btli98EcId9nIB%2BhbNUKy8PCr%2FwgiEIkQgmib8Uqn8quWF1%2BH7Oe%2Bhtn%2Ffcf%2B%2F1fpoQ9al%2BXLy%2BIkKVhRBQcEp5pKXiMUPDP3zUrYRoQkcGP0k9a98n8UiZKhDHWgHagLPpj3uwe%2FT1P9Hf5%2FybtBF77Wq46sel7nqqvXX69XrXhzfrq4vtXCy6zzGykiyUTvaC0YKscVGsps8MYAOz7sqbGc4%2FLEnXXNxEf%2BP1dVfJQpbq6TV9ZKF9J6vJ61fr2T%2B%2F639QWDCQ6rKymjjilvwSiTJTlyM8VtcPwVzDmNDHMeyRwPjumxu8FHjvtuctZajCRlDq0DLWe9AyGp7dvcdzJS3S%2F7lQmfolKwFFk55IvN5IXckqEvEeitd5PqWyIiMKPkrK15Ic3pwfqPFDA7yPRG3vgiIC0%2Bw3x9ZxIOwRDXfwpXjzBrTZWxC%2FfTmsewNF%2FF5fy8Wx%2BW9OG4lEzY5xWZdTy%2F2TQRnMZlDqyJQegcJmnrErE8ubG2WeVCqMFOGHujfypx%2Ff%2FQl6pZb%2BKxSyX%2BvXgIccrZfAT8BW8wb4AjI4IjL3F1SLlxWK%2BAmRAsm78B712Iw6LLkQA4IHMpo48AuUYANk1dZRKu7%2BI7JaY8kfy%2FrdjegjaY3izBw5eAjZyeNwbwVwhxKhjxggJhirFzJ%2BtvVjYzjxwHCHZ6qrpc4Ajd0%2FtS3YzRo5PK%2Fozzv1%2BPB%2FXD5gvtjY%2F9wYHxxToWpHqLsRA%2FVhjNL2NcLnUMzmGrvEqSu60MY%2F4ISl77uPhIu6G93p8Jkd%2B8GMJfcNkD6Xh%2FwTYwyjBap%2FYeLjbJtN2Y3jKug1KQ1Fn%2Bx3FkDSmKWsFMV3k9QpWvL%2B%2FZDjZdho657O%2Fh2nvHaLNVjY81aegOeaC38EIM%2F6k0f%2F85AHU%2FqcZuFMspoGuSv9eqlrBSjHcKCoh48D8v8aAhAaAPoQEhG731vA1A0AVgImR34hEAhUhxVgZATCoS0r4reXzhAFALwIAJwITCW4P8IZueqTBaHxAfgcoVg2BqFmAAdDt9XfECkDoFwN08zYP4yUKJ0ZKOIMtnp%2FBePLQOpZe89K48aT%2F%2BvaG9oE%2F3nHQOhgmeOEwLIW4i97zgXAjZwkFC%2BuWRDvOfT9UVzKq5Pnp9kzvUegPtCOIZLTqFHL%2FYYtFj4piPcrHhn%2Fl9%2Fs53%2FTdfhc1y8H7EH7FDX5nz1u0gSnOo3JU7aKIofcRRyNYNcJLqyedFclglEBulG5tN577tze7ghvLQuPziIP6DrR1pDYMdK%2FcNVgxzKglaHX14cZ89fgwzEikF%2BXuv6uWrGx3L48%2F983I3zdMj9XGS3q8kvKwayZXhJBEVbq933evfGIwFHsZ94EQUDEG3pjSmayMgEl62NwwysIE7BESgEEorEGQTfGgUEBwLckWRCtr%2FiCwBwEAqp%2Fb99j%2BP8dXgGG01A1drRJnS1%2BFSjZLI%2Bjef6sDfV88e%2BofjY9ggw4eJ0u2bjnL%2FVU4IIkAOHgcBqAqFgAanvjtA7idrTiXWP9iSA%2B84Psz0t8Qekq6mv6xZfXLy3RmNQry8FHJgemfbn5t3Dhc0keH6bYdihfDAiNC8d6DnoXF%2BOvVe6FIIHX2GyopablWjjy44DA%2FXVP%2Fdxbm3kcmldrFLfeiFfUAowUqIiXD5ub8n8CsWCtPSEd%2BGZcBYCFV2EHMC5gxHlGBsf8MljYxB8qk7PMEfOWLbP%2B2W3HzP7ZcJcXWVZtT2kw94TMrTcvNEAMp71I0OMBsP%2B3oRPhcLGW71ykrp59T4ji8aaqms%2BSBdxCSnxCkXVmnHsLicxJ7UZ8vsK0NmtXiBGE83xW39nxZalS%2F9kjYZFYQT6n9bbhsuPkaPpLjxEn6dIvKcBZpbzS4Q1fct7fMRUteCMXxDlaOiCHQFHlp3KZKJcY5PbvynBVmuVmGjGA0tUQXw7F4fLnLk8v6Ql%2Bw4IKpcqdUz4yPqP769jCSL46GybhFYcsWFUlmE2Dv5PX9SFe1srBVsUZhmqSfZAfAlZMebfxZPNctQQeNFuNYGsqLgJWID9c%2BmN%2FJ495WLFFZSGXqA%2FVY3l4dfVk%2Fu9Q%2BLPuUenj8sLjz1ZXqp%2F0fu%2F0TrpV79XJNUWqL%2BWqmIXN14Iiu7u%2BvXv0gVCI0bvjYhjhB73g5dXlKVQ79mM8YBV6fBCJ3P60S4o0gZjgl2L%2FwXnQIJOEHjFPr8aHbv4LuhnNfL03eT8f9Gvq6Nmh7Bhw7Pkq8Yxa1YJCTG5f0srgsITVY0ueojcibjpcSZt7bMFVpM8DqDSMuphqaOgptLhZk0uUAnlCpfw%2BZAavbr7S3cOCnhJLLWi4w1altbgU7zDxfeARl%2BES07%2B2e9MKFm5pQsoJPd03EhQFQnwo%2BYHlb9qtAfzVtCLXAorQ447echGNgHeTuqaqG8vDQJ5Gqk5iuaiX2%2FF3kYBeiHuO4CaW9dqTQSf52wO13k%2FdQvaD8dxlLojK5uAuyW65QyLgGVfu1eIgIReclP%2BkUSSWJ12j2GThs5MjEHnjKEOlPUW81bjbRXtHfhJ1fjGXuW6quTX%2F9CGW7wvGPJ7L0qFPLIhPFZtr9NxwdUnl7WH7UpeuHxo%2Bmwb%2BDrhYeNmKcF1hG6TN2npNQ2lBsIMp6r9MTGcugoZZuv%2Bf3FbG4dwIdU1ZfcN8nl1fmqVju%2FRTidZmYVUHs7FR5Coo4Pv7ttC62rihDGJugGIn49fQKM4xoLGuwRJCplRsaiG%2F36cjHx0sYeu5T8qZKyhI%2Bnryes2NEOIMplltJE%2FaaO5GA9%2FvZo5RG7CJswL8I2qdlMQlzOe8CJSXD4R4F%2FKh9xtcNf%2BuX4ySdRIlMFR4JuqPXeFBRGpJ8nHC0LDMSCskLeQZLpwM9WHeP4ow899TZrUEzgchHliN0rvfvvHEDK1oposS2OqCiP33j268hNed9%2FovXxHP7orkim1%2FGCi937tuGmWDAqztYtzv3cEatqfv8LF1caQqmXNz%2BEQ0K%2Bv1qn9fhrDC7zr5fbZ%2FBFzERxucVleci%2FHZeOwioOXoJkuNTTAZ%2FYLRNmG93c7GW10wpCDjfh3bP97uzP1M0tI30zt2oL7SSCGy7ymh32vsyKRtkq%2FyMaMLvjuOtC%2BgJN%2FaktfJ29OXzP3JQobk8a9RFiCtEXPbcic6C1RZPzZfBTlUncQ%2FfE5t%2Fd5cnT1ECGYI5eLiefCAgRB1YDtkWmojgp3lsgKuJ0E8zZEbHPftdKKPCdEizOJf8loOzUHVzApK%2BgSChRng1VTekAqD3x678vDYLigmGwa3gT3pFa%2BesKQP4GoECdwuJ8lo%2BiwGF9DxyLsqR0nPo4w%3D&media_id=1254206535166763008&segment_index=23" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:32:06 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:32:06 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_c4WdQiv8LuqnO+Cn7ZsVEA==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:06 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786112648782197; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:06 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "33253acac9df6273309f963caa37c69a", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19929", - "x-rate-limit-reset": "1587864356", - "x-response-time": "30", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "0024483800056c59", - "x-tsa-request-body-time": "98", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"Yh0FbDtjn0rJvzr5iMUyhMxqP0o%3D\"", - "Expect": null - }, - "body": "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Vx7OdMfocK3llCJDkEGrIXxLjy8tFdcnpR342DG0p5j0ZRCEwfB3djiFOud8DwW2NcJwQ3OFoF%2BBqn63wndym8yBU7Hr8MEgjd3a7aDpCfXDj39WWGPFYLyTNtKZfjfdSqETxkdvwI9yH784S3fevV0SWw%2FlGDfqKJHEDH06f0J7uW75pH%2BidvghB4BgIZz58WURLZY3PhbvWYf%2BoYUHSS5a3cdInX9OsAr2YZexW%2Bovmw2C4g5My%2BAj3LJ6goBMASAIxu683gF9tTAc2A4dgNTEBwMyH%2FWNGg6X%2B0BMAiaBVHgLk1pVKKjxoYEGP1f20q7%2B%2FkiyfbEpR8fvJ5f%2B7cbZI5JsG%2Bnu73fvhlFT%2FJ7%2FJQ4mT03WqzfaEy6iG8vtvBIW90iu1367nIgSmduCt5Bt7vqewQ%2BA254eoru43l%2B88IwRSGV%2BO7h%2B7R%2Bku9qTLJn2b1lOBPMINJgrLYuKbvMIf%2F6CRi%2B93d9YLxF7wEmUCKOyfQDSBj3gmoqkYyRJjmBQLaNIcmK932c6wwlAasWP1f2hbd7XseKgqpZ5rN1E2JVRKrWhLCpT0pQa8UhAV94341%2FX89cgyMFw%2FTRLbF81hPrt4AxNr7v7%2F%2Bn9R%2BLyop2SmtPJ9k%2BoIePadd3yxPrKulenyQ7rQdEyk3fie4GgX2bJ6772VsoUREe%2B9P7dRBdy4ufcXd93Plon9ieoVh5iguWZocCiNZ7eSX4quT40uQPUDSF1yz0RMuY44g1OaRLIyx2PYx5PaSgm3KXl9e2EjDr%2F%2Bq%2F7TJH%2BLu1lUepVCUIEzbfsY9NPuruNq6vtH9LuCQru%2FVZD1ma92hHbKwSGoKPvnu%2B9lOLPl76S79TC%2BX%2FDgpuyTUyhnMwMnjnlBaWRTc3%2FYaEevyFECLu9ZBAe5ysPGP%2Fk%2BV6bDkbLpeGEBDqY2ZX8eC6K5jczWvCXxzl2VaT48%2Bg3iCZngXUqJSp3jg9M%2FsWKqUhClOJsG2gnly99oWzu7%2FRWu%2BOLW5cvP2W0%2BvVu8nvlv5PDrxBpf6ZkXR13k8K63KG7kCDc%2Bj60X7a1fte6snh132Y0cy%2Bw1lON6sERXLf1lajSFjQ4sHmQcus6wSkGOTxA0wh%2BXLTfKYgzQMn9816wBawApvTBbgqVij63OGAiTgMfRGmWD1gF%2BeECQAxlC31gDlFRsx47JST8KIECUFXGW5KqWgZRL50jiz92%2F6b5Yg0NDNkd5Ps6HueIGF8sxwyLUWgdyfqMJnTAa8XqWZfOzeQfJGpUcUYNQ8wb%2BCU%2FQIZZ8gtqmT58TLBXwj9Zse%2FtuPVBBNKnaoVPk%2FfbsMCyDCXKpuVBa%2BUah9972%2F34rN61d999999iiY7p9o4gOyQi39JNZuMdq5V%2FrXffWXu%2BpC0d24gMihEQghLh%2FebNzXGxo3J5CgQlToQII3Tmo%2F6ErGoxl1TITrz%2BB2sSgyfkQRHuFDJXMiJnYRSg9ERvnus0NRYlTJM1NGCpEfgzvs2yJjN6oTHNYuHoPxGjlxJT449f6HYVGhGUpdktZzS%2BvRlyEUvsjg6GYUErx0ylefOIDBYLSd5XJVJ5DxzkIG2MILgJM97A8VsOvtNFH9y1yTCvvdQdNYIZnQj9MFDpPFDBkxBsxUDqbMmLSVriIuTCZzUF%2B7FxcXNiTMaswXyloop5PzyRsWcQOCsS53feFmERIvmaF3Lt3VLf6K9b6aw2I3dYwNi5f6pL77vyiTnL2Tyr13LoQ5p3QvvaCZGiGPLn8ElMtN%2FwXiK64VnDueKv5PjyVBFgGeO2lyRBc2Mnbbjb9J%2BCWXSHXie5zvJUMv3d5ZPkNDRcGXEGZZZXCwfFh%2BoNRMRFMUy3DEnBPIouPEgluyo7hZ8UxPG1RBRAQoe7T7iHrVeeCEQES1iPdwdWDqykHtD9oZxI4I0xLgnhTq%2BqHQqPD7LV2QFIoKKh6B%2BHbB3wPzVH8vXzgDzvOAPOPFLx9BO36xdz3699o1d9yXZPFfsXJ6GXMxp7tRHQCJJkS%2FcEKiJJhnOdtQ4npNHuvKIIiZbVTcs8lmoCxOWtdzWgVX96HdYtD%2FKUuNe8Ki8HbKRbxM6x0WIKTJjyfYT5MpDqFSr3SBpDIEAPDBBS8snfRZsJkfNnLgPPJh7gT%2Bo9k4uXLbGXI%2F4uXg68ieXjRMowhZxl6amylMe8Lm7%2BkFcquT0Wqco%2F%2Biaktcr8Jk5rd9%2BCuyv3d93OzFa33fIi5VamFUXx7FFp%2BJCHNmAZ3PHCrnSgPyeK6gSQiETR2L5c%2BStYeEhcSNlEWg0ZD8OKGoxQAMe%2FMG76vW7s89t2v1QSRzpCOfe8FTIfJ3degrOrpasv5v1dX%2BidJ69J6K3lP8v6IxLBNZPTif3hFAwBYFDPxf%2FlfWiD8eOEqrve7eWy%2BNL4Kx4UFdWvjXu0sttj9UNzWofFi%2B2rxPGoAAAP%2BEGaKYpqBX%2Bhby8VjFw6up1qUv%2FvJ69Xq%2FsXxf%2F%2Fv%2F5f6y%2B17%2F5VY756u38WrH65d91693S%2BJX3LS8oYBIS8FZ0mNeGw0GDXxDId83DMWzmd4H4MRx7nDHGVaMNeGA2eA0AXC%2Fm5hR51K6wUcFXPPW%2B0zNGxwBfwIaG94HUSHBFS3DFbOHBVx8c6b%2FzH0HTY60lqdwoPImJA6kDWs4TIL%2FHyywYr%2FAVIVDftw%2FsRhpt%2F%2BTz%2FwR3ccZZhKO0L7voj5F6vX1bq1QKa90YvSX8q9%2BrXdXVrFbxcdBOKSLHfLmGJmYBgJQbrY0p4G3x5f%2B3ErV2lEqIjk%2FoRNVsCR58BZOgtKsigOMKmRCUxd%2BA86CvcQAA%2BAyEAAOAOvv2r1UHwGOHuDX6Z1fTBdxDkHfMMAA%2FAGhgAHKAuL89LzbjrOSxVyZrSwSPYwx46CUHFud0e1191CB6EGQkdCrLFLLsLGdJjLLFjt5ieLqrpBI5Md83DxthIr8jmju3MAdaNBPzuZXC1GPK%2Bc8cKIPKgxX2pdj7nB1lS1v8yDOgmLoPxpy1DXFa9Egy%2F%2B%2BAZzdjgkCBNA29lL3dG0zvzGyiAP%2F0O2mlbW78NjQZNItc2hGGwLLDmkXQtHcISdCFKgaYIBgAEbwT%2BSIriqlcdEKPL46nSfniO%2Fl7r0J6QdpHFJxKsVa1%2BrVf6sfNd2T058F8hD4k7wgiA%2FwBYpLZvt8yj%2Fj9AqIB%2BQGGYtiSZxLokd5q7FX%2FQLM2OzBKQiaB20HG3GZZKYvzRXF3FBBQM%2BXtn6Dc%2BqR60xW72O8QBrBwxoQ%2FqebAtkw%2FdR0C%2BZENxh%2Faxvqbo%2FNj%2BDtB8%2F%2BvAWQoO82NKTNVwc6HEidQeFq4gag6HtzzBwMlJiWRHRQil4Jc5UTl77H4AtAF6TiPkxXil%2BKwkhNfX7Xrpfpa5FiRX%2BtXav8X%2BuWT9wgDNGBNyeooCLK%2BwgDi8a67hRnVc10X%2F%2Fr6q9Czpfr0Xcm6t8Rx15zDAkAWUSPBoQK%2B5Y8lRQGOqEUpgDCi2%2BcyiguuArAkPIvZf5PA4EooiShxYEIDFMsVwIu2CYJDGu8C5p3Y2Q2IFMf7%2FR88vX7EeTXSH6kHLbL%2F%2FL6uSerXKi6yevxzHCwhgC34TH%2BM0CxvXz9moL8YFm%2FEnv4JxWXgL2oG8fg9EdjzUT1TykcFOK0ILKYIzuHAWMWxnyq%2B5rrFNC6k9a7WKT1blr179erLr1jUT4wRwsYGIE4ODBjRTaDiwk%2FkgBpwQM8Ekj4cCcfzdyd5E2YfgGLCxaB%2FgefhIrwp6T7L%2BoBnMxYNk6dngGAgCJ%2B3jnctbii2UYJ2nwDh4ukgZSD3zEdSNhN6D6Yfo26X5v9q%2FspxIsZHkPhlSfGe%2B5RZQUX0G1do2yyfSiDFj2MJCjIxvYLqW4VTJTq%2B2WnLLvJlovYJolwJU6mdrAExcdv1Us3vR9Ix3WhPS8T1fPWTJPLc8TuU5AQE55IpJiHMaNxLzMWgoCJrzgm%2BprOSD%2FJbRxmDl8SiEnlBBZ%2F4g5UmeK519yQrJ7mB1ERcSFRCiWy5ENRhe98pF6jsIlX%2FercPj8FXM3vfCJ4CoM6X8hpSzcWx6LHS0FoZga2fd%2FoyaXjD%2FrcOlCpEGWCLechg%2FJGLVdT4jtfWuMshQet2Ntilt4Y%2FGilGp4dtoDqbLUNa1ERthKA5aakVA3ygQVZ0C5z6NCOgT%2Fml56GOaMNzqa%2F5Z649GoGA%2FtKysF8tw0yd3LRfpw1Pd%2BrtGIXaMFUt4INTaP1%2BtV61fFgkLxD304EkCUEjbu7nv69nF3Fbu9RTl%2FwGeDIAgoJNfCZeIcesB4jpfAR8WTd6wEK4u3ywsg2bIkDgkOY5yzYEibiABJZA1OYF%2F7p%2FEI2tmPmy%2B7T6jko86YuAjP2d7p%2BwvcNLi4nOI8NlKrx%2FcWooMw%2FXfoV8%2FXcO8hkII5TQP2HJV0N8DbpJsXjJL%2B9%2F4xnViwK8ZIzJ3g%2FqFji4g83O%2FF253Jho6esZu7ibuee%2FVXyeqQT7YIMCD89z3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DlnISMkuQnbyzo78HVBtRlVYXSLpWl9JahGJLL8D3fk3AIl792rvkPvAVNchbOowt9RxH54yapOL1DkvuYeo4QOxOaTRLzbaicEbwkrjDZxuoFXBidRISG%2FJtS%2Fsn3k1MA0zUc%2BA3eXcu6m2nsXvFd%2FFfG%2BUToxI8ot4OrGqu%2FBCE69F74ivXvKb9e75%2B8v97mFQySBHfdA67RA3jkBAV6wRZhBx6P7Z4QvhYoE%2Bs3U%2F46r6dI4ZvD2CDCqBF5drZP4IOWO58fXKIborP6MIs6n7Vh8OFRnyrvkS41n8JxEjXdO3rWyEGoj61Ed0lpJdSkEuDfe%2FTBELfAJHx3i1%2BEyMz6SW%2FcFnhlimjfbux%2BNNe3xkEBSz1OCzBSvkZp%2F108f86eu%2F%2FCMGUQhtUR%2BIft41N5qam1JAwGbC20%2BmFZRfl7%2FsvNBHmmBD96wfb%2FxcKkPAcEANLMGx5Dzwd8HTxRbaz630kOaPjnnUKCfjgaGw2DzwcPw%2BDrzqlbCHBy8FocfB15iBoDZ1JPJVSnhHSiHxX48dV0pWqijsFh4ru%2FH1Cw0PB6rKrsn5xWAvYzPnMxbFbtNBZzx2xqXwKI8SUKmArEGDJcplyb0quzx66UAkXB9Jb%2FoJ93Xr1fIT8%2F%2FUllps3%2F2Ck2fD5ZaP73S5f6bbG5L8%2Bb2m4XOx9gYR3ogUVfgrKTIO3isS5julsdgkqh6c7Ebpvn%2F5t2Psvd16I7mzldlGFidT9ojntEwKtr7xUy1l4V0Y2PJxHjJEoNfG5cX5YLImxDYUzG2P2RA133IIuKCUh0NjRAbccTNhiWkvxQXpCCfwoIDHA0jaWITLEs%2Bv6RNonCY4XZBZ9tuSd9ToyxZOA3zwuSDK%2BKFBI8oKXBvDTLdZ8JDBFU0kh27PiMM2J2Yh54A5WBlGhkcMxJbnfrqi2DrsOj%2FuIODFUYAMHHZzSaC56gM38iolMc5gy9OrscB2yGAX8z043wNKeHr0OyARi1AHxDotZtaNyd%2FoKsfS6UNrF3VrqvECD4%2BK371bBLEOFyfMVu56kpmNfU27Pt1p%2B6sVZt3snn%2F%2FoTKkYIfLuCwjECggXh%2FjbTMn95Jof80XJlWH3qfWTW%2F7%2BPCRoX%2B5c2UvsIz4MTgpu0qv3GgycHGNYvLYFB0utYnglGqmTqd9vt99QUNgi4zUs%2B9ckn91F8SrF5NSzK%2Fye%2FLufx2%2FpYFce4jfTD7KWEju9wwCAQOfnF%2BWl4KQnh%2B72496rGlFbyCivo54t%2FASTUlCQVCQkCQUGwXCgmCgmG4UCwYCgREYVCJDCoRM5vvWepM8fz%2Bl7%2Bvel4vfn4rfj4VTvpE6Du7%2B946e0%2BNN8W5o1Oj0%2FcuJ%2Fimjeg669hfn%2BJfxtLov3QvpLay%2BZf4I0aDlfQm%2FtX%2FEP8YsBD3nJ9nwsvZW4YAArns3QHe3AyzS7oQB4HqAiY7eM8vbokxKIWWmlQiyiaUQtQeHFC4Z7Je%2FtAg1KzKIyEa2iqC6DaudgpHSDgASwUiEgSIoUEwVCwUCwUCwoCxXCIlEJFEJm%2BOZ167fHzrvWde8yErz8Zz37RWZxSXodvP3ebj4%2Bjv3bjiI2%2F7JWFa9uf8VS0xo6yg28DvguX4hzKstGCPPqnVZQfzT5984UwvXu9n9SmZFvZwqfCxNPl9XnyOReYKsdidN6QAPX6BC%2FH6OWuPVA7ryidBU0B3%2BURMToGz%2B4AHf7DHQBWyZZdIVWRimFb3iJoYxRUHAEsVJAkFAkFQkJBKFAqFgqFAqFAqFhIGAsJwkEQmFgqERmFQiZz8YrmvGqrd1qt4tVX9X656a5NCcDwPb0%2BLt6ezi%2FIean9u9ErBuzH613H%2BIeLSLVe%2Bp2cwYzbcqYiyvVf%2BKF%2FCVs6h47IHPN%2FPrJLCmDHfk1Fn3m9b%2FvqY8ig2rMSRFjogJz%2B%2Fv7gq9lHYoOgXKJ%2FHewLg1oW0S%2BUeEHzLz4KV%2FGKk4S6D4fBANP21VVkJaL1smdZpoJRDLOqkMARrOoeOcQcASKZ%2FZwWSmCqFPE71nnu686GIS3xrYw5h7n5lPglVcdx56f1XNs3RJK95d9vVAXjtlWidNEvpm3CvnD2Ru5f7YPEHl2f3WF%2FO0LrGpW%2F29v%2Fgl1%2BlPR6KW6XTPY2Aycu1JRzC68%3D&media_id=1254206535166763008&segment_index=24" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:32:07 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:32:07 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_fwRCRWovqdo11PF\/Y70SKg==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:07 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786112706894255; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:07 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "b7f6f96fbb7ac6f84c67e4d6a45d66ba", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19928", - "x-rate-limit-reset": "1587864356", - "x-response-time": "28", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "00a1084c003c2543", - "x-tsa-request-body-time": "97", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"ISjjOsz1ZBKv5d5MUGpJB2bvRmI%3D\"", - "Expect": null - }, - "body": "command=APPEND&media_data=mVWvcm8SaVVEde3PJjicf26oJYQIHcFYVUXnORYUeGKITV5hUdRK8%2FIrUbKYkTAj59EGO2vkRjr9Ol9Xf0y%2BLOuqjtjroMcZTF5lxv4OTh0dt8np%2BNXKPbrnLYcuSKxa3SeyyxPe8cSwtMwCFyMyo8Y4ASCZ%2FZwWTljBYqRLuc3V8p56AGLXE1pewv0Fb2DZMnGerv%2Bz5LS%2FDuKiL3T7xvH9VOVUYMKtE9rBXb8gFEM4fF0morDwr%2B16PDG8Zzd5Jz6D%2BKckm5bCrjM2zyifLaoZ7gN3RJ0DiQfUL0jfiR1cOJsg9ltHWcgBRLfTopX5Q1%2Fblbr25XX%2Bb1miydzSCSluJE0ZTkqZ4w3IUx0wOLaXQfMjSZjsusSYkUQBZgztaAc5arUDfpkJA6i2FQFezM0Ac5LKAyti9A6fGrOFAAChYsldXA6L0PsngY1zAqK5jKI3A15jgAEgmf2SFmpZqRLtl1XNOPoGwQ3etdxH2AAWT1%2Bo5tsl8pABINn9rSi%2Fw%2Fv%2FAPz%2FxoeUTJ%2BB%2BNu0O0aINMR0zENKPIkELgnEhhb6ByjVcoteaFWTnSJkkjS46pH0nV9p39Z38YvHyXzqb58A2f4paevIjWClr00hPwOlMQy4fAWuO87i9%2BeVoJ7DnsY%2F1dr3KmQmf3HSfd%2F2yrLdXJLVuejyJIvXe6UzgKZlEaZYJyiP0BH%2F3Lv3ww%2B3%2BpKIe20GD1%2FD74NT2oHTUDv4wOzjA6uIfu4yNcZHs48hceQBzEhDQXHaBwEo1IjqEjIQwqMwkMQkFAsFBMKAuFQuERvGuN1u9ueN1Wt6zpuiuPFNzMuX%2BMew8%2FbVVV48ux0c%2BHlj5ZHXua9uHFWPaUs2VrG%2Bgy6yk8FQODlM%2Bo51L9K0aUa6wlWSUJ4j%2BWAqyBY%2BbtN0vEn37iFSohogW2oCDug0vvVc39MECwFauS%2Fdq%2Ft6cAhG1c75DJpbFnRp5lpwqCvuzJsrSpbek70QZCK4FoqHDyuv7cNsBraGj7odvYAI%2B%2FwdGCgACnACZaC4OAAADn5BmioKigV9CMtoX5VF%2FrX8VdUXxfP%2F3%2Brd6f79%2B8nz%2B%2FAwN2rEnq1VVRHawSer3a94EkPBEdujfeSb3wIoYBBy44WS5fd%2B8VgkoFKLtMlPpw0JF9wZvZU7QV5H3DYnGv9gMQBcCwsjbwKlGbfAjhvwoMBR0yxzYlFm%2F8T9h2sInWeHAHhGQnWBMKaninfsBW17BrL03%2FmuqoOk6w7qWtVX8DjCAxx5wCZCYB3MqBnGIXzaFsVxC5WO%2FMleOW4%2BptdS9Rf%2F%2B%2B5C%2F%2Fr1z%2Fqx3jsuXaz5QTjC4cOCB5YDEDywHEuDBjeYew41642zNwfyJhXO24HTQUiaaOMGJS8X2x3gLzsNdmCCCKvpyGO1e%2F2klBvywgUWCRZO9Hk5J6vbqBSYBWGG9y4rzygKeNAFIDIj%2Fv3UP0eYiTW65zc1pS8Q18W2adYkMAO4CuN76cODxEUdzpY6mc6pfoWzxxIDatjq5ScG8tzmMmeJGxNkd%2B7ZT8qAS%2BMzf1%2FUtXLpwPxOHngDy8XLxcXIOmj01yU70gHHD0WN30fuXnDkSrRR7wuXzIuLiLREfq1%2F8wWqU3DHDLcdzYrza%2FdfvA1hAcSBltV3JOlp980zDjD95cvzrL%2F1CFgBBgiQAYUQOMgPuQANzC8RTrPAAWO0d65LpKHd3An369yF%2FL6S9v%2B7Xrp5HYC3BDwCDF8BzDIawav3ucitXz%2F8n4D4JEEhgEIAiwBeh0Yv970hDjY3uBIKAUW%2FlHW3piexrqwXwwUFW69R9h3J1WtmYm4W4KX2U%2Fvwoq3o4QCQw4QE4rIbOOpwe42jxxWnAVkwVzcf9ArzpQCAQP4lDLLAutt5k92OOEFRgZsD9JClYhNCivCCiRwDDMD9F0HvdoGtL%2FziQqUB3YZQW58NWO8%2F%2FFIrvK177rlq1i%2FVv1r9e%2Bl6b1cktWP1at19STCPgDFRo4%2BVMyDoXF4C%2B6lcyq6uuuiteoq%2BTzAiweAZCAWCXZg%2ByurAF6Aidd4Q9of3atcWrvav16ue%2FXqX6tfrKT179eq%2FtdUTzCoFgWRxDCgwAuY2rB3nA5DBSBSSSQl%2BZqywOJ4Q9ggMYqSBSS4epUtvSv7WSeFMAGMakTbn94nDGJTK5h93Lddrn7hPMSurmeS%2BxP97PavQ3paJ%2Bl7gjXr9e%2FUtfSy7rnrkqeS%2F1PV4JC8AVMZy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FTL9YH2qlT3vlJ4QgmcKDVoVywzGWN8G3LDyM8usAhgfgWsYi6wgqTHp%2FfLnKCc6gKaIPdQXfMPc3oWxUGNUWvd9yWvfr13fr3a9JYaMP%2BHXnAWATArLw8EgnbPMJf%2F6BYReIUhBaKSlnB3k4yyxfl8CGOBcaGc4gg4H3%2F9YLxULo7%2FBDf16Ft2vVhHLQhPdetd16wVcl0XxxiFbbHjgJorWxYx%2FpYmtX1c77A0fGkfIPL9o4zjsE9d7kEXVRlJU3nJ6DDjpux4JHvSQ98Vy2sXf6vJatXEr3692vX6xT7E7gW4sFBsEx%2BOgQobtjY7EtDlueBr7rs9%2Fry%2FcSSsnaZOi42EDQaTpKk0EiNhzP0mo%2FvuuWvvpBHvv4%2BKtcognxyyAMsHwcEAHwN2UNQagMoCZZsFgaYlAAMKJgEACIxpR4EwES6ctGAoAlbbLwC8gKIFQgaQUYoxCaC5jxDXqjdxATBcXWQxugAbCAgKg9Bt0e3HMSCDnjBg6eOpgQRM2B6fTgZ3z139TZv6fJDosvZUwFbaY865zks1aDZAeugmG27%2FwnDidioFVhWuVy5aRUev6MQqfhEg2yUtE5Zgiel2ou%2BEM6mkMqlq2sE0clgQbHPWJRkbtPtTmlSO99M3wfo8XfRdfzr099q0nEr1UXdVam6RYIn2v4JzXPC62TucKx%2FLxfiQxp33vA6mn%2B8RwqRxyePvUU9Ev%2BOoPr0LPfiDNHkuwVEdiX9aMg9drvxt5SIMUy5G%2BMPL25f6fGeA0DLegO6Qfpk0l6c5B%2FLaLS18I2DMSMaJIx8uLwyX8OzEp2ySz0PzkX43G0Upmffu0frh1e7m9Tq%2FXqwNIW1gczAjhHe97vfWAkwxkEO%2FemArQhvMJA0jBl7vu%2FE8d%2FeDsM9eCctmcMBysQiY9tCAcvxXDa4GptSaL8I8vQEPwhNj747%2FnK3x8s9jP6pl89ZTaCW2fl%2FXwwRaflYX7FDKdTy%2F6%2F4uxC7EKcM4pLcv%2FqL91uv4SLNvmY%2FBCQZvxfD9SB38l9J30l%2Bi5fr2K%2FjF74kEnLghxjWFR4CeAhCxTuWMQ5UuN2XwFsDoDYOFywVSYI54tJOK7sawNgw4EsKEEuX7UIVbsE8PjMwnem%2Bg7i8HgV3Eg8Vvufzj5XNaP%2F4I5vfF%2ByIl0vsZbGKOdScnxP5ZqTGZ9HcfFEtw7TEmsyv%2Bvq8EpJvPkV2n19gp1fMFy5BUDlxzfqFbBkZ9AdNuJMNa%2BHt1gOBfiMsWqmonMhH4MOONYrvXy4MvT%2FOd33qJH19%2BrfrqIkZe266ATgNGFBggU1F89xdRTEfq1J4woEw8aB4CYyTt%2BIed7tiil9rFd5nIXJ3vH60hDggfEXLbl276mjc%2FwFAggEd6aadv4fmgtLGiZkTMxZctpiqOACkA25lQIR6hhKQXIxcynxsc9TlvrF%2BHi0GPlXlvSbEsNY3Lap%2BvBgLd991q7L%2FoQZPx5L3OHDnB4%2BWDcV%2BoE0%2Fljiv1TvElP%2BtuvNNPJn1crzUkO%2Fwt2aupaaktP%2F6vXcvr0T5IlwOwa%2BmbBKaWhTEnD5nnBfsnuF5SEmiCapD6nh%2BI5J6kFY%2Fbh3BrnWql8FomgKPSrpvB1Bu3epRTB8ID%2FbIu99%2F75NQRbNNCZTrwmynLdSX8F8JDd38Mo9fjYzmGZ%2BF%2BEXJytaICe5uv1xMZMl%2BOnhbjmG4E8z1P%2FLZ37Lxi3%2BXtjrWn%2Fnkgxq4ryYRMl%2FlELjgIT6O%2F5CXnhspQ9yZri6zVoT1WGzBxEswuxYcDH2LwrG7RPv%2Fye3%2F%2ByW%2F8UW9rOmE2Jx8Ffd5ZYZhVefSp%2BLFXgJhREHxzO7H84tUxKa4SMGHurl55bRdVYjLl73J6J1E8evDRI2M4GfU9Ux8i4f23kpEhp3mqpggDpdf7Oh3%2FVyrIYZ6%2BvCOlMMZMxoUHyZfqCcgA0d8lrnrKTI3KOF0Qn2sWGCmGkARsjn%2BXDLXw1DwcRfg8z2VRNAN%2BxZOxlCUqXhWRU6BiQY881%2BBB3JMZLf8vxBSkGxw6hSCVp664iIn3KX%2Bc0ge1zXj65fQ2Dqz0UBiVH9RhdwkdHJT7tPjvVWlAH60YIFzH%2F074I2V5eP5jQY%2FsWxyQdwyRDjT79yfvlLgkwa0QGR78t%2BKYLRtaqxg9QNaVFJOvdat%2BrT%2BiNVr1%2BKsBMcaHHzQ%2FF2EUlOvamSfBfvKQX6XfbjoL7TNPhzlpX2jIqot%2Fhe1Lk8C5aX5lEaFx%2BCOcxvJWH178upc%2FgnI9DlY%2BuzDbs2vgtNBL0zn3LDDflMINjP%2BjwYhkcmaQlPf98caLIKD%2Bp0cUYxp7G37utAH72zILoR0tp5qhipeHaBcUvx9ZIyfC3qUenGxRWGxmV0%2BQpHyVf2yLfNbfZozKxKxPJBfPe%2FjRs3tilBH0PCjjiwiBvWFFSFAqb56QFMuAVKMYWfXsQRjYrATpNEhgEsFUcDWrPv7cpnBwK%2FlstMJatFY%2F4YReXEqx5yVy3kjGG8t6%2Fk1O92tPfkaE9Vq3Sq0zwr69kzkF9hqdJHTZrGBIXDv7LMH8htJ85VjZpKZ7BDiOn9fZPTX%2FyXu69EK1PXBRL23cuWpHcfIJniy1uPu6bCtEoo9Kq95PzczTCIq5KcEGkOlg08%2BGvp%2FFpr%2FVS%2B7buEqtkrifumXL0pxHMQR%2Br29g70gjEbF6I44TB9%2FCMQQlDoOrMNMVB2wtlN4es%2BPlpK14lOmOrAdsRnG%2BuPJCnLfgspMHlgk0sGF%2Fi2zR%2FPIgpz37UGoVKtRD3MLF%2B4QNGHCr3wfYD%2FGjAT2anLwYDsFkuLAzo%2FhHRBRVWq43QKjBeOoikvfIGgyCc2Fh3YuQWMxnuN3clof1evX5xHVJT%2F4Ii3J%2BDvX2rn7rr8L7trWq%2BMZwChdm2xz2vBFjJjwZfl%2FKQ%2Fn9bglgXUrGWRPmxOfXh7V95UIJoNVIdu53YSHs7hE5fK%2FEfFfGcv%2BFI6UuB%2B%2B%2Fk4UAaqtCk9VUGsSUURrsQPBj9HjwDjJSxUvyqFxgcQRJxtZB0eAdzXu3PH6gr21XUToF%2BxiCemGs1FAAYH4dcO5PQTl%2BsWT0%2F9f99zN%2FL964IhF2eD89vhxOF0%2F0Vn5LRqalXsnx%2BqKVqtWeEXWJoU%2B98WSGPfNnWGTljbj3cl6Uu0ykjnxtfSTabrGvDpOeI7YO%2BBiWCwYEAtMcw3DoWLzbbuYJpxH6rDZ2lIAidg7qKV74ABBahXwrQf4pgiHxlu6ZLW6kTruT1l%2Bid3%2Bi99r3LJ5Sl%2FdycqN0j9yFfWsnBEKaPn24bARIXBUQDO1Yl5e67u7u50ye5YbCWWOJswar2Wq%2B7wAAADeBBmisKygV%2FNfoT1er169%2Br169JdepUkon5li7Uic%2FaLFUJqlyeiFX%2FhgX6rXr%2F%2F7r3axdycTdyXk9f%2BTARIVw9MAkenHv%2F61zHv14CXHB8Rd3e%2BFFZID07Hl8uX4Esw28MssWp4lk%2FZafh9eQVdoAxggO4Z46DtybiDpe%2Ff4bKIc03CEyIKjeB0bd4GyH74dL4CPBLQ6J4X6v%2Fd16ur1fCXVP%2BT1ddrB%2BtehPfP%2Br2kDzBMAmwwYUxTF1J0sd%2BUS9z0pyUqIDECMAjwwQlAdsZimwBCuphR5I3HSyt4yASowsy62VjNu7h2OYJKq7AITyeLZvw6AZARVVFQ9zdbw%2FwVrKhdMA5zAwKMDLiEekFnu4s3BqohI0ku%2B48FzMFdQcptF8jVttMYkQP0%2B15%2FGNRepP06lvWoq%2FgYnBxFfQITbKSQTTDBHffI%2BWw3TJ%2FA%2FygoQEgJjdoDqft9nYlwnAtBJWIeSflje4xMnu94GngfGwpfDRwRH8ZrKzwtN9wM2M5pxDQV8BYCA%2FShAsHGCV2x3yK3pFwthZIC1hMP3%2FHEP35CgjhsR8SWY8wJwWF1VaTaqqt2heburqkV%2F1erVhtX%2FWX61y916viFr1r9XlvnV%2FAlALILjHLbitxRz5pd5fWb8cgQ35831gUygSSBm0JcwE%2FmoLf7gZhASBODhEwGeOjg3Yt6wfaz8%2BvJ6ghBoAlwkKBMAkiAjqfX3wio74G5S8GVLKRS8GrllU5cIKcggySELXGJmctYhM%2BcLHLlisVit8PuB2k5dT7LU1ezQQSfyoXXFyXJxC6%2FXpfXp75te4BvgnWWvQKUMZuEAlJ9i0Ni%2FXvBIC75KuqOXqpa0Re76EPperSml%2FXqv9cK3Vvdepf080Qx4SAaqeJE61vUZfNU9R2qKO%2BmMwBR1qN8wcGpW2JD7y7%2BmBiQcWlhd%2BVGQAFwWlz74%2BiKqQR7jCviLi69e%2FXufoxWmL%2F%2FJc%2FXk8Twl0aAfsFLXHDtCQUnavOuVQEkUdN7Lr6ItEp2CTce9M%3D&media_id=1254206535166763008&segment_index=25" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:32:07 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:32:07 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_ou8d9mrDzIO8rnW1ZFSs\/g==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:07 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786112764361972; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:07 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "67763eadec8ab8a4876aa436003e92bf", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19927", - "x-rate-limit-reset": "1587864356", - "x-response-time": "34", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "0027a46f008b64a3", - "x-tsa-request-body-time": "96", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"9rBdp6AR5R7JRKjlkG6plDGbhtY%3D\"", - "Expect": null - }, - "body": "command=APPEND&media_data=%2F4r5un%2B0P6S8v%2F%2Fxi98IUK5NV7Fd3Jl16%2BpaSgkFCeBctgoZJZAI5rrBYSbss7izJ5Pi%2FCg0pCE%2BcryR62EGA3d9iEici%2B2Nb4UgOpf9BQGAcHojrkL%2FbwEvvsedpH9ytiEI%2Fjny%2Fzm%2BT6PJVRpLcQssko3GY986FQcJGOFyDmVFV%2FGsNM3EaKJlpFoQMZq4Uts3QFq7R%2B7Xq57hGu175179e6T5YiwUF3fcuXkL%2F379TCGmg4k7mvwvi61w11rccnXjiAZ6B2fSrv3q2CEiiOew%2BQhciHuvINRPtAKA6ztQSmGC66CNjN0N5EJOq%2FCk9L0i5sNxsu4lGcaZA4Z9La9q4k8%2BrKgQdjPgPmpZUQtCTCVBr%2FcxfjMQdL9oFE9wNCakOsHVctxFnpTmw1YM5MYbSH99yx1oQVdMYBAbpbxlg%2BMhd76lIq2q2jBv0ev1Y4Jb9ek9fd8twDlBNrAT4pd5ICHMLFbiHFxaACagiBd8BEhAEhOEzZeLL%2F6lEiXkSesv6%2BK48OXRxHH9ipo0%2BlnNPiF%2FncDKG0WXy%2FYf%2FG0XQGf5FEbBR1dCGPpcBXmq%2FwQnC6Mnuz82971wWZc3qYgvwMVpjmX9fCBA9jVNSCAj3QlTH%2BYNwn38r8uh2hy%2F56hvCIlE2YP54k3qGO7s497X8dRP2OK4O96zwY9Pd%2Fjo5PYZrRF8oL8hFQXpSqNx%2Fr6HkWzZVsOViN02T0Xvterpe%2BSp%2FBGJy%2F%2BtWsVLwEUCAXd99ZPfwHkQBlLXgTQgERm5cxDgrim5M4GoExarFl9oCEUGgMQbAhBBitwI%2FYQgDgcDQSXOhkJtc%2FY8ukMmepK1AIofKHooAAgFwC8hqAWYih8Vehi7A1FxZ4nFHEjwk3CqQbuHzs%2F2Qh15Yd8uGhqGGEtZuDj%2BX9G4V3ICAsG4JNrxPFhF4Vf5f319wlxD6a13q2NI%2B2nXFXGqCTilgYkOeSrxKo%2Fn5QT6JIktFA42mHXCWlyfP24VK6iPMMRG%2BAoM4zBHzvfP%2FwQ8t98vl%2BdsgL%2F5HjsCX%2BvdIPXHkK3MZ6lYjRvcENhlT8hPUmI48n1XqMlbBBCvy3txBVvi4lu1Iw16J7vGx1l7NqDXjB%2BRnIL%2Bk1WITP%2FwS8aZB9t0GLQKyFpx7oqVeTwnr6u%2FWpeL8E3edgIwNkGRHOsDkHaBV4rdS%2FvafeBBGBcGAslX8L1l9PkcPnB18ZEiHXXeFRBDeDU4mJzAAF3RBaQewRfHVz%2BAKZooTm3%2FQfKBPrHJ%2FChtPTfK8edwlOhqoSGG6WLuMCShi3HLEdZ6j7YLcmnIry4Y4y8WrwRz5P2WY%2BwXjbALn7u9VOGBT%2FrtIEggdaqpUtyLSm4XITDuCHnOCH2Xltnx3uv3dcv1Pgxf%2F4sr3vfZua00%2B%2FxctG8213bfqU%2B79QSCDmJ8gxvQMa6oGHNhmHfROP2Icvwi%2FenEYHUEPgcQT5fAohEG40g%2BPEYVr7Jj9YF07jzFt3ezGqlJn2UbeAAKYsCbIcAcOAOZrDEmKDii2BdyV2hc6TqOGpdj8odOwY6jxph4Svn8go3%2FgN8%2B%2F7AftWDJ70f%2FBNeQJSABjyB4YOtt4V8Kqnh8UfEhAUEQQEigPpxLw16Dla1%2BaGJZ%2Fh3Tc4IXPSOoZG4%2Bo%2BV3Drx%2FKiGmaL%2B5jSfT%2FBF5WH0rYJe7MGN7KOyfmtzqPI0MvJ%2BHuJ2aYu00r1WOZj5cak%2FfH6BLzmmgWKa%2BOAec%2FD99ymqEm4YrF1j3tpDgKaiU2f974dn%2BcyOjJDX4hvPql8H45otK7UP3D%2Fdms07sEFGQgf3UreXP%2FNdBUS9er6te8TiC%2F%2B0rvapepi7vXuQke67LksF5ttPj4KisDsYIkF8nv3JmKYMBpdkMNCA%2Fr7OdfqZhtfLrzi44fLD79QWCncIeXQv8syBL3OH3Pyw3TLhJ3xOid%2BYwH7QYftBfwqemyHPFs3qJuF%2BH0y9PgkK%2Ba%2B%2BjSEmwTPLlp66sMaAw4s4GAaVqvQYMnhZT%2FcOuWo2e%2Fl%2FrQkIG4P%2FCF4IDxJJ7zzsL7e0nn%2F0JrsKSsbYYiQ3eUIBtD6bfsnt%2F19bUnFyebe5C%2B%2BvT9RGRGx0WY52wMEMyjHAVvu6G8IGG9FyRhIcJF8zHbv3xo9oShEGdNEl26H94A4UiQ5f0rwYE5pOK9SwzT%2F9HrJ6dahe5vBikFScLlKyrTL%2FfdjYpiX%2FdBpxFqPvlg%2BnX1KkXk%2FLd93o6Bj5EfH0fv0ZP8v91RDBUXULst8dhPJO%2BXELA7R%2Fl8l1wnyVsbo9%2FQRkMYh5nAGKUQjAwMA316oJap31MebLwgJHr7eViQpYKhBFtTK2Z07Nw%2FSmCpwK0QU80vBGDA9BYDj0NTq728w1FG6pxTjGCzrEjNd5Ms7GeanrP9ZzAlfTntzQ%2Bgn77ta%2FNFek1jB5ZyC1Ip84rsPD6I1yCKy9%2FUZoNeq2IOomReqVb5eXraiqeAcfCXP%2BGJD%2B8bUE9T8KPnZaJR%2BvX%2BHLt%2BxY1toF%2FLKjXZtZ93NySy9%2FhEzHJQD9xUncZ9adWuFJ916gr23A1ayuGO0rNnHAeCw%2BCyXAzmunomTjUUSjBRpmMn4Jvdyrf%2Fvrddfisac8SCNaKFsN2FBuZMkvvG7nL66%2BT7T%2FEZV3cwueTBfo7HEG7u6xCIsqX1Z3k%2FunxXr7z%2FrpyX4dUYRUZL5f8SrHCEHZnLAq5R5XFdbCpQM%2FvQJ2C7DM%2FrXGZXmQWL5WprWyDl2ZV8oaDh8I2e9%2BAdLpMlU6WmI6r4ow4FJUxUVoJ0xWvymzEI87Bo758vxAWOyhIYO6dvb1ix4h%2Bzgs1fMa3zXE5qr4GIZfNfh0Imvrxo816TPjRpT4P8091faL3qryk%2Bq%2F7ZrV%2B5pRgmHvqKh9EmaWLIoUgdWLgTDP7Gd6O7%2F474MIAMPZzn20o6RaTnl%2FL6Hl%2F4YKGasEL8tGXr%2Btlqv4biR9vm3S3eXd9bZE7aUup7ddK9VDXCqQryx2PJXGj2%2BtD5PtXdde%2BvshTMEz%2BEyASfzPG4v%2Bej6W0oRN1DOdFiMxe3LH%2FX8IzJ7mGVvI7dyYtYvcca8oiwZDFSY%2FqXe%2FCI8RTeBG62SKdK%2B8M7GP8%2FyRBAfYL4uJ47L4YEAlmxpmMzEcF%2FZPuOCkrxeLVmI4TwH25RwrLKF9FiUbpe8g8tR88Q8GNgeXd5SXziuW3DwAVUx%2FQKCWqQaFYHWC6%2BDu7kvvv3pdqCITCfdux%2BCbvnGV8cqc9sIzcvbb33W6DqddjeqfckpyvQGzLR0IZkpKLthfuGNqqDBrcgVt2Q8bVfOph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a1CbiCPcf9r1%2BtSbosVjv3gVgR%2BGgjfr32rt%2FQYEPcPokNqBGvoDQIbPFd%2FiytzGhl9a6L4IBoLzsaDjQgPWCR9eaWU%2F4I5C%2F2zJy6zrXqLvPl6EYQMnr3ybVwQ3d7j4LyyqHxkYNCYaYGV8yY6ihC5fk4SJ9Z%2Fih0dCdClUdMLPw0iQHRk%2F%2FRWe4JOQSAj9D3TvwWcczpIJvgwBs8cQD%2Fakiec2EVWYMfPfn%2BgUGOwCtV9Wap6C7p8GR9JcvM%2FMJg7ehy%2Burgrw6ny4yOfzebkXc4JCCyCvLr9e7idf0XL81Wf8xNV9K%2F4VxDuCf8iwDNmCmQDzlodFRvjhFinv%2FHb7xEEBsoycE4BSfl6qWHkSgpBUaxArrUEJMRyg9VuCLN49Rj8Exxk8aunWM1Y8k16guysNd7Gw6rF7gtMP3f3bZYdmyiJg3F3y%2FdLhEg8IjpOY4dpnXJj3rFhZEH2j1BcNRZli8blW%2F9cvYEqSEd9gb6D3hqfChLwLjV9YURXoxqGJGYphXDYLYjaQDC21u6KvdipR9I1up2Cv7Z1RP4KEniq7QKi9lz2rnxtC82UkJ57mtymD0ZZYG62OfNnIlvKRAq%2BqdvD1heaP%2FxdboXUhxa0MJAoF7lmXdXsEY%2BqD3YUYirvtEqvV59fWTwVEsny3QM2w2uH4zhvceOTsqp%2FJD4L8PoeAveOk%2FbMXOhr%2F4Le7nz1S1wT5W6b2nF74I8nZVs7Rcu%2FwRGDimbWLK3MXOxrbUhvl8npLL4KSBYWH0csUF%2Ba2vNfNpuUFXwCzLLPJzAWEeF8f76ZaGX6gOxfP4qAfz%2Fz2UUsUBpVrjObAdTJJR1%2BzCuNnuyMU5fssGXGHMxSHqGCNLyp7h7QwaSV0pNl6NIFJeQ2TvOjwMO9zycyPfxRltRXn7pVwnCZGc2NKvwnFlVdoxBJjM%2BUmq4pSlxDfll4H%2F7d1aFsifYg7B%2Ff5skL%2FRSA0p56%2FYYwhuTRPle395PBEWHsS7epyKE7TM%2F%2Frk%2BNdoWYuDMq8kWr6c8RtGNeDsZvyxGJkuqsFsxuX7CT8RAfuqCNMgYPDyeibD0PDmeNcQeUSIIIcFpf4d8Jiko%2BOHPEjJsNhzhdcWlnvLUN%2BsusIECBAjpXLZc2YtDnj2vytTKzYUGozA75zofUL9xVVwe%2B%2FEoZPnVKbpqvXLu%2BcWQVy0bJ6sQ%2BYJiKxPtC8OVkpExU%2BK8NlyXXzdF1rheXsbsbZWLr76vhZasn1%2BpLz%2BQv%2F0Gsv1%2BiD62n8WTOysOcGF%2F%2FEYVseLMrdnzuFeyGojW4QrIo9Laa%2FyfmRG4vD7Lcncd6lFzVNb9ZIuCibNKArWqEf9rxUEeGYiEQrHfFro8MRr2zOfC0XLrfyf3nJIveiBKqQKnzZ4GkMjsRMCqtnMqlStzZ3rwfBIYIl8T7%2FmJe6R9qZV2UjvbkBRN%2BF%2FBQeLGK0q4ST0Een9ZVa9%2BvVdSnJ32j%2F%2Bf2GOP%2F%2ByVr8Ep2OuHFrPrlrtFl2p0q1gfjUcqcXk9CVxkEIQNmHGkdNfhePtfmp%2BpJtpfWL4ICS38mapr%2BfW73ZQW%2BK8DnNet4RKBLDY0zmx1ShwYVRoNKMvmB8OKNj%2BsdUxzTJSv6%2BYSXwbJdplrRhTVDXp2L9debqrnUyXft%2BkhGW%2BgeBRkFb9EgCUBVgEkFJAkFAkNQkNAqEhIEgoEhKEQkFQmEgmJQoJwoFhuIwiN663kvnma1%2BdZc49ea3GTXjLzdVOJ9U6HidHbZr%2Bt2%2BnXo2peDr6%2FbW14jUHGDt2zQ6l5OxpKj0p30Lq%2BgvCh77dZqH0hLupc0f0US9FIvLsF28XT0wvvv4H0DM%2Fa%2BdhKmtv28X1etOeN%2FwO%2FD2ch%2BHSgFtvfwtgECfLq51Il8aN0q2Uyb6KIWbnJd27DHMHcntp%2BJ0bw0QTyOo7Xa4ytgBofdvFK5bktIiKqgagcASxUlEQ0CoUCoSEgSCgiCYUCYVCITCQhCYRCYUE4WGoXCoRIvmSr99deNd7nGa8dcept1fzuVlJd%2FfdwdZ29Xdo7N1eX1rq3xns%2BisdBje7gRf33YOn%2BzaCR5j%2F8fZyp0yHU9CHnnvevlSf4QD%2Fk6W91v9PcMb%2BneB7Lo1mn%2BqCGOsU7hW29XT9VOpo8vDXvNdg3BAgeB4CgAUqcKZwCa2br3cmous4%2FjvTuvSe%2BZG7q1%2BW56un5kj%2Frru67YMgXjpfllcx%2BMgM4c%2FObOQgLkIi9EYgcAR6Z%2FZyWTljCcmXhVSbqr%2BgnKa4bnSLBnAWpsJ%2BQb5eVu6Nz20WqC3S2ivrfvPCdTuCU5ToaWrnGh9UGBrCYoioOy%2F22etGghFIR1kEb8oUmZIf8F9Hu3Zzm7sytQWXkMYbscGXlN%2FpqrtMjX40XvbQByta%2BhK4eJ7KdJDulRPeSJTHmE4WryAIUoUYJ5nXozhhDVILcEp5Q1NuHcrM%2BW48ZFcHEuzoVrWgXBChOrVjaILWvAhIlnXViKkgW4lEIVwicobve7Q95pB8SA2bA8WA6naHI2hxMA2vGJRADWGGJtULDgAEkmf2cFkpYuWKkS7d3NbNewjI1KYMgIrW5PcTzqVmxYzy20ey7a07dybbsq6xmUjvkaHAPBGwX8HTV0jecT6T%2Bau6t6%2Fa%2FtHtHSPk2BUdF6cEv%2Fwqk%2BCSRMBXTCl3wSi7zIT2yr7jngvlKviV9BfYX7TsK06biVs1YbqjBHJeDhf6lA%2Bg3W2J6y987dX01VjlnVVhv0JrNWSSc%2BMxjHHoYiuwRvYCnrOUKr824HaKgJ2GFYG3E3A6rIdDkgSQI5B5SHu4B1wHvAmh3gkklMCI3D1xPEAjc4AEk1JAkFQkFAqJCqFAqFAsFAwFguGAsFwsERKQQqITueO9X85Uz49M8%2BJ3d5xk9p7s41XjzIp7DufN2%2BXV8zv8Lfu5V%2Bh7vwaZ%2Fdu1E5%2Bn4Bqphl7bu86VsdlPFgEzc98gwOz4DTioHB8c7r61ACi8Edb99Wm4GXurMdgNt9dRdbhfrg3MZ78xYAOr7ff8OVa59fXl2i%2FTgBXjdF%2BFNm%2BZQSi5sE8%2Fj4dpPhjaueevtgrKs0np8X6TVCMcJZMoTkEk71lICm4HAAS4UlCQlGgWEgWCgVGgVCwnEgmEInGoRCohOquKrfv%2BOeeufx85vrxcqH09M6vN9SpTgOjJs4Oh0OCHb%2BC008Lrx4feH5eHTAn0APSKx%2F17eO8D5fPP7sAK8T7sA7vtOI0wDoQX6hfaDAKD%2Fu9NsgiXcM4KFk7MKdVsUWLp4HobXlyABH5uW%2BGtj1mjlla9PPvYAcdBz%2FEtK4hUCC1X3%2FqxJXuYL5x%2F9gUUHp6jqWJZjOL9IsyC01AhWo8wDgAEuFIgqJBKFBKFAsJAkFgoFhOFRMFQoIgiFQuJQiJQidWs13x88Vv2714OPGtc63ftPGV1U3qI1odjocO05byc9%2FN9rhnCzdpA5ukFSaTP2TaWBybV4dvh1wfx%2F9ODUbzjw9IOrGVftANHbIxJ8tZoe9kW0Qa01v1GzTalRgpxnF7%2BAKz1UnhpwAd198Gr1fi7CT2t%2BQBmFqx7CpD5fHgiJW3UaM5G%2BF%2FTJFe6%2BsVNS6y%2ByZNEWhcRqoTO5SwHAAAAKE0GaLAsKBX%2BhMXf6nTuhn7J8%2F9%2Bvdyy1a5d91fdeuUl98%2FaL474ZWzzVevRJSXXr3fc0oc8Fr6DxvuOdN%2F5%2BqBcbCzlYHGEBuPGQ6MLzsMalDFeP5xJ2%2BEj88NcVeESBjuO5bchLiAEcHch1OnlBFLWmjgIEP74RA1glDgw2DXkgt7HYKMMtMfB09pRHZv8deBB%2Fuj1fUa6Yd5WZs4vkamJHvdOJ6T17Dce9VwhAyBAoTjgsw8%2FxPgrx5zy9ClxxBctQpV33I%2F8cvx%2BrHfzV6tJa4VfurlWrVgsBgCAVZG73UQPs4feytav%2FguBUFIl%2BvFV3fd3LhGdXsaCILDPBlSi5PYPy4XJ6Es7d8SAkgWDdWc3kjhNXx4tC07pC0RDpk0O1OXmxkTv7C4KRaRLuGEZo81Qs5MzTKaMyyJmJacNhoPkgf6NmixIWoPbovSTE7smc1VLh3G%2FEi4OqsXSJHx7fgO0fhkkg1tDX8LLW6hZO7M0pZBpq7OfZ6RfmBvUs2wrqnaEE1aBKrhwCRak13%2BPwiSE6VTB%2BiMr0ku0feAsgRHEk9Yn54b%2FWVjvUmEquTerVclyXb4VbIKNu78tc2EVC6yIhqmj7pE3hBXEpCLTbeYyYzzQ%2F8g4QNv9jCoDc%2BWaFcsv4WZZb8ynUQis1ykHHpYn3U6hKDJWOMc%2Bnt0pqrdyi12h73Itm9rSzZbDBmiBVJ3t1Wa%2B47jH84Zfob9rFUzeXmz6wnMEHE4bnnxcH%2FHv4hz4btVhCYCDBUBjlElyzJA58tviju%2B%2Fi%2B8UtWj8%3D&media_id=1254206535166763008&segment_index=26" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:32:08 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:32:08 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_pWESYokmOKFnV03Hdm++nQ==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:08 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786112818783626; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:08 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "a426f2e97e26804cc0efdb85090eb00f", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19926", - "x-rate-limit-reset": "1587864356", - "x-response-time": "31", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "00d69f2c0050093a", - "x-tsa-request-body-time": "64", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"cdyvv%2FBPfYka75gUpuXZOowArfc%3D\"", - "Expect": null - }, - "body": "command=APPEND&media_data=ViqxV6sTXNfxH6lu%2B1lfBSLGU6d79Cykd3esD0EoNA0XVQFnR8FVpC11wT550B%2BjbVpM3hKU3CE2MKpAwO74qLxf3XNZPX%2Fn1R%2BlEcvqZK3WL9Ycm3pYeAnixg4Jr3JoxGH9MlCbbhYQEW5guIELc2QYlkdJQGg9FVHDCYUk8q9I7Ws0BBDcIkIuheNGDa6SfNQWRJLHh9VQGpy5qqnBKJRhXrl%2BORqW7KsulzfaCNeb%2BrHxXV%2Btlbq88vd%2BvSXzq3cvlEYUHw%2Fz%2BT8AoQNGKxQodB8pdAdHwfeuDsiOQAB1L7Qc7Eyxfb07U4z1l4aDJHruC2ua790EZVurScy9N6sq5mJkhQIXcD0NcdA%2BJeIecAPc4B545eP0Hy7S8ePhjN%2BgnUCHG624ks9hyeSa%2BH%2BpcXdWYRAMYqYWKrMZY7elp%2Bf6eNDkXS18fQe36DBdbpXmzggYTNhD%2FqERFG2TwFo7sWl9ThLaATJ0CeaSrcE2oPx8op5hl3JRRjb87C%2BPfo%2Fd0uL6uvXv17gw1SInr3Krz%2Br161Xq%2F5jbDGRhvoFQgZ44B%2BJcBZD7yYBVfQmVvjKZPh0%2FBMNVg5vH2xaQjg%2FBKU5IPbr9BqK%2BWtXECGZQavKqJA1y%2F06QjGWpMhbXTx5o%2BELzdVVGNeVhukS8uVOou5aaCLnfYR58EIIC7Nhe0UjsIcVQO%2BbTQ5vff6F4VzVfzX6Jl3Rf%2F1v6PXmPuIHKYmBIFxWK35YrFbRsk9P8XweeCHMQ4D3nyky4XOBTN4CJChtXbqAbMBMgTQwZVLjc4CfdjGF4R424cUp8ZWDoWCPzA1wGOIIzbBh9Wm%2FOCAfgg0ZwwMUOou4jaIR8GdaDgNGvzF4cX2PhqcEFgbKEAwcWzjyY%2F8LbCh6gPCF%2Fr8fKClATJPVwSCWjqd%2FwQEOSAau5PjpKMFztlsskP%2F8IsG93L%2BX4TIFf3MFt3NK6Imn1%2BGePkK1bHJoYv%2Fy%2F9FhuoGHh16BapWDmv2XmYB1%2BjcEpb3cJWCy8tL%2FOcioLFfyfS%2F10tSZ9XVosVivfFh4eEyXvu%2FDUEpHfuqvrA6AqCLBZ1F3XFMUNUslUvwTQ1JKLNVVxdZfhSpsXqq1VawkgKQbBeV7gF8bUwuExeIF5YR7iBf8DtBLEAAHMEqoAAnAvBRl4EPQLBKDmVY3VAcQ8v0LMX4VpVGEuNUBKv1wv0qCXidgzdUReq%2FRIq8JZvIw6XlDJR%2BZ%2BvkghPXkMbk%2F8RLONLGsZSfyeSuK%2FWjp5K5p1i7tYIQh7wnB%2BHxBHaxL2xXrCpwJqBKak8mMzy3g%2FYCINvAXJAJIICbr%2BCaZhSWHhJTHJeL2fsobSPbgwH89fJSw3XiBtbu%2F8Egoxij8vwni%2FVVXkudhP%2BsX61y89PxM%2BL%2B4wZSf279YVzXdq%2BT1%2F5MCIEddTa4IQmTwJARv1lfgtzD0mDZl%2FvxHVSZ8uWQ7VG18hgTv7X%2Fvd8vq%2FyVoteXd3f6mS7klrwT71pXZfnN34el%2BefyCMnr2LPu6dqL6QA9QluoEeGXS4FC%2BCAyJ2A%2BwIJW4Pd4COQdZ%2BerEcTL%2FyKcNUPqa79RbXZTOK8l36u1eYgrjsnue93mIde0Ve92YFhXARmTQX0ccqmryrcjAulv%2BCmkdLJFJ5WYRxI0w2dfd9t4K0DgOaNwr5Uo6lmB6b7TBC8w%2B%2BjMRjX80M7YVdX%2FpEicYWzT%2BHGdKmuL%2BBpN1NGYN%2FlwYDYRQ5RDPWSe5uecQCrG2KjMdGwHiP0Z922cNZkCOjZx%2Bc15hIfpwjU5PPc3x%2BEKlNuzMzi6EPk2I%2FDTKq5QwP4RVOGYdw2TO%2FL6dY69Z%2FPdz%2BhTxNrl%2BG73qnj%2Bnr0WVecy%2FJCSH0NYfIIRGQJE4z1EGy5usSFbvpyR4aKegUkigo0k1%2BmCW2I25Nj8%2BejBaaaaTIbjShI%2FnHOqTv635CB7Iv9XrK3aUGXfGkDPYXbLv%2FGHmYUWSyEmMY9r82UxybLcSKbJNJ0SxSeIPgk3LibgOo11dmof9UVISq9okKahiPaQ5Vs1Uf73hN4A7JwGJtG9LZsdy54VvzOGwv0ld7r6Zt8WbHmjeL2c%2BgMySlxr03z9ei7kndesU3hkgwf1bEvmSRgcNAZPZQqt316M6%2FQl%2FzEmkz15jHkcn9IVBG9Mympm%2FJ9xaI%2BsjPfbgl7G0Pt1vDvg0zCH6p%2BP5IJSHA0EDmegPeLfE74OzWOaYKVH3Y0l%2FekTD0Pc6VKxvBv98bzHTwUHijHnjnuLpm3bLuQkKHGWe%2FMrMAeeSAMHWok8ix1F8Z7J%2BIngyDYzR%2B8T6ZX%2F2qis7YlZ68SCAZCx9PmyL4ngngRrWreX2cxh2hKPeTVD%2Bk9Yrui%2Fr9%2Bci%2BWGQYPz18fG7awhbl8hp8yLU0M3y0W3Jvyf3iLnqY0nH%2Fv52CPyY9eS6dF7CML6e7v2d6ZwMobGdxDFvHaX5Pt4rDgqC0B%2FfBXVMXEMhPpPA0SHmoIDOtQlwKfX9n6FxXLPd%2Bt6vv9EIn4IuxvUtopa9Uc8uvvxHzJjtImcyBJSNfF%2BJIqXxz3oEPJjsbwL4XAuh0Z3eyjZOqWAPOg1G231u11gSREYCsVzPDv%2FCmS7URwLh90lVjoV3xTxl1aOdN0I8lysUtFPVAXAsCELCt9tPgiJKV6OrOwAAAEaZBmiyLKgV%2FNE33GeheXurX6seEvaxcqy%2F78vtWyfn%2FVVevTXXEXl%2B5icdpwiGgwI8tMC0dgMGJ9JY59ayaTZf%2FEBAMFLneXliE6gIXgdMu8D0fNRdBIOcuVy63iqqAaIKznSrgW%2BbcN0pRFw%2BGBGBtw0oBiml05W9AlpBU3ioDKSWPLCwX6EnvyAOsYBUDIYvrEeiaxcomHXIl6tAXzf9V%2FBbLTEawOBhwMANJguClCM%2BwUCtCnidVx1Dosm%2FqrqX3fxF3%2BvUOJ9drL9WJMaEBQ5xmP3q2s0CcWuFsPv3SlvSv34EwgPMMLvR3Cnq5y%2BMCXAfsBxhWTmjcD5%2BtfKsDAAH4AQDgAHKA53ev%2B%2FfMjgIjAV3SyHWgBGeO3fl24v13L2sFrHXrJFQAgdbhMiN3ZgCjQwty%2FFTgXAIgCAAzDehYJLcTwDHcS%2BpLafRstTQ6Ram6G9xbv5pDJ1FOvXLmDfk%2Br8pgDutt%2Buy7XbyckjmkOxEEhAlS%2BTNE1VCTsNUFgDaAKgaXIdVzh%2FTax8pD17csdO33vZ%2BK7v%2FxV%2FNE6I5%2F6DV27bHvMl4b7Ewt1uJu0%2FqbQ2emYScJdTCCAUSA5bT%2BFS6LdbccN42dQlR90Lr9a9CVZ%2BvSjiXqW1yv1eJ0J3g1gzCIIiR%2F3rwCBA6BKZ%2BHzEuA68zkhhBQnnQBzkBmML4kO5S%2FFWB8cvzYyqP%2BgWE8I%2BoyhFotQKD0%2FLoFzU%2FmdcVugJOfiB%2FYGUL%2BJNNfczFuuBgFcGHLFTjs5gWyZ%2FLoF8wAWOHhscJO2efEn66rUDLCA5Jvdlr4C4DAaIovg4ByBgAVQk1BeAWPOIBqDEBmb%2FhAM1XBgogODVFCBU5SUvxcQdOVXL%2FgWBRzxzgl8f%2FyfNRv2i5XzfE163O5PXVetd1zVoy12rMn6IoCGZ5AhF%2B0QBVlBDLUSep%2F7Cu9iVXUzSU1c3zSYvfo%2FSXXr0t9yYnl%2FFDDkBAQKDgTkntAObJtvghCE%2FZWGL75R8hoPYe%2BlDGpf4tSYFQLgAekJg3InMnkJAtSh8Dw4y4AycmN03JwGIzl0lVU2Jecr5ZUaKnn29grH9R9cWB9%2F2gixyMsVcvf6v3Xr02kpU%2BJ7kuW5Tf%2B4148d1wJg0NwPRMfjZaQUgM8Jaxvjh3TEneJl4A14ElHfihzoTiQcCRRCZTGFMkrxypAwnuTWPF3QGSviwP4UFlAAIEQZAIhtKNaeiABCHW64V6apf0%2BOo%2FS3JfctzvGiAOQLwWDK14hgED0lLUW82pZeGRVNi5O97TiC8A7khqP8AvmpEV94%2F5eAf4n4CQ7MtDZUFY4NkACttyelyfJVXYeF9r5Ra00TkB2nOlI8tSTMLqJm1%2BVRWc3VL5ETuH9kGpMJ%2BHskQ3pCfioobyyJPKpFOEvo%2B8tQwXbYO2PbZ5REUv43xM5y%2F1RGNNAb0zVYmdSJItExkoMpnRwauJb081jhmqWGbfyedZ6YfncB6zYgslhRP5APT1dzfHh88rCZLs%2F8i1aEvJdXXEInfN8IeF%2F6tWJ1KvfMsVZdXWpvG2i7KgQE4dy1AoQDqnyO8eBZW2wGAke3fuX7Dvt4hpchjGiXxN0r09XZUCDQrKGftIoyWvBSfblEXYVijPBz09SUh%2FzwIkfCHWg4kFRQS5MWC%2BahwYqp3aRlXpgzeO%2BO7%2FvYdLDo148%2FCy%2BxrUt%2FBrETKjjv%2F5fX8QUO8%2BofQL9HF%2BoZMFOWFwjYS%2BnssP%2FqHoNz9eaZbLbZc8tB8iBoVlnbp5Wqow8iWn2ZYdl3alqTF9u6l9Zrnf7HnnLOvr%2FKwvXnYf5siEF8xPaSnDWncf0EENQnpK8EGYkPghUGA3YV2U2WS3%2FmOhHblKEJiUmlyKc%2BVvpEy41CoH5u8KfJvG7Ff6L0i8CCDAXd95qM64sMvXgYx5TYr8BYhAonP%2FAUIQ8DfMasAq8T26sqA1IO1UUxIcoxODKAEi3QJOjZqgJxDaD%2Bxw2sO5UsNM5WdUGLlM4Dt5Rr5MCCRdrq8qh%2F1YCzes1%2BT3%2FoPWW4mGwjLcVGb0eUNuA2ujCPu43ER33d8A1wRvGf77jQwGI30z1KD%2BN9DgDNrtWAXGBM0vW7mOm9YOrKjdyir1YSxbtWMTWB6IDhhfr2GSmxev6HT7569UVt%2FhwkKKloUeVrmGJTL%2FgGPqvKOX1dcGBAjHuktGJn6Q5KlaGlHO0FP3K%2FTXJN03syTcL%2FOzqCUqBjTg%2BMuCwkMQdgln1LBjDXEXqC6oPDVqHombcXcRoOxXFceTGYpTQwP9tKrPV1ffcvrlJg5Cy97iRG7bvesJb3zgVAhvnsWbl77EDnATwsKFFG4oDEvUSHyTZQkAcPeTK1w8Oou0tsyV%2BgrEgB4I8BYMKo8aGNQc1UHQZ8C1DrXOH964dG%2BK03TCNw9FaGJ4ZwpXPB%2BqG8owevTFEkZsA4tpgQPZv9EbJHxtSTaWUQFAVIJqLyIAZ6bwllCleIQVxX1%2Fnq284TrCNgwZMnD3iVKYzXU0oiPa5m43jVkrBpa321Q3htWrfxL8W7ZY3FG6hun%2B9Rd5xHfqCIu7%2BHwTkh%2Fph2ruWsVgo6mt9uHYK6pvIh%2BkmZCKgtMCYpsUz09%2BP3f%2FYdLwY22lyBrvb75pyx1dUxsh%2BT0vvEGDihRbBpiuN%2B7Y2KzZs5pThiWkN5ia4cTC1PEcGzyRFV%2FDtAmCeMXQKQTF1Bf04V%2BMCnkcZ0yEIy9bb2GuPQop5dTYNPLalrD21fQ5IV8Q41n2A%2FKfNNN8r5Zo4U39oscrZtvz1X6x%2Bn4CyGPByfwSly%2FOA%2FwagFrgIEBRjhit8QPdnijiH%2BwoUVCyI3%2B4D6zpckvoHhHy9KCpJgGlPOAAO8AqpDeurznSlBYIPw%2FD6HGguEhCf0B%2F%2B%2Fo%2BQi5QIK%2BqajRMY7Jh%2BST%2B4eK20Olhylx4klGC8hj4hORxLUOogvS37%2FW0QgKcjIQD1dvyqDUsS6h84%2BYfONf%2BPoVE1TDq1OKXhl3H%2Bw%2F3cOjS924RK8t44eFp9ngVP6%2B8v19gslYjjWSVetk3BvtIR9vuju0vUJ930ZaXbq3YZOQk%2B5%2FHZas27DBrOHGwpWwa%2FHTSa9IV3RUN61NMLcdIS8g9sq%2Bj03RcPvP3DNu3XxF8j7vpvCu%2BJiJ%2FAQAf4xSCnEg5Pmw9HQPKYINJ%2Bd%2FGweaVZ0UwYCsrEdH1%2FUaJGgmYSEwIB2qLu%2F9UkrwTNoNtGrPw8feMU%2BiBbjczrEPGKaY0MBw%2FjZQbFH4W85PEIYH1OGhgox4QjV%2F9B69%2B7UJlPpGpwEw44aEyf1qPkQxad8oKeDGwmLjRaL1%2Fl2mn%2F3mgliIwZlaqrlyasbU7BFnUzfXqIvty2NePcVsqboeSI1jrJOINBGYx5MYOuSZ9IMCUoX%2BdHGdXy%2B%2Fh%2BOBS%2B1eigvIDHyg%2FOICXHsZKNSC77%2BvwUeXjgoM%2Fsn3rqN7uE33JcSl656X03oJSSEYFCAY%2F%2F4Q84KGZXQz5gNfxSRCbeDUz%2B9JQR%2BMSo3JH%2FfEeLzZPk%2BSrH7Ju%2B0Lc2hO2Kx0EF8U%2F4kY0MDn9VlswYBVl9l%2FDZzDyO0plAwJMbasEf%2BstNlEhuMU1YFGkvghaWWx%2F5s0M1iwHtv8qEv7YIBHCtXjYl51GZlBrZltccAk8Oizir3FSY9Bub9iSj%2FrLuvFDFiDcppyKPcNCa%2BM4WVXD0sWGdMySi6Lk%2Fveg8dDcGBePCz5uXQihYjHMdEXhy6j5Pv3xsv93hMzwpmErDNXokMSjiUcZs9UQ11csnnn%2FY0RfZHDAe%2BANtPZnjMTavtv2%2Bla5j0v62Wg0cD59AuvoEBB1ze%2FmULZ5XAlaQ%2FCn%2BOv2DavG7FZP6oT1QjPdZYJyCt7UX615bvNuv0WLnNFYhpy%2Fll5DKt%2B%2BXyl%2FC8ZBVwi6xoNdAvJmsM2ZeGvl%2F0SwvQYxGfGsqa9arzKvl9%2FuwIBjYu%2B3UxASsQ%2F2YWeD2O%2FVH73BP4N6ZuXnDAYZ%2BGZtg8lXRY4B3hsv%2FwR73hj2Cbu7veWvw0QAj1XNnDK9z1MrMqH7%2F%2BsGFuH9XHlKyox0CrRSH4R4v1%2FJ4f2LIzAlYXvvWpE2NspP0hPwQQhcPeNQwIaaYTrcMDMubLp3l2oauQQQy0Tfi8FeKHoSnvv2hXwRNqFNuEIIVJN%2BRit25fzupBhB%2BJkMPNnFy0pGTR3bpiQVX65XE7SK5BUsqCyl1Hf5M1NhH9zSplIJGfhtVttAf0G%2B%2BVbGyPSUKCOtVzlGlogQLtwqkqR6qJFeFOao%2Bqq7cqPm2BfQj2s9BSLQeqvTOV5f3OJOcP%2BkNaGa38j%2BmxlYr5FPYKMcM8b0CiO1OUeGBrUWY8QUuVt1Tp%2FAZqb%2F9nE5ctRV%2FxFUoX2%2FuhnX6vKX%2F%2B9URla5frlsL92aBF1J02BvixRONIDaMFGOy9BXppDcFvcFGDNApqZZ172cH1cV4z5fNrUdy5wIX0a5vM9DBgYCv8LdseA5BiUx2%2ByuT9fz1%2BSEaTHwrLDfec12zHEX%2FJ9pOuCQvAQjOo0J%2BGCOh9u3Llf4bn6f4JKHd9btQSiSMv2mN%2B%2Bx5O3DSfOjwGqTh5A77rBH5Py9pQSipQMO4FwvFOKaAGrcoAoGirknbt%2BSdSeBJxOoKZuKwW1fKcVMXKa9av28a1MIdqeg1%2BmToGG9JUDFdb39bmsIwGfkvIEOamRHIcYRaUELHLAP2xyfdRKK4w6rE15ARnZ5dWjPGj9bs25EZLAUxg%2FXDxI6bMXAMewnXlmr88nunUwOIdyIzNb3DRkL0%2Fhm93DYlh8ywHWKeQyq8m5UgZibhchak1dRn1%2F96hsLjOzHvcNXvkvk92E4l1MZo0%2FhMLgrLqpUv2vaA7%2FslX0Hu92vKzcua7zH1XAOsDX4fCffit%2FJrr1MQeIkBeunD%2B73syjzgJTOYGzp91jAkKkQH%2BkFrZPXzYQEATtI5hUSK21IDh1M%2FJ775WHShM%2FarVHGWedRSYVSDCWbRgxwEbq3%2BxmJm%2FUv%2BkmFrvdjNB0ArGH%2BhHkz3rmtW%2BUJ3vZ3fOe5%2BUUUiT6khrTcc9jiT53HCEwg5Za9Qt0byWy4qCLrf8nvyLi9E%2B576%2FBaJmmL%2Bt7P3ficmCEzgXsfV9aTQYK98AS6Py%2Fx%2B3%2B2mQ%2B5LL6VUSCwRmvmqNga1hT%2BpgFmQWuaf88nviMZMyfiQ5lqCXoCBYxLxkhA1Qz%2F5q2HqeaO4r7bRxGwRHPY8hui%2FSPfSCsESaNKO7SWKv9pQsRYDAd4KfestNFr8VfUB6DhygqkzuGuKnQdJeuOlQdWIGXPOFqAyHERcGy8O1MfahKNjig%2Fn3A%2FfuVBTe%2Fcbtjth8O2DopBuKx1WZpIv%2BMpQXkPgdtZQn049MAVT9UoHSCosuLJqsTY4H%2BoN%2BCi%2BLHXF4UhTLu3Unm4uFeQKkatpQGdK30mDTKLJeOeSSx5d16Ev3JLfklJrBi%2BX2UrJxBm4VfztpaNb65fWtwYY6g%2FPi%2FGPyvXqCkrDdu9%2BzG%2FJVW6gv6p5cr5xk%2FYKg5P3X%2FxN27dt68FG891W5%2BHCbuvx8i2hgMv38uvZAX%2BXg6fhVEB1x5Mf995kITwm9x8KI9yVh102LgQVTjMXP6hkGhkXD5fMaYnGwKc8Iekleoj6D7Ojd%2FtZ9rCKCJQ%2FeK3mqzx%2F1uI7%2FeWs12iTMx659KZ%2B%2FRAUUoaTUJpC8JAnc0WsjSBbsN14DNkXuKNuFVZMr5frlIc0Ktz%2FxhaXz6mLp9KIfn5sl9fiAV1Y1QqPdKHYI3UkYqn4WirB%2FNL2hP69Xr%2Fkr0VOvSu7XVr9ak9CIPyXd3r8OYhxdfQY6edfw3RbufWkLeIHXdELVRGHSZAeeHQbvi8mz06hX8kmpfUEuLBO%2FQ7O00YGvUIkDHvsGG%2Fd0T0RL%2FS%2BC4JGFDZ4dszS0r%2B0lPpdT%2F4LAsE%2BI%2FBIJDx5foCGFwqSQI3ZDDfPBtPwq%2Bl8DeFwfhpiQqceIzmWHfWkzJ4n%2FoJvQ7xVFVX8VP69WTWru%2F8EMKvvsVcvVXVJwwoorVeq34aEbBsKQShJRPPy0zHuI81tEOSq74AAABJhQZotC0oFf6E5X61PqvfX%2F%2F65fa1wJqt3z%2FEK7%2F%2Fv%2F9Zf9%2Fff%2FaucCX32qd%2FVpLiONkgIPTgzDQsVeWSCD88nb7wO4cwWXvbg6SfR5fq6zf9H7ig7mtsDvlqyyjl%2BJJDvTgM5AcMXBReJGA3PBpXCgbh8NnzWeeMJaILN4YDCtzw04l54B2g73gVw2BTDPgIkE4b4K3La40aKv4H8E4smXCQy8uS%2FX4bF4Ze0%2FCJueG1Ja9c%2FSLWT9%2F6tYPnW1ZP6kXXrFXrhJ65S%2FVrl4EcHeYB4VoonUSDhzx9L6gcwwZJVHOKhiywLUoDVmMRkTrrCrxpUtTmIKxj%2FbcdImaY1wolT8bY7w2cPXZnAZOggqRtjiNr1rBZ0KfrYZaK6UsBYw%2Ft29x6ZJ7b7dYE84GoSFPuNqqLF5XtRt0sPsw614O5eK7PQnLMHMdzY%2B9YDIl5manefKjOkO1uwteCQewntxoIAZySSNj%2FgzymetQwIGlUboCi5bOsgj2xr9W6WYfxMAVLMo%2Fqi%2Bw9HKdY77DhhvhAfpcY3IYVzUtlF5Kbaux2TIVphs26Ba9IH%2F7w2gCWjw7PenekB90995Niynfif82i%2BZB%2F2vrr9QhAkChED4wsCbYzwMEQqEuxnAMHLX%2BhbqtX7V%2B16%2FWK7v16X1c6174zCCj7Jf2XzD6%2Fj0GjT5noJ98TIFOMEdez4dGn8wrFlUYZeOEOnTEDTiFesDANoYZoyK0IEdljGp1C7pLPAGJA1gqLnpLPSQfy5JkrzGZ8WamwE%2B9vazHx11TThRXTqZhAAmDJCACcKiBItU80IEmwI6fPHvgA%2Bh5EZfTT00%2F%2FOH%2BiTv3nTh3wgp8DbgfoclrJfjcsouX8JKD%2BggtAnWSz5r1Cq%2Fhk4vwgszBAuqg%2BAsP4O4NR%2FVJcJoSVPDNX%2BKrlWK%2FVlWuvVcu5Za9cqvu0ggWIFLXEucnvKAcYDAL4VNWxigGIPJyZUiOvbFXye4PQLpw9mGOIOHcbBPUwBLAcdzE9f%2F5kPZ4prrotXXa%2BK9a%2FWKM9Xk4vWIGChAwcAyYyYglkcF9iUqSwPGrPUChZwKCUAYlBRVITdN8o1CUryt9Xcu6%2BNnBp%2BaKezgpwDHS8Bo6FhcTUDb1K9Z134WMt0vKDhYivQ9%2B1f5VlcH9WrSCt2O8aNL%2F9GE8Eex%2Fn3uMEiwpm4F3ug%2FcTgmPdwjE8%2FCRBROYd1MdWJ%2BEiDB2RYqSiVHqiyfR%2FigKVhZXs2yZ9fCbBQLxMFwSFuat8nkc9LyfERFF%2FoSwfrL1Xr3Xpy%2F2BWBaBMD4sIYnQWSY3kPZN2X9wIQNgOsb4HHEuxrAuk952AV3gtEWgzJoFU1cfDRMFBGRQdioTLxcO9n%2FcLDwq%2BxPV33XPVpdUib%2Fp1BVXAgjCT6JWphj1%2FymRxe%2Bj039y7L4l6uNx1MVqYhjjKMtgN%2FzdQY4bHQDWvEDtatvcivEC6TVyX5rIi6yMkPyV8Df3O0f8dh%2FFBoyFPfUunVCVqlqHG29CjEvapuX7Xtf1h%2FxN476E16sTeuU79oEG5BitaMMSMAIT00tfPrTnW0MCYqMOM90bbf7QeJ5aAHdJqJiCwO4IUGpDAGtkomTN7Q7oRZHiHp81eNmGIKCqTDUuqXwKYWB%2BFroOxpsD4P9qewB7h9zfN5TR77gBF8UuiTl74Vtjw0WHihccdCdawzYZKesAL6FjmAgippgjTWGIIg4dXQ9eJ1AGo%2BhBsCDPPJaeJaZ1HUT7%2B7%2FYM%2FnKpzjBFv%2Bt1EGvRsFLQggPoKeP%2Bx5qyprmN0kbOoFwN8fXCSNOyxRZf2i0wU3V9q%2FxdU5ug%2BPDbDnkG8LT7oOtYJxLhiH0%2Bq5Ycax8V5dONPt38mjDO8rBSLCMpKVkJgxM9le8adL0kpPlwYj%2FD8d9bgtSTHF0kny76NGGeFEO7fodLOjmv%2Flrl%2FXu79evVXY5aVcCiEBXd3zZwLYICEffg%2FDwTM93fW8eeCDwEb8D2JMJ4Arm4SoHvjebB8fUo6Ynl2kiMGQWRXlbp1srcakmGZ%2Fp%2F5faavGw5PJVhY8OEzGxLVmXPhuwee2M%2BBr4kNYbIqUq4kB8xwglxd3L%2F9gggLW0XmCOP%2But75Glfp97c3Xc73ErcHl3pem4PgCWauIw0MB4EULkj46IDL%2F9jfQMfwastbSeVFAmM51FjpGXFlN%2BsQPXbB2FBqeefKiGLl4jpuJm3JZol6H6pl8JHWOhKn%2FBGTOcISyy%2Fr4ICUcbGsJM%3D&media_id=1254206535166763008&segment_index=27" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:32:08 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:32:08 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_2rC3yHHaeeCMY7As3WucKw==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:08 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786112878094850; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:08 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "bb4022da03a58093169d546e6d7d5b3e", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19925", - "x-rate-limit-reset": "1587864356", - "x-response-time": "35", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "0095cea800f0ecb1", - "x-tsa-request-body-time": "96", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"Z8jsv6e1ht3y8puTyYsPa%2FerRlM%3D\"", - "Expect": null - }, - "body": "command=APPEND&media_data=h7x0WiRHNoZUInd74Rs%2FHgp8S4qa5WEvLL95WZAjsZhJjHyjffeCjhO87GrvPvHS6wy%2BvqHTmH4uoK3v9cWCbue14x1GCQw0Syh7dpyfKr0FSWhlajwMf94MTPgI5HCGopqpgXD%2BT7tlkSC1Wqmkks4JRpaFnr%2F5BSPl8tilmuR%2BviRlPM8wUve8D8EgE0GgTlFbvuKxR38DwhsQAOCAHBQAGWAMQ5LBn4OngWHNl68l6adXJF9uOc1TRn%2F6BKU3CFK6kOjF6PVYn78AW30GxeHkWH7zwX%2FFQ2wHQofX%2FmZk5fk4D3OXRBpPkYnf7DnvfCmEBMCBcjZzsw%2BsmMyXGsBye%2BntAsNchDfZZKB5eLw%2BuM3y%2BquWFSx7YTXNTGEHsUEqPUo5HML%2F2N6U7BuTG5cQPjtDgHEI8cAAsHgDynsohg0qTJO9aBQXaHLnd7n40mK6GA92mQT0zrTeqTLrbBpbhZuVexwoD8KofsO2sBC87KUrZviMd8pZcHySTO7FPvBErGTeo%2FyJ7jLRDk%2FixHlCpA0xJBJFg67HHdjB5OvIaSpS%2Bq1h%2FYSLmRd0DttpYR6a3n40IxYcXyo%2BW5f38O0YimVWQfIMR5r8VOljCC%2BOhf6yXDV3HIlA07LBjLOyh0o0UsDxThXdgy8fh6mEJUNSp5ddcr5YG6%2FFW%2Bjk9Sl6zlX71v8PrTyNekuvJ%2Be8lektX8RrR8wmZwLA0zSEKZfB48p7nD3qz%2B%2FzUZgRmbT3ILvjKtN77aL3Cgq3nPHWZYX%2BX6wVATLD5CxZA2oG%2FrzXmAH8AMscdqohajwUJ8YS9uw0k2fUE9I3yQs8JTq9%2BaJTRLYXUD9v1D5QAovqXjjv%2FvJO8Yp7Ho7pge%2Fw3UvJYWlZuJ50IBHxAWWDzNZYRL9o6TEAkK89PY3sFW0kCpEGKvCaSwELoEUGT%2BXc5A73Fd%2FdaCpa0H%2B8bgYIVTXf4hdl%2F%2Bx429KpBV9z%2B8yBwVjoOAxrwQv%2Bvq8ERBIDhYNMV4fsh791FZxLyey%2FaqYcqeuv5BkOuF24Ymx2bBc%2BLgf6%2B1GJSNvhwuHFwumVsxqPBD%2B%2BRzvwnm35s6hwhqGawFQa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wlgoICyCiaYtSmxzx%2FKdTm8G4kB3AVAWT5xPF0sLh8TVjm%2FAKoB%2BChQ9ivEMxdNptXq1t4PsWWawHUBaA1hURihdWKrNLxosp4YKtwWHGQKSvy%2FIEQWFVbifC4fNoZNiLzYHYvhaPehUU%2FX0vJJ6sfkJJmvFkjsWwktaP%2FZWbehxy%2F2%2BbMwlAvSsbtzW5mNTqGt6r57YJesLdN7x%2FxVn%2B0CT439d8nz%2Fgi42Zd99EZiRyI%2FwS2o%2BPg0JgkbTdjeM0Ig6cqSRlvCva%2BCOrddjRY%2F5G1LWoa5EeoNWmrkBfI702RAgjLSo%2F5u9PePcGFkQf0vIU1kg3%2FeSSMoXphKnERlg3Elxf2EslAi0%2Bn0ZvEIsFfZryl0ilxgs6fmPw5w%2BmbXbLumbeEyiyaQyuOTwZzl8QYpj8mT8OuIHMZtz5eIeJeqqsutflKEO72fMKj62a%2F%2BYuK4kc6jK6gGOcuRBUmJL8zIvJ6ja%2F1E8xqG5V6tisrGir9aviav9etOuT37XBQQXa2lRo3Nfgm6niFFiFTZ%2BiOL%2FBEeNjW39rfu0XDq71LgiIQYILPF%2BDV%2B7KJBEI4ZHuLJ8uYTiIIpSxqbiTwzRPDuV1X2w9%2FUplI2%2F40J1Xhay9diUQhc99A3gp0wXJ0aYwAAicHUJgdviPWZcxVpcteh9V5eqq%2Bi%2F1f7Wrup68mGkf9Or9%2B%2Frv9a49X1YdHdojnhX3ePoprWQrqdPxA4LZPqveKR%2FqHM25G%2BXU%2BAAAA13QZoti2oFclVcQhNf%2F1zd93PXq83rl2r91avJ0rF9LB1zfXErVevVz1Ak947c6a8F4b8C%2BFgWCru7YnBuYg8Mrci7wbig%2Fy4K4hjw9x5pjsonwcgUDTAxQW2D%2FoiMUslRVpRHwbiPVD2y%2F4N4HkM4pfA0hU%2BXgY6xuHXFqV6tRddS5XYIdatjn9WEMstfXohEk5VqvVzJ6%2F%2Fgn7w7TMTd5g6rVVUVrINEJiH7v2sOhw3LUnO1uf1zO4q4U%2Bf6n57Gki0hP7j%2FgcHIGD0yp7gq4yxZ6ncKZSy5PMFI6JASg3G7o0c2GohBjXInlpiFz5Yt8nt%2FeCqBUFjZcjroOy64XDwGt6exhH7fqs%2B3UwBRcw9wU%2FPTNYLe5O0u4d4NXY3XSLIbm%2FUHfAMyHluWj4c%2Bt%2F3ygShYf8Evl1lbsmKOtRtqWiZa%2FVpO8XMPBRGzpcrbU7bLKN5V6KLXgnBGevjiT7rHDqJ9%2F%2F0h%2Fd1a9in7V5fVpLlv3WvtX%2FV9YCgBcAnIaEQZ%2FcDNgKYNZfBnX8CEYEsyIjD3n0VvpzqPHBIbiicUbMm5MLbisVm4hwe8OINy5vxeby%2FDEoMwUApBIHzTNIVh8NXJW1Apl9ndd0rA1IJNmH774Nrr8JK8g39LtQgorXIZETOwmFf77v5TnWIwb1EsE8l998%2Ffdejucauvlq%2F1qT1cu16sFVarjdcV5PvASPziAgWdgguzk0HIBbtA4gHvUBLGChYaMF9h98LSA7soGL8FwaO%2FQdEvxwsGl82h71wwu%2FBJyXV94rVXdzcy16r03en%2BiO1fJ%2BjIpDIxDR0JmmDSMNjuTeJBYx0pQBtdzjyVPHH%2BOU8WX9Ztr%2FbGYJnnhYbWeA%2BvpgYzuR5Cawi149ZXS7PG1%2Blfn0f2KXFfct2OhHLd%2FyrkyeqvN6uTTE6YzDBsBMa2MGmxvchslRgye5gHj4GaWYa8Q78nv4KCASpff1x9H2kjIUNHkNKmQeGnTB4Jl%2FHhM2PTbTHrve4PmkBqH9uXO9lFlwywLAYwRML%2BxKDceiL4mT0dzu7i2YOwgGOHHlNkA0MV0cI4ABNwBKBuIDKaAEgHtJAAEKI7YIAAqCHCQgJSmpjJ7AW7kAhsd2zIwOI%2F6bFyczepMQcmAbQ%2BlBw2C34DtgsL0Cq0CZXLA3y6%2B5Hk%2B81EKfYdacz1KqOBa3SgPu6hw466GjzUqN6%2FCC5xwWABAIATAkfggLF5rzJz5zUBsHDgUBoyoM7smKRnGdReE1JbU%2BgtaPNIDgPfL3GDnx%2BWfURh4BjpfNkvEJXN%2BIMEZ5jRlLcyYbN3J80gFcT00vsn4yeIMHYt6S%2BAGN00Q4vt4O6cEZ%2B%2F9%2BzvFPuisT3%2Br3RHOtVavJp%2Fgk81tTtoaTGhjw48cDh7hb5qM7x4aqdehFZDqctNLeyefOmo6W3f4PTNe%2FJD1IcVQ8AB%2BGQ0WwN4ceBRekxvWUppFjVN3sZ0Tcx%2BnUdz30DB6JZb3l9%2B6EHDF7mALnEHD17qvTBKa0mxJkkDQJtKtfh7BKrYOaz%2BUS6YgHX3Zqt0zgd19cevhjAX69xtOQ1WxLp8WDXoLGFNcnDOvioTH4N4xNXzWDMlkHvhjnYZtWDMRXGUWvDSKL3rgh5MGJcX5xK05%2F%2FmkXEfC8l%2Bq16dN%2FFL4HUKawP4W%2FA6hQeMu93%2BL3iih0EA%2B7u%2B7va3gXwRpmLub9pXEv%2F2CSOr5U2PwVbKZDQwugqEbx3kXhAHIQ%2BYvxvIkU1MSHhwreJRvW4%2F84gLqyKhZPDA%2F%2FCxW37mJ2%2FzkY8aa%2B4cKSXX48n1h4p8NkyWBErT8Of5k4ZbrSxshoQzAC6%2FnE%2FfOkEEaaVxi4josXWdRGeTr%2FTKmDKojwgMCcGcZN8CQKTVDYl9d3D9K5hs9%2FA4eSf4fyDUwQFMeKx8G7kIze6hgkJOWkx3925U27%2F%2BGJBg4IPg7iCmwxuNWyvfit2szEeTH0LMU8LoQ9Y%2BtTPeEqWoCEBEU278DwCIfB4sEHMXFOrT9YOEcG4UIKMV%2BY4AqymCEnDaFCu8x9hDsdHNYHpKNKKAMSPVdjt5SjzmseMK5zxCwgLUss6GMfNcA69sguP0X%2BI0OcMBWCRtckA9%2FL%2F6hMyBdqYUbB5vQfwqWnay%2Fg%2BEbBgTBbK%2BXGUhoNCTO%2FiTlM3yw1HMovgiLzdIvjyFY%2FzLw7TLWZWK1kE6rl12xjGxexP3BFMuTz%2B%2B9cOymyq6YZbbnjQG6OKc3Jts5mZL8KklE0G3YymCV0nRO98y3X%2FwzVgfpL7CIOk1iX7sEUeSab%2BI7o7lH85VWeHyQvd8vfS36t8R34CEOOI7u8X3d8ngAzQHrBAgmHCAqiDjNVvEB5eSFeU1djM5O5O8pq8ZJC4XR3JbkTBXEIcLZw41VujNwVBgpubU00y63eofmCf4VIFghoU1EYIfhiuZAdVBaIG%2Fy3WEvS7vF5PErFf3f0NKBC8lh3508f5kxbRRAbznQB9f6ghG2i3cggVCXBOai6LBj%2F4MNbwL0ZTHWOomn9fYI5V%2FXp1%2BcaUuzHjH%2FMKbjNO9bG5fik1DgcKkNSwAZqSmLkgOh4DhImr8OM%2BiG9cO8Ih9WatKT27X1S7ON9v96iy3o3jQQHp64KCcZEBfaPv1YCa%2FGZ1g%2FBP647ERLglzfgd5Rc8A%2BT3YCRlCBQhEGs%2B8O7U%2F4ovgqngHmISCGZ%2F2YdS4OkSYbuH0SZlzglKHyW60oU2VS4yfC1uTtHRbHljX57I2NivQvXgi1FOLEUv30yZLeuCbek93x%2FhMkvl50kQsN1LYbFtScG8yckNyWYy85E4w3uoICLr21JqOs%2FlwZjK%2FQGM9A%2Fhiwnssh4SH1PslE%2F7hfj8xA6N9fZAkaZ9Ef%2FBBvRXosI%2FjETslqzW3%2FJ61XFyXP5iO%2BvMJ5srbwRX48sc3dh0Um7kncwg6SDlDA4RvXXiFdP5PO%2FsJle7LJJvhEEJLb%2FsXNssV5Ndgkpy%2B7J6%2F%2FRKs6guKMxrWRms8J3%2FrD4mW0vGsDo6ugeV9HDuMJfp%2BpimqaoyCGTQCJfk%2FBZ5aBZZNjxY3Vtzh2CAiY5XwBvJiG83wA70ZBiLT9N%2B%2F5Jj93k%2BsnK8vr1vH5XEb36OZr829710c5SWQUcMBv3RPevs0NJAlvonl%2FfYosyj3e5cISiEcMzfujfd9EHt8j6G1V5CAd9fyfn9guqmOQmcQ%2Bf4UnwiaYGvRhVlAd9MqJ3AOWT6PvftfCQIMqSCtp8XimrGny7MUyPhfCbtBu8y4abqt%2Fk5f0hmA4Moj%2BlOzBqtagIdz99gwAfelK72zp9tsOzcPaHyPgYEYkmbDUMhQ%2BzG732GWXoZ%2BuZaBBW2uplJ5rMgXjc88VVpL%2FGlyUSCL28igSJJHu3Iu6TIp6YgHOkjA1xvb4xj%2F8MXggEpx%2BD%2BpJJgto%2BqL3LDbMg7WVOaCXoFAtYY93fkv2m9um%2BZ5er%2B8loQ%2F0bk%2BT6r%2FJ9%2F4S2dc8Na9J8VzMeNabrwru25lHkv0SDL7eQEkrEiDB2hbnYeMz1tCJ1iUH%2BOhKd38bufb2FCHVgRRooJqYIBJHFvSxQsgAg6CL%2BYqMzDJe%2Bg84ZHtHPk27stTC2Zf01cbEMY1VQ8ew95sKKDGLmNI%2FAoPZVsfjprDD4NmLJhl7%2BzSSELjiFt%2F8DnDSm%2FWM2rjXKTZzXM4UEetVVBY6ESn%2BWe8edr4dsKthjey%2BqQlkGBE9fUVQ2mT5oVRehyQ0LO8oqIBTlos8xqqhl4Tw8ZZa6mCk9slTZIiXVtVzl8XQNoTlQroBuQznckzy1guCBxouagnmouTGZXNgoz2J0L82e8UIy%2F8wUEIaxXyayWuVX333k9f1RmPy2tdj73u%2BnX8%2FCOm30v%2B5Jf66r2S6Pe6hzkhX85o9ZPe%2F%2FXZbRzqmS7f7BAIwJWVx4JO8vgCLEDzXola35%2FV0zFyny78vqhqRWNLvRx1ojDFNmheunRdxuQ5IvrqOEKKL9zaHiLNZBWQKTKuR58gOZP2ERBXxGbmu%2FpCTu0uJnqEaTN2%2BObAsfJR9iw%2FuOKFCFmJ4TOhZQ6sx9gg4gyyov%2FKjxW3%2FGX6MIEHMcKeakmYs4iXIPsEcfa2KVNYllhQojgus2NKkWYk4Nz%2BH%2BH8dg%2BwrjPc36QKZTL921CdEjt2%2BYfEOeprPgUeEJln62Iwhy2lUfJWQMbGe9IcOX2uaYFZd3bly9qywf5F3E3%2BTLTXo2XYISnpodhtXd%2Fmse%2Fy8vrzEdly%2F%2FXYI4%2FTXpvhSlxEBuuhcvpctxAx8pP1ydQS%2FviNDEzNqduy%2BXvRoP6Fp3u4mbJc1Wvc13%2BNr3pAkJqz7L%2FieSzfneXKI7TJIHviXkvCxaMg0IlSiBY1WHaXZV6CcFebxDhsRAKkU29csv9coUJBRsdINYr1TH3TvTnKmm6zMQ3SteE0L7luv9F1V161k8vHwpVyvYhTZ5Vw%2Fe9%2Fgkzw3NeoId1Y4w2csoyNBwRv9x9KJ%2BL23%2FswlGf1XWXxMTGQgglaGtOHiZfl8XGxVR1Hif0jWj9MsZPsuvBD6ZYsbcz12EyiCFynvNDViUcdL16SGtIKUn4Zy0T%2BorH6vfq%2Fdetfr4O%2BWrmyIPVnpqqrrEu%2F3qEbHOveFCdQASQUiEgSCg2CoUCw0CwkCwYC4VCg2CoRCgVIYVEJnidbT5%2BO%2Bfbvr3l0heXq%2FF5xzxk1STgbPzxvbsW3fNuEnc8J8L9HUa0LeeiTdua%2Fcnvu1x%2FyFNWGzf%2FHhCMaB9u2%2FRxorr6vCp7%2FHty2qlR%2BoA93wfsfkEW6UaCMV%2FfuEuoFnWeqeTuDL3v61HdZ1hr5yV3Y523t5%2BzPaQSCpqep6b8QQ%2B3o7L4CF3F3nXXkRR7%2BD1l8FeoA5ARWjwZCJjdb0KLl4oMFSATwg4ABHhSUKCIKEYKBUKCYSBYUBQLCQTBUKCUKBMKkEz3kvdd%2FHitYzW6utVXGXMx13xjURoc3bc2%2Bnk8S5P832DxVyz8Pg3LPxvRx89wY%2FGUuS8kvls8LMR8L%2FDsYpnBEHab80Cb4IvJUMa9J7Yc6zi3RsFkOPhBoIntkl7Pg0i4EYVa2P7BXuLf8lNW1dffUb11CPuPZDtnadN%2BS2p5K30pdK87xgHB2ejqzRbPPoWHHoNvFvYVm%2BNr8I42UHV4parkUV21FOztW6uclI1GzNAGe1gcBKFSQShIKCUKEYSCYiCYSBIKjQKiQKjExu9b3vidzet67u7pV1pWTXN5equpwPD6tx6e16r3PxHV685v%2B025gIyeXLX3p%2FQtP3Yh18cfrKNvyrymsMwx29pU6OPTcitA38aLSI58vQ5L%2BU%2BmMSP3mt%2F2GdYJ7gt0CEZ6iJkDnHDh5R6O7X4efvu4opHH56h2OYCy5Gf%2FCTh4JQ5d8lc9PPiFOPCCrb8dpmq6PmXwa9DQOfJRlnElQx5yFTqvGJfi5Faiu%2BbpcDgEqmf2UFihcqWKFSKc5d51zquOAAooWPzLaPsT2Jzyl3075x79Y%2Ffxm8ffWeWhNg5Fjbh6%2Bm7B%2Blqfhrhlxb%2BH29eiv%2BLNc2kvzvh%2FnK%2BnfjXwXZFPR1E%2Bo0M68e8o%2BNOx6Fm7aWzvKiy7TPkmfds5xEWR3k82%2B3qtoMLqDPfQA3cSefjaSUEAUAyoZ48kztBwmjVZo1fW61UslWVOnoW9Z1KHXOIOccBxnpGNXR3MjGOQznoUoFykQwea5564a1mIiwyjKJwNlyg4BKtSQJEQKiYJBYJhcKBYKBgLCUSBcKBMIiUJiEJhEJiEzvrcV%2BenPx6c6541SZeuN5mq1uuF1JY8bPn8MnZdx6NL6CH%2BW98X2oF%2BYv0606bWup7IQmNm%2B90ju4cvblxg9f%2Bdhzv%2FWFZa3utmOIQ0S79pSTb%2FCThmIekZ5LvYMPGop%2FWf%2Fooh6NxGbppT1FPGyz%2FkoD%2BviNI3n1eLSJ%2F%2F1RAKIKLPGoVnACNbAWqVRYwcBKlSUJCQRCQbBILBQMBYNBIKlQKhEJjUQhMQnZvpXrx%2BOfX189eOPHWpzrd689855lZnUpbQ5ujh0PqNv9438b8lE%2BB3yBdpFnfh98Rj5ijv6QAHth76F%2BXqOMH7Gou1%2FfUhf9ekeVvzuLFG%2FRU0hwJg%2BnT9djeeve9C8ED3RAkWEh65BsZkEFlY1x%2FbBg%2BG7cfyApCII1BV2iBCKBe4VN4DgASaZ%2FZUYLFypQsVIpz3rSbTroC4WVMbBafoT3jh3bwD9DWPJ%2B6bb4Xw1ztzOifaQs486DbgWaEq8qucmbMK4yURILTV1y8o2jcigQ02u3p2UdVNzydDPKMZjajHDZjMzjWypg5bM95ziY5%2FMrqJzdMp4%2ByNozvfQ8%2BA4kXA%2Fo%2FE9mFfM%2BAFAAmfJXEAGEuQahB57aggmUge%2BdCIDQutUvVsOMh8akdWg%2BwHVcC%2Fig7faF4KSapp728jG%2FNeCO%2BIF4nQBG5gAcAAAEpxBmi4LigV%2FoTFYzxyS167Wvi17%2F%2F9e%2FUqvr3UqVhD%2Bvdr2T8%2F9P%2FrG%2Bl79XPb%2F%2F%2BT5OX9e%2Fr1arXrvtWk4QXuiO17rV30rcAkROnDAUNiGjzwPowYKd3u76tXEtIUBXgVSAwvA%2F%2FFH8kjDz8U7QBBCB0MBwZx7hHZBw3kqJd%2FhsSlJ3eEtQVN8DBG3vAqSGbfTR%2Fe69hJebtt9F9e%2FXv1GIOBHXrte%2BT4jte%2FVvpE79cpLWv174mS6u9BExeBcxrJ%2BQ7BCGgP4QIGBiqpylQY3jSSTSMyurtfMzJmw2Wom2TualRi9PP5k1H8jZbSD9jrD%2BxFC4ZRguDMH2ih6MFANwe0oA6jAGkUbwRjFQ3LvNHx2IEhofoU4wwYafdvWRK%2F8d6sCKJArIbqcgndHe0rv8lAfEvyxaFfgZGWEonJL%2FI7emTP8ss2S%2BBXHhUJkyh3w491kzbiKlV%2BYyfO%2FFgnGlx0QteY%3D&media_id=1254206535166763008&segment_index=28" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:32:09 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:32:09 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_6yJjrf6tPGkf62VuuY8UMw==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:09 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786112935178444; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:09 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "8a084e0cb820099c7e1f171e46b386ec", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19924", - "x-rate-limit-reset": "1587864356", - "x-response-time": "31", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "00a259d5001cf6c8", - "x-tsa-request-body-time": "69", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"Awx5TUISBHXs2Rzo8%2BLwlPE6y8s%3D\"", - "Expect": null - }, - "body": "command=APPEND&media_data=xQY3SfrmjLhJXU1RVh%2Bit8NKUrjZzgnBB5qAt%2FjBNJ99PAbvaeZe7eY5dRT%2FwmCMMUCnk8kxeq4O82f7Qvu16tV6S199TXE7rX6pQWAugTCiY4h8Q9XbxTHEficeLfzUtu%2FL4dh6d9uo7RIDh44W98rLHbnumzo27wJYUG7xW56nc1FbltwvUEzMFdQHYVSGUfg7oYk9wXMMqeQlJKDqYg2xaBPArHCA014rbMxbOW0%2Bqh6fvzAe5b%2Fv8QRfDw%2FohBSdaAM6A5mXUmKlnHWmh16eDswxmP%2FoFha%2BBgbgctWwvllRUvGNSB65fBug8UVno9u7ivfU7EKaaZaw%2BxDcfcYXtggJWq1WtTCKzE2KlGkQsRL9N3ySeheUlq6X1cr1i%2FVpN%2B1i%2FV8n1%2F%2FR%2BxbLn91gKUMnJFgg1s6a%2F%2FrOHiARWId3fwagptwcS4dAMbCrV%2FE%2Bd67PAoag4CZDX5%2B%2B7nVNdEy2uXqrfr0l1uvS3k%2Fv6Xu%2FA2hfxBgoOgC9s8C88xyE5k1j0ZqKU4LYWfCAx%2BdwP0esKb1NAa%2BgQZeMWbrAU5FreOjkDlFhTQYseKkO7dYRONzKZ18dtaPXJME9lK41JeQk4TX%2BnO69DYsV16s%2B167XruvV8d%2B%2B1eT1y%2FXCrmr3gWQniycAtvjRq%2BXyJCBmsycaSOSXg5JcsBnvPAee8bHuASxYC%2BqrShe4pnfR3Swmr%2BkqsXxrKrCNt0f0Lfxle%2FXVb3qsV869df6sr1a%2BavWv1r9ak855c2NfxDBAK3DL%2FgY5UD1wSAC4zOFUwAKqXQADD0FSLQEJE82kGCxjX9YsQWN5QFPCqKpNgFPmLCUNc1trqgcG4uLDzZw%2BCW0Y8O%2BjCptB20lVZYpXeP%2BN%2FPNNzuIcbfZZSTwNC6EwkrZbrYTBtDsO4WYH8flnIf42D%2BopsIQBTmYkcM9%2FrGUOTNZ8eX%2Be7TWMeIIjgMamATAlcagP71IlY9RubzqV7Qatci3WBH6Me1AYZype%2BxBvfEdtWtIwtwVRdgnQ6vxYbjT%2FvLlD9gHRAKocSZ0b6xIhByrcq3QKlkISFbaIeBbdRvdDT%2F5wijFEHahIZWbW45fy%2F90Kf9Er5fl7unibv1a4T9zeNdyMOE3OJLaSARPWcN1xp5sU%2FC8N%2BJwPi8vspZCtG6WQFVaL8bBjM3CHGTFuufcv5X42eGWaVUv%2BKNxXyQEWKjfRqT%2F%2BHrDmTFlH87DURUsajGYqsZUjOrBrta9P40qgtF7ReG%2Bp6kBlaPPfTsUaSx2O2WzKZWRnzGjb3CtAn%2BVzX8Mx0LQLv4ciBv3DxBnkLWewmNkgK8nhtKxJKzX2R0h0B7cDDGp%2BX9vUb3IO9M5HvfuMsIK4KGroUzrWqhrv0h6d%2F1GywTdC5DH5fw11DKWP4CGV3LGjQG2T4MjIo25%2BaSTBoHF%2FyQ1z0ishHmFRg9%2FfRkEY6yI%2B34JhE%2Bs4kXLNJHyIE1ay4iEWdBmnAeVffovT3Xqy8DCO8D%2BI3jIGsVrASoqQWKXfd6wFfwwfNaTuoCG4Xt1LxhBwkc2oESMFvAu11h1Cnub%2BvIwYTDTJkgw0i4r%2Bhi%2FkapNwF%2Fpfy%2F%2BGocT%2FjwvIRP2Bd7annIbG4z6dFZf%2BFt%2BgJw1hxB9zK8PfGcZEW%2BP%2FGMhq4c0zjJGrGT4dKIfd337tkWGDivrvR0MUppSfP7nufTRT0rdQveQR0LH2GDe0ETdtoAVtNIJ%2FryKGDtc9EuX1Gwf0fV0lxCM2qAh9P1WpH4IXoe%2F3WGQS%2FDxIeMbEUieGE64o81YW036I6VQVEOtZAtzAgR16G7E8%2Fz9zH8dNU4VWZBiH7ZQFEK3pC68JPuj4RtuhhTpFIOtffuFSz3lIhhrzrUea%2F1h66A%2FoUagXKRDzFvu6%2Fl2OYv0grGWtQttHTgd05aIetaGiXWwjZvbR9%2F%2Fo8XujS4H4le%2BXfFf6s917vy%2B5n%2BCQ%2FEOWPnBRpA8eDweUgcgeDhC5Y14EIFRhk2JH%2FwJgeHESS0kr1kysGBAVArGxe8VigNwB3fG7uIADgG4sCZA1hE94QExGOaZRk1bZRV0fB8EQrPAAEAngXkzAAOYaoPnc%2BSAPLIuCuHSQHdgvtjn4h3%2F8KjXvGhLMXCjQq2HzLjmsOT9%2B8EGAMJWB%2Bp2ZqPbZRhAf8dQsCypRA1c%2F7U2LKsBHuH%2F57d67vDpM5CwmlswwSgxwNLQWwlLvRonoy8a457MEFLrGxW4%2BYezJ1nHTjVXDzh5wsAywDXDqnn%2BT696IWf9Ph%2BnROPr0sPKY56JuTT6ciD%2F0HbVIYzTYKbdu9fodl74b1v%2Fz2jJHF%2Fl9RN8QQNVwYu50x9mFjR3MXk43B8eUthE9c2iNxEQ3tJkPrRm9ToSL5nqmhX1h6PdATn5ElnqtrrythA23QNPXixw11KgZHfhFrHp%2BotQ7GXLgRZ5SIFGU5z4jVtZUVLbvDpxEEpMe7B7I579rykOeRe%2FeIvmoj4uIfgMgIAk7vXgfDsQ%2B71gfAW0IyYK7k7j94ORw8EgwlX1e7TYvF3C5WtxgJRpxjMizE5LBr5Han9PBG%2FvZ7HhMseEDd4l54AAgHd4BbEc0gWgj4ffNp8Bgb5mC31mkQfTSDbXVPJ6Re28P1oFWhhu7A1ci6vtSRqEGJR2sGKBD6RQExF1eCAoKMZlpZI0%2Bik4f%2F3OS6Bo0XEtCGMEAx0FltMubbWm2z1BrdPlT8fRVfky9GHU7vp6ILcd%2F9hMU7X2xpkt17heDywsNkkIHlgwoyFgMVtWntis9VUP7h4VxJDblKK3deGSmjHKtVLdsPNJt%2F69tJfL8VUs4ICuWnwBm6209RjPnOXa9%2F5tIQ%2B%2BaDhN3X4z8ELQ5%2Bl0it2z3fIjw0GhR2%2F5nC9np%2Fsfax7ERMERMpfwFu%2F1nfrBmLwSw%2BD13NxQzc8DzNvApmBqHBBBIPrLG87go65PUBDgQvwrLEA8C%2FPJgD1vlXQH5DQwIhlnSA0ZlrPsBW%2BK4uwGVKOGDj4kKeg0UO5mQO%2FaSeIwa7bOaU8NfP8n4%2BoJEG4ZgGGO4aOGKpZfh9Kl5f%2FRyKvEhpb91Q5uEBCXw4uXvZX3tYV8O%2BaXdYhM%2F7EUn7d36SL3erkBDxWONWauw4S48mIlsoHX3JIVsI7ECdp2t5P3SKkgqTuRFuJoDEUD3sEHV2hsd7wgfuaz4v4en1%2Fh2uRpSC%2FKe%2BzrHAQ1w%2F%2BpvBhRJqo8GAwDV5hP6jVcnDn0dIVpfXXWcZzhv0VzS3f8PLqNfRf%2F%2FpeluTL9%2FdEyrBMEUdxWi4IsoXbJz2GT9vWw%2BZhl0mggNxXOEpS8LCXJwp1bpgl803f222Hy42IjSLqIWMKjyTAr5MB%2BUc7BokpjzTn40NzxAUKa2KfmwQNpL1g6aQb8MRNmuEOJV%2Ft0xe6WoQ%2F50WzMTc8IXcLiOPsis5WWA5k6eMDJ9Pnt%2FD8lbE2ff8UMgzahZF6FpOsKiXnjiKQuHcdjSIOlZ%2FqBHu%2FLJ497h47scoYcG36JowTe9qADiaKZqMEAWNf8hj%2FsVAjUhJ4WGffkUWEG3lL7uThimY4M2K4gcB3znR692dWhMaRDtTjVW3d%2F403Gkf2acLrqYZvTfQSm5EGR3b6d3GXtGitrzlMGfpbKMomaTeSmT1z8QguU5d3wAi%2B7793319oWCDXp8niQnuHZmG7DCdhmTrknziRiVgg6l8Kah7ITS7vQqecq%2FlxGrXpNPXkWsJX9QSFi%2B%2BvXzcn3VbnNKrRHhhxzT%2Fruont5T4c5wuPA5K0QHDMlf%2FIWDobUv%2FthrB%2BGAzBl8bv0Nr%2Fr8FsbyXg9%2Bf9vwzeisrnwJt6304X6%2FBFd84%2BX%2B%2BgkRtNzggHkbTeHZUKCUZd793X6BYfkN2GIxkImsD1L7y13SJLCbRvk1U0epawK5PqyOioLkE0N6MuqBMbBG0YaD4ISwBRMT1ghJ1cocgrTwljK%2Fn2XPYJGBNP9fCAIOYhhCCRLJgGK%2FsRYXucvgR6Ry8jqwexX9jrNE69NfIa%2FGbfHftSS%2BiDCSKNifTW2XzKSk%2FS6HsHlcZwQQzRI%2Bmj%2FPW2DkuVmxSYxqFMnaY75Z%2BIwWJqE6oh8oGVP%2BJY%2Fgs9VXh8BspkdTg%2FTmpkHmE5uVtSr6VtzD%2FDWJvNGg7SYqJs9%2BgGV3MfyAg1pJlaBes54mStcbmtFfjvijX9bNe2TeNhsenKF6IWmS5O3mnE24Y7%2FNXyyejdXr1F%2F%2FVtah%2BCLpJdRf93qfZyh6ZIDWGeUxlhyEBbQy8Bkk05SSsYz0bHymcdU6%2BBOPm8w4J94%2F2WTxV%2Bg7V0KcEB6AirVbzXD5GM2KCoSjPk1TLMakDW4KwrNFArraf0F80efNzDBHn0weTjvIWn26kdUGmDiNucfWGyA1tPrj5rWpkfV%2FPX4cRPqduvOSBhvc7yESHKa%2FlHIwiW9hvPyyXZqaibUcHzTD%2F09gkLuAb7ePa6sPzsxU2T%2Fd3eDHLn%2F2GiFDUrHDiV6vf%2BT%2BXy9qlCIeOfGMZJ%2FifwI%2Fp4pc96%2BCFvm34%2BvljXGpjSI3VMUYw45Y6uW0YtdGCcoGgNO3ddqLhPQg2sTEV%2Bz9Oh%2FriaGkStTugANJnNRyoc4O1KgesfSRUzyCbI3oAqEHz%2FqX87gX33uFuzRD2D7%2Fe3OMIWxXpjsCSfjiHxyYFq2jkHDsVUSaZivy9DC2z4bBPGy28QI2yTntbWmgVi1dpS%2BQyERGFCkSdxDkdd8F8p0YoIkg45idBPGN6dDeTlsAVOdqjhsTB6gjWfuwJwOqC62uWQUwnVvfj5iiORFSq%2F3uPIH%2BGcswZmXi5sx2gzs4tL5PeMwjA6hkWRdXdVvCpDjN9EMYuIcEOS%2F6Edbcvo%2FVuvb%2F5d%2FsRlMWcn0%2FogXnCAaOG5cTCDv7g4QYu4qxtf%2FhjGY5YkCGddB9dRAfcqSeoMr84WKAJH6oOHF%2FsZMhJ0h8Rt6823YjeQg4hBc4boyCBS%2B%2FcJSG03%2BwfaNui32l7iJhhz5RXeT7e%2FJEIQB9%2FfL5fvk%2BxHPL9oMFu992Prkp6YJSJVmI%2B7ufhctg43Exby378dkKQx%2FCIpbQHWfLIBWttHvAX4QM772vCoxqQyYdzpfOU1cKlNxb%2FWm4vbjCx4EA5tUW3tb5zp8d79caePjVcTjwT%2Bo0g2qld7%2BwrDt0JgalUgldIsh7wP9brNFMF3Mp1aXc%2F%2FDIkQaKe4IaYrSrJLCHLk%2BHzLQuVl%2FaJw%2BVImYP8lqPipPhKxtEadCjSLC%2FFzcG2t88fB3wQ0xtW41l2vpa4jEc%2BDfttC5ziBc%2BPCia2pCBsn0foov7%2BStbkaEGf6EGxjyLk1OnUL3dnVar6kY1ZI%2Bnw%2BcoYCyvi4uf5Vp%2BjSYX%2Bzo19F8XkRn8Dd7%2FCXit252fghve4rWhu693J5OtVr%2BggQtKxdeoERIeSnLknZPO6vFXyi0PdR%2Frl5YiGRnYFj42NGb6l%2B6LAxevvE8fwVX0zDWU780u7XgjKrneX8rE8EEGv4Md2DV%2FhMniwo%2BgPZNHr6nfSrNLCkKsrhV52H2GGopMXB%2F00f0anBoGsTBhzXA2S%2BISlPM2%2BA1Qc2tfi%2BBIIOTuXUvqLCLBYWI3400Kmq2z98ooh%2BjsE%2FzUfrohApNhtSP9%2Fnet0tn99bFFhAqxc2tkhV3Ip1PXJY0iQsRLT8zu7YqsVQ7plP4lUf2hL3qtSk%2B%2F%2BS0WK%2FECGsmXr3Eaamxtr1%2Fv3FdJsvg%2BrJDN3uo4v%2FfovVPUbqLxBXvnx9NFyWK4cek%2FcVNUEWJ00Xqm1DvnzPEYzx2S1PqTTXye5Y8eMhKCXxA3klV%2BfWo8pCEz5fkoIj40EpRXd7ZvX3cnoWxLzU40hO%2F1Si7rdE7nVKfV4qvfOr1hz3XLT3N%2FECgdeeX%2BKRzZSJdpYmPJGPLswyI2cKPeAAAT1EGaLouqBXEXLd2hfVzVas7Vj9WLvv9WK5P%2Bj1YbVv%2F%2Ferq5Lkur7vA%2FhHwMIg4hf4vJ%2BYksHgUBANJulq0WkQN2ZI5CGl4aZxy0fWdfyffg4LIGKRcz0xXDXIUpnDBx9HA1%2FH8XJP1IaKbHfOwlyp%2FsSnV69Xwkpcr%2B1Uv66r1yu%2B%2FiF74iS7wfBQOGacMAqj3mT%2FB%2FdemDDuXB0jDYXMoFKUpnYIwHEDpDlonHYaR8gMEpbbX%2FXPHhUEg3dMQCwKMUZ4jIcHT4lCUOePg%2Fl9ETwdnHo1%2FhKrtdKbKbZCo1B2NohzFxrSEQJICWBOHjPt%2BH8HbJEX3OXwLxaAwB2lbmKq0Mv0J5a9IH32FXOtlDIkb4LXzbEuN7fjhdgqqW4DAXnvk%2F29ibQPOiOnHMm7k%2BN8OsYEYsEHgHv6XAa%2FjXnypbn1iSGF8fX5gmLhCd%2B%2Bezvvn1g35cLB8P9VVEr7WIZAQLP%2FPY59aw5kYa4EQMBspcp12OxchS8Sx4jHv9Ca%2FWK1f7qyvX3a%2Bv1yqqQYt9f3o369UEKK2tcLjjnMUcUf1px1f7YJcFlK3912PlD0SODvj9WqqqUrM24npjMWFn7TPBGQbqqi8i6qtw1pg1tUePJzg2pbN4GPUP28cLFkBYQtlsUYo1rQiny89YvgYzR463rWg0VfpYGAGoEhReEofYCwCl2OA%2FOuAqFZscccKRWfijLexDhbFYrPj8LGKMtisaxn5wUlknLn9agoo%2BgsYrFGJfphvbJDPSqNQXSoqU9TQOwHeZVsCVSFaKx%2BspOTFfQlinv1f9ZXd0ysW%2Bqr1y7V3An6Af%2FCCpva%2F6eKPhAYtYKNEv45Tk%2FuFP%2BHkP1l%2BCT85hQxewKy8GGuBZdg815Pz%2Fuu90V%2FH1ir1imXEd2uVWuX6kSTS756p1bL6YxIgQhQY0BL6%2FWZooK1KGSyjWCnZ%2BR4wN7Ut9JbMOQGRuJwAEZunQdx5yDMIRn%2F27BiFV6b%2Bsl%2FztKTscF39uiZa0nmZGVyZnS%2FLHtSm7lrQ11eryWr9LXrXa1iiaq7iXmYaYY8Cu6WCY7uYrfmf0GBjVF%2F10Ck0HUxA4ypfdGnOoQfLL6%2B4qdfmFINVE%2B%2B8nn6%2F6PFXEq%2FffayrDFa4RrN7q1ir1v3d9yvIzMMdmpZXcuRhlVhyfX%2B4eJjWRfMGxdmEugi5lDA9%2Fz5rqJNoEvUaUsCl9QE35VvRzZAbpyLW%2FQOmKx1oOSD%2BJRPIOUaRkmNi%2F1q0H4Pec75fTQEAdCJBM3x%2BO31W%2Fw0K44Y5WRpNf0vxuX3LEHSo%2FrKFzjPp3gAeMiPYSVOTYLsrL7IFvzX1GwOpsgd04ShkygwPv%2BImjjBGJkwn42M7fb%2FNEeMH0%2BbNSKZ1hl7Lqq1f5FrtalvxH%2F1VpK1au1avV%2FparLNs4bnyl%2BEzFNcEF7xssMC6BnMWCQNYkiHvP%2F0GIS6Aa8lOO30j1%2Blj6tRS%2BYv4fvHR1OEBeMMAdTv6nxZ146lZ%2BUVErc3ZjZRu0gRssb54D%2B8%2BTMuNxpxWOoeuJGF3n1dz2reIBdcVsTlOvCnTrvdsbR8acXIcn2Eo029pVZO4679Ovdz%2FwJiEQStXkYILzCYZ3rnQdqEXt%2BGWaR9L4V6Da8s%2Fxzkh%2BS%2FHO8YvNv%2BrhpvF2Rq%2F%2B4KiCsd1TtlNJ58yN%2BO89BWHue8dIaL7Q3bZv2sgvz1eA3l61ak8%2Fx%2FQNKlmPsIEnxoP5fOnNMgUQNaljRppbopGaP6bebQILBmLgiK7iyyZbDA1c8MYarGZaPm0I9BD8PIJjrLssUWjOv8%2BjCLCPTqeL9F79e%2FXqwO5kXLeCCBPZhS78CWTwJphYjd%2BHFfxBRo3EOPNp0L0QC%2BYGwbcMb65CjQIeBfnEFWlwl3pvDcZInxsdLdfG%2BwaW6MC2h4FZQXg09Q9%2FuetBHVC6UTahtn3p4BRVx38sx4hpb54gPw9WjBoE6IlewL3BD2sRJPr%2BQlfauIywLNqAReEOv9Ff73%2BCnIQReTw7JxDPH9DsOjdi4Engli3fnlH%2FJ4EdXQ3wDcIPHvg4%2BnBtPpAbCZZUb1BRQTzTuF5HYs3EU4vLS6jh3Qi3x4y9yg0OsnttS%2B%2FeDCid76af%2BnW309WfsKl3d86Z727TyPZRS%2FTfQ3jMd28IfNPdwk4z8gPeq5kwZXtNCoQHDGHqdKI9a8sjRBBIuGhPN%2Bvw8R5INs1AjFVGdUx4ht7QOHkdIlNdepb0E3Lf%2FBD0jUcfBRSUimVqn2%2FLDHEnEDw4MtTf%2BHKV5f38RapvYMDvPLAfcRNhpWCVxcsIt3qRBWaea%2FzM0zNZWXDNE7MtLD9yTNfr1XfNa8CQGARld3afXMDNgou4oxR3Zjdr6%2BcUMy4XK14MAgWq2dYIDAoDY0pMEcEOFsXUuYg4Q8RRIB8D4CcDHvAO7vrfULUP2w2ndj5F8vgUB99B2B1ABqRiMAW5wx6m3MQSgB8BcDOjqqoP7M569KDBsxfBX3BsUbLhzyHgQKUI1mFnsk%2BGhZwxDEOwRsbecHtdlAxukytVuVLTX%2BCAmgQRnHIIDOQ46GVaFleqd%2B7TRIof5PvXobVtmZ61WiAlECQ0vLShJIaYHbjr8w%2BHY1LVgHN3eRqRkNZb09L5LwyOGfxnYuS4HrJ7rtOFYTd%2Fazj3VxkU0coKFFTLyjgLMeG3cjSt3P%2Bg%2FOw07c%2FY9UxPJBqZxERARvUOr6Px6w1CJ11QJO73Hw9%2FVcO%2BmZYIoHG0CiyieYl9Xw5TP8SGchBsB6M4ap1cXzX4d5OH3%2BCqMiSGU1PHbs7KLd8vx5C%2BNdB48sD%2FqThaji2v8K0sXCFRmXFDbYP7pal2n%2BX8iVoEt3h6faeGSEdfQVpJMIJjrqNEUsH9N8pkMLrI%2FhyI5Si%2BvGxsf8d8d3frU%2BqvS8CAEPBYyCJf1hqVkqvyiEIi1pmDo0aCqyIwPm7%2Fn0lIkI3bK5mpPECwIiTUGK4JxyIALdLspfSBDcP3pPcsKuOsop1zIktPKszHSorkbifQdguu3yyf77%2BBp3YN5qBPYDeB9DjT%2FYOBMwdZFQ2Z06DN0WjnDROR1qh9fDkhwMSbIfYiSOvStM4Q2S%2F%2F5f%2FoLYQd%2FP6BEh2oglAxNKNDUPNUEA%2F2pqGhevBAkB6%2F7EgSjRLyKFzO%2B4ceDYla77IUUYRPAFNfPfrLhVQ%2FgghcA1FgZohJFgGjn0U%2B6Y5RwcJBq2KGSXfdZInYouhJ1VYQMsQf3e%2B%2B9T4JT3GSwvzGWjcbPXGSI018n766pVeuG%2BXA0uNiQ%2Fi2PG%2BuiR5T53afuWMv5fhwzClIJc3H46lDPYdw3LltM3wQtsP7zPu%2F9f0uieeI570JrA80JrL4EsOncN%2BsGJTCASiHSyYI5F%2B1gveCq90ZMXbTLt4Mv%2B1h68ABwoSMHcmx%2FY%2BDgLRpYDwKBLwJUXcsiIJlXoFwz4PiRdg1SE9%2Bq8XA%2FDtAn43oQOsNNtZ06V4rQe%2BgJp3tdTXiJbbYFrGaXurjeb1mR5P3g0nwt7uQI4D7hLDAn3wT%2BWKf7OQooa2y%2Fggj4masX9xgSBryeLopPGu3POXoYeE%2Bn%2Bu8NSu9tItkoPsIbiteGd6CyJqmf5yCI1b%2BLH25bFfca2HyvapbivsbzU1D08%2FNhzKuyYqSfom6wdvOzIFWkMeSZ0Wy2vkYSvf2otwYEDuW9jKs5FN6vuhDVwdbywYoxcqc5TCS0R8n74gih0mu4Yki%2FSCR85vow%2FvjNhu6jpQf2g9Ju9ER8MRDVvXKlGJf5fbtJwXwQLTFLpM3aIpQPVETa3X%2Fek2GNlcBd9mAEI7YxwA4nk7mCIaip7DUthxFO%2By3cXl%2BStWjbRa1q4aJYM9w%2F1G1iH%2BvOX%2Fy%2FXTYfI4ObQuw2x4yvDO589dxOAgjxeYr%2BX3KXwYFw5bxyBAEfNjdAl6BphhO7Wi4FilGQ1J4pRmUNThfHOXB2bLsf%2FyBuQNwPoQ14fDC294fS0f3NGgesGfse5x0SyI77EsaZpTfzwPQXocrGRLRZOmna7JYxASfGnnTyoGT4W4Qd1PMy2pKksMEtd6ycFDPVH9G%2F8YFzITRF979aVGaE%2FpMSLCola2ydJEWVhh2SQwmxP8yPvL77sPHvMEBwhtncDD4hfEB7d2ctF1oMJHcN97uCDwB7dTbzJnt9APBhEyQ4CleXD6leeTu6TSoDox3N60v%2FnYLzIPCRw5vapAjMqviZflO6vhoqCG7n45eheg8WSOOMnj%2FgDLvtTr1r7Yia60kw7g%2BKXGgaD6Rib%2FR%2F075%2BdDzYU9EGF7lafZOmyrLlz7uRZKkqrpUka8vE9u7XvaZYe7uAd%2Fg6tpgLG%2BNJKaIVgWqS2b7hqtESqV3C5MAiN6fv0EDkw9tuVQS2iHOGA3Gh40EbvCMmD9HBf4akdp7Dl71YGDDFx%2F9pBCh7AIV5PKKEwPSEw7wgL0LJD%2B905DEkvhmzMr3fSm2F8HwfmDblkVDWA%2F5d%2F7DpQUz0%2BPPjHS5Njh%2FL3t2sigX39MpjsMwRvnUZX7fDPcMBOUqWHb63l7dudq7%2BBv6DhDoHoffeeGX2LWsbn9pQriWPjglEBg%2BSFCHo2lYJA4En5Bd%2Fueqa%2BT8CLeY9f8hONgsb%2Bht33GOiK9MSQAZg4NSMc9QV6IdaKDv0qJEY7KBgiWzb32sWMgRS%2Be8lXYINb6YaIpJty%2FHSRFDZs3xMpS5%2BY79NgTaegqFqcO4SiMtzGXAviGCUbdq%2F89vrOS6Jl6VLABTO8kJm5jirIivTMhsKmdfLdUQKs5OBv%2FkIOLFWBukYAbhMRe2wCae713fandtZB8124lVdsX4VnBxcD%2BQyhlbQ%2FpUoIR%2BM6S%2BlaETB62IAhmmKOHZYtx3F%2BCV0yCR9L0cNrjPDKdOv8n2pidDaNBjMok5rtY2bFogz97pQ464w%2B7VNS9735YU4%2F69lD82YE4V3Cd4%2FhvkB1RAr2oUyxb2L4qLlq1IMwV8qT73RMNjXuREf%2B32tVX3mvDovieEs4lI%2FdWWT9%2Fie%2BdDuqdc3d5X5fmSte%2B5Zsn61rggwHYMPwpYecK9CiWEFwjqEzFlGkE%3D&media_id=1254206535166763008&segment_index=29" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:32:09 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:32:09 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_PtVWwHTE+lfKzZp3DJ0Z4Q==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:09 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786112995588563; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:09 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "d7f2dd35bb4cdbae597b6b9c4dc57a50", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19923", - "x-rate-limit-reset": "1587864356", - "x-response-time": "37", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "00e808e000994db7", - "x-tsa-request-body-time": "96", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"%2FQDy1TCHkJBdRxIGkbwPuwY7dsQ%3D\"", - "Expect": null - }, - "body": "command=APPEND&media_data=NWKm8KEqE%2BgNKmoVodUnvsnQfzoHAqg6ENtgwkWT5UcSA4pTjlgE1SZOT5GRyL0Srl%2BW3sEECM96OvJOp6PhUYM3jJhmRYOyjJQ6iHen9GrTs5x98kJIzvuCmTLLUjoxPlkQR993f4nVpHhe1ve6YmSjBrsFrE%2BtCA%2BTxvtoOchIIvCZvBGTmpFenq4QtB5kHw9qv8O9m92oz2da6e4Nrdu12YlbX8f0Mlccj7Gz%2FYXvd3eihpxhVOnTqVPU2DPwthpIjHtoSCNjv%2BEV7gr%2FC5A87GxmMJnjuUPd7Kjiyou%2F4o%2BuXdl1WOjDVrmsX8ownvx%2Fowp2yg2I7ouWkNbStM7uhS%2FddjSC9D7vVGK%2FMwjds2Li49J6JBGffLyQkQlX%2BS%2F7tVhLL%2BtXv9HVdSAoH%2BtGRBssxPC6K6tVXnmAuQ7pH2gaLGMooCKuSviAPa2q43OxYWzvWUc2EKUi5scHGZKI2W3Ssw1H4W71RgoVhg1Ny2jM6S7b%2BXl4A%2BdmQdjVpHEMLll%2FSmwU%2FIQ9uoAZEjGbPHESRudZS5bJhZVFEd7oJnC3gVlQtgcgTDaOc4llmzPj8ey2K%2BD5t2%2FiyCHEj4W8UYo6Z8vEOFziEivWTXorX91e9Kdd%2FQJzMCjonPD6IOAmFOn5%2BWX9lbUvLzGT3L0sLFIfwJzd2xyiI5c8ydJwMdxDCd76cYmg7xBFGamh7DGXIdGvKeTpRwgffPDgKdvsvveUaOo%2F78qmJovJ6b38oIbK%2FxbawRQl%2BHzD6V6%2FXuCIrhZLr9WfLjQYS3WsZbROQY7nxh77Mjl%2F9oK6FFzV492bUP56%2F7Y0QV8XeECi3%2FwRRcL6ZjRHeQZ1Rmn0Lqv%2FDPFhR1vgljdnoNZzrP7wTWb2ar5ejgl1npOeeFulPHDmnH4fEhWIflerkzGvMMmAdByPFzUq5HUd6P%2FxrBUQb2N1vuHjmFgdB48z5xaxfBXuDzxuB2NTwc4WAdCQH2tW%2FikMKfD3MVljUcngP8GM%2BHE8SHFSgD9kqraYwI7bT8%2FQXzY1WZOPkj9atX1lSY4o9Y%2FibCTivvkMgyTNSuxDnvy16O3vWJ%2BxC9JYIvCBGDp6bxZP5kk1EG8GaU1uo1yffpUCC7M1LE8CvTirTp2ZMSB940YPNwzqrKTGnHZOvbsZUVzaFJCNap1Jku9V3966DqGC9E3ZPDvcK33Kw3eJmjRQypJyz4NS8njvcgW1rpFSJB%2B5aTJ0N5L2y%2BX%2F2z19TyRdfRYrvo7BERbJSnOwT5fHLvl5U9QQdyDBDFM%2Fd3UkKo%2F77y9wM%2FSo%2F8fwl1zLn09uEnCPXX%2FgskskG6YpjMa6ncNO8IgGVOx%2B4rRSw%2F1FO9pVXd0qpJJJ%2FWngowFa6iulBkKtQB2jES538XhCr71spONvqtVHHffsGLfrjbReWQSMMWxXn2Ii77vu9ZCyj5MF3B244tWkbX4vXVDCz4FeDvxc2Dv43LEQ43FqljrM0xsP1hNvUd27yZqOcX4qbiQ68GMY3frVL6L67Wpf%2FXvJrLrJBLB6wQcxJoJ5R97iCOyuIhHJjOT7%2FwnczmsmDEr31gj5s2En10%2Bevn1m2Ql3Xt3QaLL86Wx0bHKwxPycuKo5bfQuSTSiA9Yn7ySwXCuM2G1hp79rclkSj79P0zUiZy%2BvKQq9r%2F9C2r1b%2BvXKRIj86v5%2Ft91OrSeIkzy0%2Fq9euuMv0Rqu74v1%2FIIlz5fljySZkwR%2BkC1qW%2BAAABFFQZovC8oFcgjv0Jbun%2FLxXwn8Idqy5rrr16ul77VpfV%2B%2F0VIvr4vmiarFLfL4CnBDk9wMECTsESDA7gbR8FB0Fly3clw4%2BvGFl%2B8EkEEb1ORee46d4fZCUvKeKwrZBJI91QU%2BIm1Xgsu%2BrggbQnJVtFrFLY7sPqyp1evVuif16oM%2B1aru1Yl9XKl9r8ODeCvTMphAUbBH%2F8Gg4aFOOZ7Yw3ii71HZOOT%2BHFibns0hpBzaPIfeoDIBMN8seF6iQdr%2FPvH1ElEM3KLB2J4MxNFm2kupTwMggbifFFqLCEIA4FQACCltxu%2Bj%2B4CUVc%2FP%2BFcwm4S6BWGkJeORpuBsBTXWCIqKNIWG6gJ1eP1hrJR2hVmpiXDBB9Furm4G20iNWMtI3Z%2Bm6HU3WiBFjfNEGNifJ8Bj%2BpYj%2Bqj0SxP0nbK6iWzbJEPy3Wpd7bevg8FjYl8HfpYA9JbsSTuXw8BklgBAcQeUEimXEjA2r1%2FQMOq6gUeSSrHkh%2FyLD3%2BCoeGJjFSry5xAqJwvF9trn06XjJ%2BBCSH%2Fd30tsctL1d1uqRr0Rh37q%2F1YkubBQIIJuYlXrsUg6OLHlg8Jbw4NXlf%2BfE9ZOfRDvcKwH%2Bc1%2Bs7%2Bez21lcT0ciUrdGZczvj%2F9Buva%2F7gc2Bnk03JShpTbasyIQDLfHFkDxFqtVFxMisZIeAKLOU8thrPTRjG8IFCqClvLBl2KDLGWMUYo2DxsPAvZYxRvEdB9Zh0Qx9eqnZrk5m6TnydqFD7BIWLpgkAZbAvBvcNsC4bOAjhNMJnaLVHnSEdLlJmBSG%2Fmug%2F0y1dQ0YkMOLZQ4FTSbZ%2FW%2BJQJtyy%2BX988Ev7Zm9%2Fh4JfXOlnyhnhlppF6IQd6xNiSsKNNVd%2FFovVi3frF3%2FdxNrVzPq%2BsKVrwixQy3B283m95GxIIdwb8XLb%2B%2BXBKLj%2FuO%2BPzlruFgqStVWq%2BfT5%2BIPJyAzVz4Lu%2Fz75fCLR%2Bu%2B8Uvxav0QvctWryXVU9VYbF7yGxgqAOtU0Z4LKTIxcFfem8aWcmtbx4CjI0K682g2TMd%2B37YDQTvpfE0yXHmhLhtfgLu7cH52Mx1hl91X6CLva7XuvtXPhPqX%2FXX8E%2BTz%2F4j1q%2FWCtPTRUCjmwbm99lJPp18%2FysExJ9iJsAt6oJxqbjb86fgop4GOqTVaMTyu%2B69Fa770yfsX%2Brnaue%2FqrqHLyZbq5rpe4Y7tqMKRFEWc0mBjB%2F8v09YRJaJnM2MqQS05j7jCuypBYdoGjTbSxxod8Pi76PulYMJbgNL%2F9goN2FH2VnkPePvJEIKFjyCfUDtoqizE2BzJJV7aQWSL1Moe6QjW0JYQhsy22O5YboJCkwAMx%2Ff0WZKsNepviIO8vvvn5axW%2FXu%2Br%2BS%2B%2B%2Bm0VF%2FovfqdKftAsJmsfIiJAiQbjz7gQCuFOYcbWxa%2FDEtG7eJN79uAuPx4jYxX4LM%2Bbnzd36%2FBPW0NHSxd1HWnljgma1xxW4wfer48XKBiV7khWYWqRw5Z%2Bppd5KCwQfifP%2FwSmDyPzZlPkX48YrWhFTkwMv96jOzPcF1yy9sUroQTMwcyG%2Fd%2FWPl%2B9qgpE5LUZPVrhj%2BbvO15yRz7W07VSi6Boy%2Bld%2FcI52A9Cgyyj4wil%2BOkl8P5rFKQEr10iWfKhrqXdvyeiuPrVc36xVaur7vZXUAREEypfAjxRaqtJxA%2FgQRI4ZdbvdeXOD%2BY14DkzLrweLGDXiAHAoOWYOUwuJoLYwDD0kfez%2FbKDHkgu5f6acbQTCV5%2BPGzyxMa1qHu0TAHLwJl2vdLBjarR8PcEECev5P50%2FY6vB%2FsX4LULrCRgRfIbPhaLvx9HCMWBA%2FjR99OSwYTb%2BTVVkKN%2BnZXkIV0sZxfoCBXj12UgkMz4dXsaQtBUPCZZmcI2gxyg8BWjBUHlE4%2FwsVz5cbu02sDh94y6KJJ%2FQI7vsPm6Q6U5f%2FwVkjTQYDWGUXX6L5VSDYEMWrUJ8xBHrTr%2B1MkXcASe8nf3wRT16FFj3ZILcs38T4QPh3KCnkvH9Age5%2FmzrZuTjPm5V57Dy63ZfRSNfr17rFV39k9%2FwZdcSNCi5eEAgJI73xXvHoCwvCQjweIbEAAGsOAALYIAA4cAHAeAFggAAphwB5wAcEBwxq0gUZZmHw0aG4tIw9ZfsxAJDRQym2yYQXm5RbRhvfPxsQAAS4LxUGUVHIKXsWc3L%2FH36hb2BWMmZWhuW64cGA6BgdkfQmiPW6I4CCeAxQL4dPwbbkFwCKGA2Pt4A3X4eSXJ8niQ9dB4nOMTpECfC4FKPDMop%2FQUK0ndpm7T3f8v7%2BNiUEDrCB4HTr0fQQ%2BQhJ%2BM9XYY95g4AL2RIIOXeQtCAuVpkcasFeR4dlpAkjUQEvkgW8T3l%2FbAgC3%2FDfdupV43c%2F%2FXvw93fuZeDsvA7SYRSeaismWsO5SJ134KrlnnLiex0dIh%2FRcZeOGyOH2GZi%2BAyk8vzlx9n7y8RNVIKacqL9JmXmmXJ8lb%2BH5OaQ%2FScpusCiJqg0Z4JGDl2vyohluoWcKQTnxhEhipSxlqj6Cu86vvAlW0f3cX9o8KZbozwyH8dZu3OYtYz3YVJusxBppW%2FLCO3NnOVvlGCmouek5Vg5a5u69f36xeHPeT%2By%2BN83wt8IfBmIy%2FXeNJqRtgvusJe8tjaVSVAksthNQJNjgZwHtehg%2FsWUqWiz2gR5JJ8RkSyN3Hsvh%2BA9k3se%2F70jY3QLgcw9vrSxV8K7E6NMN1TDrQQFgYlBBB5dxeTlpGyozhDI6dE1N1KfGyZVSYMhilx9l8H4QDIEpi9KHF0nWDY%2F4b0RQvZyur64Tm22Ejws%2BkC8XTvz9Zkj0%2F9wVCEU8EHL%2BUkM02HUbiBvpdydTOeeFio9ouaG5YskM8Dbp3F0wnbBf%2F5f8JB7ZHrF67ZQvVxtuOim8sM0X%2FYWL0YqZ1%2BjuFk7ApLf9Q5fG88P0h6P7cle0uLat52FSlIvnz10jU%2BpzIMEoKOG0ToD7G0TDOoCw%2FaD0ROlzMbyGJqXY%2B8%2BXoycMXZSII5Kgswtau8YWSjOQUXu%2Fm9Vl%2Brf%2Bf8vfSo7agTifUHWoJDaqVsvrXRiXv8FUU2dWBgO03KLDAPMFyg%2FBgUxYZ%2Bi%2BMOQ7Br1S3hqG1fU3e%2Bjn%2F0gtx2744zW0o1D6Wq8TP5%2Blf%2FthUwUQVPOGbvVeJByRyRij8v%2B3YcuPj49h9uMmFTO%2BXD18DGMecQbt31PxCZ%2F%2FenPjXbRX%2Bgrdlzer%2FekPO1PhqSkVMpJRoGBLhf%2FbDxMKpdUGjUlhMo3g%2FYVygirTvgSyTpxyCx%2FNbWXG1964zabqSw9hhcizwfSLh6uT3d1RjgyDRQZVYwMNInE%2BT5X8P6u2XL2J34P2GkHNW4rwXwSZ6d6%2FPEuBC%2Bm7pxk1R5HAw7Rf7NoFccMvYznOWAaE1Ct%2BWZ%2BXOr9zUI1lrKs%2Bhz%2BqfusHQX14uGtgTukH4Jml%2FdafwXk43HtVBIyHF0f56h0oaSXEUFW0TaZvVIPlJmhykWggOku5hg%2FsKjRgnYpx%2BgEugwSCZg89bvH2Qw%2Faukidk%2Br3w2UgQDA5oFTdShAxaX%2F%2FFXnhDcXkyFu%2F7T%2Bis%2FD5nfx48bDmVMyrFXM8dEhrrlH8MRkQHUjiSrQ7%2B3x8qdUN35N9jR4oUHKExn5GcjPYVPGJeyNimIevL7IBXxYzF9tcwvSzHBjxaWNhB5Pd26sEHG83l2aBQDDfIMaEgrucBsGSpocbkcp%2Bu8KEYXjJ%2FzegIThX5OaD9a%2BF9BxaiXHVBaz2hXDZXs6%2BcOhh2XpVsPTUSc1cVlx7e0J3giVaUv%2Bc9f4YhkEfbm9e7%2FXrJ%2Ba%2BTi%2BrU9eHTAf5ffWJuIrWI4vifbD2b8LZ1IgaBXFoFAeuBLblCXpkyWTuDLdUdJHw73Y8ngMQmNqky7IcYbqFpU%2F%2F6DcPpTkAa%2BIhv%2BcMBjg%2BD9w4QdF5uD7A10odvr%2FeT15doLlmGZeVcg%2BSj9szCcJefeOdfShSVyDWUywXXc%2Bm9Wn9%2BCa7dQj6orwON627u%2BTzTXxuf2hnWUub0f8S3081ypSMV%2B0Mk%2BUwyPC3PPQg4wuuT9QMCOuyvLhc4s1U04nh1Mv9YY2EOmv6BylyDOVpgmlW7YJI21vY3h9cZjoKK0SD1wBPJmQ1RDF30YcdgRtX496qaATOz4%2BHLQJj2D7gT2GV8IcZbmYQEwTU45RA34tWiusWSNbRG7Xk0WbGsaoC70WCKjruFeCG%2BAHIy%2FTw2onAvlsEcFVF2uNSrKjX9cq9ZfLK0kYboEpk2gWk5%2FOuJqGq%2FhNh2ZLc374c1ZkNzjhT0%2F6%2FAUV4vdSMZ6Vgh%2F8F%2Fl%2Bm%2FGYGK6gEYy0cfNQEL3X1unoYCykw75flsqsPUj6cABlNBeKRxeqelVWVoWx6CaRDcpGXGzxSLQ1EaJILzd69sMUhiiU8zC9Qe8Eek5kC79hgysXed%2BowdGHG41lO1cyENZcW%2B0R6%2BSf34k2Pee%2Fi%2B9ndHzvWzr1LPZ85f9vFR0dLxDFAQ0PBXEwpM%2F4QkibY3AgK9wcBlroFj4LG%2FaCNoBP15%2BB1jtHCDPsvLwKT%2Bv3E%2BbzcarnX14J5DZaaw6iCmW7e%2FSkVMZdihDo7t3dMt73P7blBBOIC5EaFp2%2BD19ifv6trR0QTZ3k9P8UTysZ2gkeN2Cyyyfpha02CDEBEDNGN%2FOQczpvGMMMT7SIYlUP77iYJanVfgKzenL6aI6jTA52g%2F6iet7qJGoELFYYyW1%2BRe23KSxTgx2Pvb36%2FitGw60IcYRmC%2Fz9TKGYcMEVulR4T1U5FO91y%2BURInhQq5F2SjqxoLNDZjn%2Busx1tGNbEIgws9sZq69XepRLD2BzHE8dqsp4kFZMFG0oeAVFhb1IkkI1RbH95Nbu9jWQSIhbnx7fVI20%2F4ZCIKJ8d3R3B9j7zQiES3vzYYXHoS%2Bre%2Fk9aq%2B%2B2aS%2FZqPeT1%2FbC%2B7n8PRJdNYavwXDvyeEt%2BJzsT5dMgEfkv69hmAd%2BvV0LsfclVoD%2BEO2ohxxoPstexDlPhwu43mRP5kyr%2FBFzG2t34JbK9E985%2BQhqe3om5%2F0ahjISfIaZ8SnGQVUrPf2LjN3d7xOjt%2BMmFt3YJzuRiVcjPX937%2B0HiZJXS3vNbPUfn8f%2FgoLdhPDeWe36hogr4vbDP4Ba5nZ26pQKeNQiubD6M8WFHJ6Zim46PEtJ%2Bp4ppMZz02nwa0v2Ird%2BCbXY5F%2B4WhaOn4VgTKldt7bX8Q%2FlPGAgcmOP8tS734cEB6XHPcPcxWK5YcDoplututI22rw%2BJLG7ly73qPjCxDQsaXPxHTbiXTpb1CBBu93E5XEOW58cVSuihX%2B2WMV12UUMLV6jXJ1tS8R%2Bq%2BxkvXqop58MzhUe77IExlVVV14yqkz1gnD5YYKok0hlxqqhrXLzJOmvG%2B9X69frUvmEJFn176%2FZ3KP%2BKvR2PSIt81Dx3Hz8vhxfJ%2Bu9e0963o5Iv5hhDqG8m7RNO6BZ40SrpInakG5XWryYAb3SaGrn8aI%2BnPmzPknoI5ppN5Thrx2CyOSlH%2Bw7mkyXc3kUDVfaU2%2FfduKVHIbu4yz2GmeGJcR%2FnxS6l%2FhyE8ucTo1bgkCGX%2BQpDkFky8DlD9hQ54oUvhKoZJRPd%2Bo%2B5buZiKu2n38w7Ef8uuw2aT18vwkxE6jBIuT8C5f1NgOvui1VpO3L8mnhQRM6tLfqf9J77u%2FxKF147%2Brk1SvV%2FrlVqdMn5%2F17Nqjl%2FvwUTUXa0my%2FX2FLvve8hq82Y%2F2evjxH0EnX0GjwQvL1437pkZYt%2F39etSr1YRiDvvPnvxEgxp6OXx03UM%2Fged4iFaHGmLbFXp8kPkBdcsOvO5ZZbg9YSK%2FJrT9rCZFF%2BJ5j2XhJHy5qVRdWvENC5UnglicGN5MznSW%2BGUJeW%2F0UtJKrS3%2BsXa1p1lFLXNTyzUO7t8ewoyxITM0fPl8AAA5VQZovi%2BoFd9IXX6xSX2r3UtV0sUl3f63c6sd%2FXat%2F%2F%2FW6pg%2Btdq%2FakTqr1r439XoZr1euX61%2BtfrXTKxXrX612r36v4OxJhVoOPIR6sH5woQMEJUGJ%2B9OPO%2BaxiybQl28GZXe7w3JSKh32NoFK0wv7LrvtD6r1cK1p9NtrXa5frVjuw%2BtdrKvV7uuJWvl%2FU1%2BrH6v%2BtdrW3CwSDnc7EX%2BNdfYYHBc15tjJwfHkpdo3%2F3uKFAuvfjRYAlNvsHWW1uGKxRmwQUocbq7aepGy9V6GQO0DbNeImgzgSguXx5QwQFAgOGDxsOvQmZv%2BGHEUlTAdFDSFJv2LVpLN8v1gog0Eh%2Fh2egj%2FO7e33APtW4A3E7nWU%2BrZ8OI4fDPFL%2BMFkJjc6by3fL42OxNncWJEhooVl8dRXX4wWCA61U5uyVZjYKiKtZHuPTgpaPlSBGZbQHACICEHAx3zA5hrq1wgXRggs740gHBxYxAVHqia4lFy8JVfta%2BP7V3a1yrFjnxztZXxHsRQomv6vCv2pH%2BTY52K6ymPn%2BcuvBvk4hM18pyHZezSbn0%2By%2F5UdlMkl3jmE2FJzy2KxWK3FYraB3yhFjFdoYxhXJGiS5LBijpCHDnBQYoxLh44WMsZYMUGOx8W59LreOreIKIYKaQH3nZOMov5ijLYoMUYrizJ5gJkH%2BIDQ8w04frowN7PX%2B6emf7TM1MGu1d%2FTjVbDgDTuRNCJkzA%2FCT2MDTXDJc%2FiwFYCMGP7%2Bs4Fuvv6K4gciUveO3KnderdCdCl%2FXq4qa1i5Vl6H%2FCPITrKE%2FeIFBMwWGZYRnL97onJBXXf0CIa0Fle2sdhAQaxXvrMWoGX%2FQK9aQfTDXgO2ga%2BoV3fLrRPhjv2%2Bc6cLFKfvqL%2Fjb9aq1aS5vWr9X7UUVesUlE9XRnxSv9DBktgxqBAxQYTihWcn8cZoRxetG3nSIXVwGfLxNRgjw3nQCiTOjVBh6BcEvDXnS1%2FMa58pyZN%2BgnVxNSqyXjV79enuvWu7jxfaNV9H7VeUiBDn%2F2wjMxY%2BNhuVjSdfEhbmhmrRX0136sd1Tfq0V6LF%2BqcPgoJy9B6hCxrTThomHGtaplpZfT44sM6SPqRFIMBnu16haGEA3Am4aPj2Nbr1W6L%2BeGBGIcBpGyxyeA2%2FCMhC1l1vBu487L9pZoUPDMnmHbQPsN5aPGBsGLP64GrfMCrn0gEfbnxOqwvramqTYFFNwHfygvNLOcIgJDf%2BiLp%2FWRL88tXE7aFP%2BuFv3DBsth3riZwB7d%2FpeCL52L5fd9IF%2FNJJNAfTNqRZFbFaoENoKHAbP46s788Mn%2FD09dl5EodVjmmr%2FirQqCT8XCRQ9aZ6ZFm3qPjSsGRx9d9RSfO92DLnW62V%2Fepoijau7njAF8PEzkxZsShZZ05eJy25BgcIXp3YOEjhu%2FqTSSpD%2BvUISdjGmyj5FXy7u6Q2XCclQfxvgNpIFHlqZjG2gYSpdNkp7bMO2vGrbnNrAQSH1xn6hjbyyfNcu2Ddeghz%2FcFkuDviCg%2By0UxpwKpKR73GVvoh9jrytfPg1Hb6UBJOSXu6bFLNRMkA5wwCQW%2BXnbWBRhQeLFLy5afwJ5QwbLghw%2BrEAYGKUwKUeEO%2BuHVF8acuFwQOHA4XGAkohBHnDQRs6%2BD90FfQ3iA2iX%2BjTJy1%2B4e2NodKzcGLghD49edIQnXnSTMcrVs8qP70lD1E9K0yUj5LcARNlH%2FoDjTdYbvrnjQ9yG0n78MIQU8ljBO6jeVR1%2FoCHXyJDxVIM0FBkuj9%2BqlygloYMrwwHGRg8J2DV9QyV01WoQaOm4n%2FqCLssPHrVwVXu4%2BRqzL7xm9rL%2Bt4fJuCbe4%2Ff6BPBN5eJIY8n%2BKNETQd942aXr1%2BCS8qjl6gjlZLgdphY8Py8pBDE59b4VKGJmZW6mkEA33sHfFk5Esf5fVdw7bW191ZyR06toxJb7JBpR1rXlj9eoeJQfPR3TM6JlMRJqZWIFKaazP8l91RMQX%2Fw8GgTieXHqfLL8KwwGmFo82XBDm7Wf6wKIYnKR27xiEBwHz7AFwxvWEA8C4eFBYrOdPhK8dwU8Ei1PMD1hSSEdJTQfuJMzQrwUG8Fg%2FGzgACWEMMAKggwlwQqoYSjAn8SFYdSY7jawmcsAOihFp1oFFuL%2BCo%2BX7l1rPd3wh8eRONBDfc1oX2ebEB%2FwYXTHSJxoMBvQa%2Bu0l90lQ2d9YJZZh9%2B%2B9Dl%2BQvELHwVEzU0SRK1Beota%2FBHWRl3fgku%2FFl%2FXwSzVUCH5oMucazcfBVFak2%2BqjRI9j%2BZg1GqMe%2Fznx8P3y6ReUZl9fwrVkSD64K5NJGdr4zGoFW%2FuCUmuaFnnayslbvzlXx4bEz5P2uOrx2XC98TUGvH3dF%2BJl8nd%2FlM7u%2FqsJv1GlCFzikIkTdSWaJGOdvpBOOERIYV6kXC%2FOgsvGIrZ4amjAH8v%2F0H4Ez7A%2F1nQOE97p3L0vePyfGxauRORtC2tQh0eXpDZ46X4J9ogZUjTNaLrJkyXfgpmsYIbDdpLr%2F7hgv%2BwQC3sfgkFvppQW48Ve5PrhupI6XL%2FhHW9V7v8EO28Vpv3e5Bj9685VyIjb68ORsZ44DSi%2FYR7n4njbV4d0M23fTqy8mr75aw7mwuE1fgIZ%2FiR9JLB9hM7SrWzhISCIm004%2BNxIOOH2w1a5MiuQmY6J2kWvIv1MrFAZRmEeLxEggMHdR8RyGWyNZd4DevosIKCk1uP4JyPvhLg%2BTi371KIpXdV14aPTlYqZRTZff7IytqOPrqP81HuZ4moB%2F6ssMHuDJ5FAZ7TPyvVx%2BDsjIPfJMVjZlryEngdJq1j9yetVdR%2FjdQa8%2F6E6%2FRqy%2Fv%2Ffl%2FnkTW9r%2F4ZJQZwgDGv1PD%2BCYsEH0jg7Td6i6mzrgUvw0RGSY8YGVY0PrP%2FDZSeEWanGP25kj%2FBJGhMU3w65%2Fwv0z6xUY6JygSkDAUCQyKP%2BCbe5v6f%2FyGveX%2F4RDRlxxBwfREgiOvl8KE%2FGn90i27vd5eOmz7%2FqW%2BgHTqy3GM%2F%2FDglM4IGiXhJoF%2F8I%2BGuojQ4yDKVK1roRqGP%2Fh80obgE1KRHg9qsJ9yyxq0ydefUGbbijQwl4xsCD%2F8EJXfi%2FD8xncMSbYSoscvp0uxMx7BDRXwwrS1u1ld9%2BjLUqt7nDM29UpttH3k%2FffJMABIIQQ%2FH9Z8v%2FTh%2FHssy4xbx8QG9ZzTw3TKroL4Jrw4i6FvQ60aGcqVtgjvd8PwRYcHoO00x%2FwS1yY%2BPgu7jPu%2FXD8N3vVWU0P%2BSGCQhRva7C8WaH0Krwrlp8I2BRgRQFzYlNj7%2BxXpCCUIMQI%3D&media_id=1254206535166763008&segment_index=30" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:32:10 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:32:10 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_KImBMpt7QSUPqH+jP7d3wQ==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:10 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786113053714705; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:10 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "409842ae67c90d017e967aa8310c3e65", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19922", - "x-rate-limit-reset": "1587864356", - "x-response-time": "31", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "0049cc9500d19cd7", - "x-tsa-request-body-time": "64", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"cF0%2F1bNCsV5zG8vEINfrncApyjo%3D\"", - "Expect": null - }, - "body": "command=APPEND&media_data=EQfEJ57ZpHhVnGFGDfLVjR8B3yGRWJuHBNAtFOgrwEp4AZEHJNuV5FoJDkJaFyLuaXy%2BVHaIoUo5XJCPtxbNejcbjxIPZd3x7trT3980ZSNGYfsf5X%2FG2SfQP%2F10wl%2FaiDihkOPBM27bVeKGBr01i%2Fl5sn5s5fapyof4Ac%2FtxJvmayr%2F8xeWmynGzKJE%2Fcv%2B1IGII6mFEgzntjMad30HhNoM%2BcgIxbz4Ej3Jyb0Ru1i6eI8EU2d1ePn97kTmJgUigGdRfw7VoGhAFmqEsbB4DoRECqo4ZEjMXz1YE%2F4LtWfUsGP1lzktM7OrwRZkCw8OdYw3%2BCuhlRFYlNNBXdrr8UQzEcprEH%2FnFv9Zul8bIQYMPM0V0Yz1zNZ%2FscGSSmkUw6VWiT2Wc%2BMEHo%2Bjjzd2HMYCCIltHmFPQxhfhqGq39usy4cvrXjSQ6e4ifzmdHD8VzWc6C0a02Sq8CI4xZDdz3flFxS2d6sN3fqauPdi3CR%2F0%2FrdsKZ%2BS8L6F7O7CPWwrYbM2bFgIS9JwE4zkL9ga%2F04vPGuOxpRcTYLM%2Fy8XLxBwG%2FBOJxxajvEtoupUZZKZfx70dZxEYNkYA3G1BMYxlLJ%2BVH8nHdO0OYl52kZemv8Yxy%2BdO4eh0mA%2FW8rATSGCcUn5W19n4%2BkvsVsC1bO%2F%2FhFeEevdcN5yIRPRX6Fnpl1kFGY6a8cUEL4GuJqyJMOKtZmGHGH0%2BGuWlP%2FD0Kr6m5WPf8RnfvfXqe356mRQPYINykHzZkhs%2BGYlvzqu4gjyorveT89XLu9rTxAnd7O%2B11FiJs8Gr8ZC7mrU8aWIb%2FKY8r3k%2F9TAR%2F7yCD%2FMYN2rELTC%2F8oVpkzFLzrAorWb0XjiyH5ggr9qRKOL3c%2Fv0hBDB7VDsS2AVrD84bDr8UK9RIsdzwpbQQ4kZU62fkpYob9m7wG5j5ql7O57hTlt8uFxFpl3rssVUM%2FK5k44ogIC0nG%2FCsQ4aKgXi0bhvJOPE1rQwQk1on4%2BX3G5mEApNT8uA%2FyV5eXifkXjWJMeLrF1xcX4kwveDz6W3rzsPlxDnNwV8s3fhMXUmeSj%2F1eXEteucNGmoz2PjA0TNw8Zf8Klptp1Y7P6dPl%2F3w1Tl9fuTKH1D927bd0ET%2BvGzx%2FwQx3FCb7i3eCy1SpyJL3eXqFr035cXxrTgYamWfJ4xP4XypYd6LGLedjg3O9b5fm%2FKQFKTNQd%2FySmwlqpn6ScK6Ybnk%2Fy6ozLca%2FyeG975JDLWT5LJFRiBPoIOP2wD%2F%2BkU7R%2BWtoS3M9cvPkvhF5uLx9kgquB0n5uY0thbenEERHNJhOvexYi0mt7Ox%2FOPxDsHfklZ72etjEQKCxHCzJ8ScdhMkdXOTE5iDvgdjU7hflvi0g%2BIra%2F3TLEuOO2VVJPKx93a%2Fv0Lasn6WKrsv7%2F%2BjM%2FBJk5b836I4q069CaqjKzdf%2B5DbtyfIsqK04LuOxDoyZ4anLD%2BD7Lj5ObnfSFFjXrN%2BohMF8ue9tV6ocnmMm1uKT6RGXdWMnpF3nnIu2XfrUQZxXeqNxUSbHaxfS1F%2BixSE8%2Fxf36F69Gcli%2F0UoK8Milo6k0u9o%2B944hIXIfC2XB0vA1J1JxyA%2FEXfbG1nMIAEimf2UFmpYwXIky3u5N5V%2BdADaVb2%2BQUtam4N3m%2FNstfOUOc9jz52s3wt%2FZyojkIYQvgLLD0icaz5xculIGIoKU6HFLUTo8l7cUZMxSJ3sCmgLJEZIRYACYgurRriYwm5IpHf%2FhP6fqq%2Br%2FLPf%2F1JbjOzncPrOq55mJaN1%2FdVy1%2Ft3%2Bsx8HIbcmki%2FeOY4BUITniqeQUzREeEmfAClApPvBlRQMx4lMHHZ1OdB1GgHp9sDd4Yau3MfG%2BhI1dodn40C2LqPQvxTz1gxWJ04%2FGggI4zhF4nsokonCOABIJn9mhgsVMJyKc5dXvae2gFQznJyZuUGly3RdXVrvS137JpgfAevFl35yR97p4rvTVHxfsv95Db%2F8oEMZhHcstZS9ACFTVJG1SLxhGSgC2CJK4JxBDlQK5jP6if4I6%2Fob6vi10cDlJz4rj%2BiMkwHK58dBAo70yaUdCk%2BSkkiEtuzcEYCC4ZCWA%2BYO8bCCPAUEiNIM5GhPpmUKNhC58hkVfCYLJopUWGw8n6MDT96HraEj0eoHe8OB4W2A3hpdtIWlU7dtKVblSsr4tOuszkPTMgIjFE0DZc4AR6Z%2FaIXLNyJMt5JM3WvOgcZytTTXRvhw21T7B8jSdIpAtq3Y1N8p5Ou6I%2Bx7dvxtLlfQtj5zZCDdgFL11fqmo9LeT7%2FyXw%2Fymnsvi4xXfaCdTSjBpTlwE4XhhezYkCL2IvdaDrzBkYHw3BfHMLvDgFk6unsCMz%2BdXX%2Ft42trui0UXKXBakp22Fp7Lrunml%2BfX8KJ%2B7p8eVNTmS3XTd2jtXOekZr%2FdDzOmT3Qs1vgQo4nDken3B7zCB77OxzaMDU0wjKRx7akVLWIQrlkhaUl69TUvQ%2BuxEQGIZIFRwBKNSQJCQShYSCYKhQbBQLBQJCMKDIKEYKBYQnUnn3yblXmKlpeNb69Km7le1JU4Hgd3HkfOO8PDYPFv2GkqqJ58XZBeovh2ttBpd8%2BP4TbyffNcer9beuXhGrum9P%2F2TxNeCa3r%2FW10Xm5k%2Fl7BgoHkVweIFk%2FPaqs%2BU2dC7rpWAuwzonvv7XwTeus8HPxVdAaaBCuwKCWnHrYNf2yDkQoK1VqWR9v5KQAAtQSI0yAbU0PglNCJsAAtxSUgE0779KNFrK3GROl6zII%2BguW6Kg4AEkFJAqEhIEgsFBsZwsFBEFBEFCMFAqFBMEwiZzrb4%2B29VnHcJKsJNzEVOqXU4HI3DL%2FuWfhuHxjiPNJJNVDqf9e3TNUMnL2nptlCX%2BU1HnLtlB%2BHOe13tGm0Vh%2Fe4X9ys674MwQB%2F7tskLDPW%2F8N12dPWEUmHz4LovKX1TzvEOrk1r1JSw1OxjgvzXK5P96o%2F4vF3y5F1TX7eHd24alFbLi%2FFssvJPiq4r8NpoqyQdxa0FCGkCHg%2FvthjvhpGwwIaZxOAxK%2BfJuN4jcUhgW%2FUDgAEmFIgoQgsFCSFhoFgohwoFQkFQoFQoFQmETN3fPHvd86745lS0EkxuXlXqCWPPu%2Br8PZ%2FdePgcs0P9iIMMPlHr1%2Bj97p6dN%2Bui%2F6x%2BeDRxX9pt%2Fgkt29%2F%2FeArUB%2BFZfY1lxv5o3X9eoydCO8pHtca73%2Bc2RJMpvmVrrlGNdHtiYm1j%2B%2Ft5GZCEsRjVJ7zRIoYeJf%2FTiGtbSFONWW2nrdHEwvcY7qFL%2BySZ%2BJah1SFFKkVpM1Q0kJUiXTxKWKQKaLg4ASQUlCQVCgVCQUCQUHIYCw0EwVCYUIQzCgTEgVCJ3Pt7%2BefHW1b8%2BrtKmt1cMvJNzipDQd%2F4cuGdnL9Nr4jy%2F%2F9Ebrs%2Fbu042Fhp8uDTeRD6zjnnpK%2B48hs5qE8R5fDI4PnmvTX1JrcV8BzJrLHV3T5Tby6MKr4Qsqdh4QLu6n%2FvX%2Bna7rlXxZ8rFOLTf2Rw6jPW%2F1D0n9%2BYxet681pm6ZxHZXADMkv2o2ojhFKiEIJi4tCKWlICKdCekDgAABARQZowDAoFd3k%2FP%2F9C%2B%2FXsIev9s3F9GczrX619f%2FEXa13%2Bsqta6lTonqbj6udyXVFyDl9d%2Fq5Vq3fd3wG8N6AEOcFwJQwIVhAfNSryAaWcsFePHUjTsGo3AlkXIK%2BEY0YyaCqjTjxoFS82XwIImQOGbBBxW5VGqUznWTnmezj3VF0agUyXWpG0EzI187SnTlhu89yv8Z7%2BhL45bXffat%2BpVd%2B69V9%2FrF%2Brd16skte7q%2B%2B1Y1hwKJBcj2nTEuJ2W%2FxrHDwUGEe8tHAr8e53fwyywM2DzG4vlCQobxzyrTJllx2kAAalzDAAGtLXHAAIkoDgAESU5gD065iH%2FXtDfDSLXYRN8cHXwPg0ABJEDgAtT0wcAdQcAFKAhhuWyJrNQSIpkzfCbGRPQR0mSTBt%2B5ZNbveRPYJ9bmIQoODK0EJ0UIbYXSBp5YGb9tjNtcwGDSwO9JeY5d12lJQbDEN%2FAQvxBXj01zt8cHvLaZCshEg8NJ%2FCvf4Zfoi6ZvXKFjjTjXx7QLYz3ps7%2BzFdRYL7sYmr80I2EJBkCCpCw8CNIK0%2BHmhI36J7abOBegvKtbaxcKgIQDobnABhiVBUZ8t8AGFrHbGJ5NX2BKMin2mK1e%2FWLkJ7%2FXqvi1Rf2tVKiN818yuWKWdVjespZMIqXlV228WxbmH%2FX6IO3R9%2BOefewmFWFIdIFxnHB%2FxhyWvuCypy23%2FNXGCqteucsf0xVvuW4rPmAwNFjFWED7Qw7NOMFD4GQi1OKsHG4tOxzMlRagquMMqQR7Uy4szDUKdVe3x%2BW%2BXcMQTw4NILnkrV1aR9ig0kR92bUyaexsljEYIDx5aDqn96kINY5%2Fxvef1L3hv3PPNdXLInV%2BvXfwn8R8%2BX3MClzEMKl%2FJ9fAv4fGx8bDzjqYEOTx9B6IvqLlRc%2FewjQJcDs14xjGcA0nGqFrruEgrf1VVUmMzoLKgMoJS%2FHTMsr1te4EZOS%2F17wxk9emlxS1fuuu1bqlwQ6qy%2F6uNEQS7d5jEKIUc9FF7oFP6FdE2ubdPdPLuzcl8k%2FK1%2BXacyRUIY1FkPFdhECrpEHzE%2BX8CcBVJAJrUZS6jzGlAtfZ%2F4H4PfsBPZy6%2FQr9Gql8R%2FQTe8Rr1dVq132rRd1qaalhJKK%2FKykOfjJhuX0oRyUzTWvQeJ4E2dcmbRy%2BBH%2B0Lqt0bua9PtdXcReOXl%2BtTer%2B6O3fuuX6NLY6gnJSEjj8aydFrJ%2Fb%2BFS2BHIL6R4dqWtIl0JGH089ruXD8i7PevSAAwt9ZEGrM%2Fs0Lsv8%2B99H6RO2rp248yK4ksOExnLRav0xPZPvd1CHCb6VvYGaD7lgFwndxqb9J5ZPhAoDtOWYL092wFrxeZH4leujQwhOT09CaY9Jcnocxtf8%2BSdZq2JVv1qvXr9a%2FVr9W%2FQsVJZP7%2FFjNhnpWHLYqXPWhB5EC%2Fyl1pyf3fQ%2BqGujYhRorwxMfghKQxz1T1yEZgPshEtb8sFWwpGPQLQGmC3QWObz5PTy3G%2BFn5kxa%2BrNMHMqE0v6NUeJj9%2BSs3xRAuckYfkMjmrNbReMG2gqUPdCPg754%2BJtw%2BssOl76D74qfL%2BEQ0B%2Fi4QgdtoV41LhTw05aa%2BIhqGq98w4D1%2BceUKNZesbwyf1EoZ3uvd369OK5VgUYfD4KDqtJVSSi8G4sOClwDmMyVMuCFr24I9x9PhLcprEf%2Fd4IC45S7V1AOLc019hhhshAVB7BBVxBJEzcFcGm9ww6ggDYPvoEIKVBY0mDfwU209MoYDjTEPhZCbvwXb0t3Z%2Bioo%2FDdBkIJaNpN%2FDmBMB%2FCBuai6elKx9WbdwUTmgkWGVf%2B4rOXYvig3y0Sk893yFZgj9XPgOlskK8YfaVPw7qVSh7N%2F%2F%2FHzG4Yd9oXPK9BlYlY%2FaLF%2F5dcSjP6q7tZdq5N69vjQ0GAWFd58iu7cXF4aCwgjvbu%2FeECg2HMzv%2BOxCELWFQXAyCI0a04u09wDavn7z9UFISIgLYtMd7dTzH8Z7vBkE8FMQAAQwIYArmIwl0GgsHEyGmra%2BnLBAcFsAPznFovPmwYcRcJ%2FRO%2FCMpj1Uwy1Tor%2FCdPZEnysX3nr46S3rUvY8rvZXvNJ%2F4JCYnmWX6%2FETGIxtD1%2Fq%2FJ71%2BIs2CQNzRZw9vh6W6oM3oGcaYw0hdLktJfaIRPvyIKzhYTXUq4zXMONLW8hsOrdoP%2FY2O2CQTRM%2BK8iCGxZvguhFBqYi%2BFwq6ubm36XoK3G2jXl1yVaijyy%2FGfYDyiCYbR87gmvubFHPlqflRcJuaX1esTFkd99%2BQgsj3e94hGLcQiCdPhQIjV2Bg%2FIlj66oDbFIgglAKAlKocywbUZMpSE%2FBNCLDz%2F7E1IxI9eG4xb5urkohf%2FILhpDgLH%2FDgga8qlQCfRU8fz%2BT378FdIkaHmpjs1Mi%2Fn6Jqif1P0CUpxmggashXR5ppyy%2F%2BocpDxG%2F3Kman3%2BEr392vgj8ImAUtdhkrOb9zYX%2F8MEyV0OMjCOn6SIZM7%2FP7426s2a4%2Fnr5HyPifXu1eXi94mE%2BtZVi%2FBH1X1eFYYRXlSMJEivD5s86%2BvnfQY55%2BHCSGKBMj246CSknV%2B7cd0Qfu8aaaO4ccN9uX%2F%2BImwTyZL115ywMvQpbNSmsKwWc%2BgM9z3Qw77QV7UbdLFV%2B6DUdmapf%2FQ80NAz5lBZIaHYwqrXjoYFsqcrUU9Cxaa2fYUqMajqropMJvaX6DWibRuS1yIvy%2F34qCV4WMXlMraMEwID3vjN47i9tvszYCyjUKN5owRN9gdjZf3y%2FXpfXv17nXUjoqJIJWvfOh0Fejv%2Bpsryx0sqBoEx14Ib74mT5%2FzUCw9cH0XL8EppofBE0X5ZJ%2BtfZyL7yP%2FIbc%2BSfSTUqKHRMu74qmsSFR4hbDm6tg3CfglTilPsMbuy3dWW3%2F%2FGnKzYEcQcNp64E%2B7qcLx8XCjHxfokkZN%2BCCcy4I%2FD%2BRfnbWvN4KdE00%2FDube9SSyEq0Goo8SkNL5f%2FLChm9uSCXquCT798aNmB2yo9J%2FNgO9R6p8JrokLlHGTh7zS1MMI%2FL5ahyJ3%2FQWj0cpZ%2BPEjgO%2F6jSP91cFtcq3V6l7vwQ13e7E3fNT9fyUBGl%2FBLfH87HfhuVi9SjMcdFA%2F%2BHCMBwnYKj1GRn9%2F%2BUrv%2FBJh0U8vUJPoPWG6csg9rPtNYRXtsmCcu%2BgzdOUnc%2BHVkhf2fM%2FB1e%2FoE8EWclJE9PHDTcA7%2FYMKrzkoklEWPhgB4zKd5SgvO8aDZ%2FxpLluHTjs4rlPDAfjYo6tAzlTuCATpf%2BCCF4nYPAAknwn5E%2FFYjqZDy8jvDGRgsFVZHm1LX8vnGHFKkNKA4eNy7ExHHzN1OluOX2hoAq4oqDCGTA2fCnXQwED9BRQPQAsrwABQcajASzxBfJYYTA3oNXCJ0ZhB4EsbSuaeNQ1%2BX1lSEjdFQYIGKt40EGA3jif%2BvdN7u0gEKkD7Wuhz%2F3x1oZyxY5a%2BakvIqWDxeHhzAx3e0SB7VjASupiWNsKbcnShxPPfBi8TVooVdFEDfEAnDbgw3TFtLz1FRAzNTQ3cCqXi%2BZizQbD22L8qU%2B%2BX2llkG6NhANmMnf5ZLRkQFKKI2Ek%2BK5G6d%2B7nudiQoYu6u1MSCfwyvp9fYIJzG5WQ%2B3SEZR2bC6V2ktTrZkNu3q8nBDv2EOuT%2FfwR6HqqGKhiElFDOnL%2FyYbLFJENDNyV%2F7d7vLDu3Xl7r1qa68hrUpH4K4cWp3jrnlt%2BPjJF%2BXroR36984Xz1dtJbQGKeXSD8cSLFfwtS33KFEI220cYz7u2eX6%2F19BK96DWvoL21chPjlOireov99kQIxL6UX2HueaH33ZFwJffy6UBxFv22z3NaFpggMVY4lewsQ%2FwY54B7wepkVD9uJeG47Di1xjQ%2FrUqGzqpNLMzQ7%2BtGse8DcJLu5Z20YISZhnJ9kOrhp70g9puisUpUnDc53Hp8QOgpbpbyui18AdjKGybggC93nGyZVAAjfOH2RIPiPgS%2FjtTPkRog0ztUsbzlY1oh44KRu6OvbHf0RFKJH5hpYgDsQ09JoA3QOt7IIYts44hGC9%2BD92QZH%2B4d0ct2xFGWXQ3TWS6Ip6FHX%2BsoSZApVc5mw7w10WBebS8kqcscahMKqPZOfDWQ8flQ02EhPDJyR02SgMVyws9O3t7m%2BVFPKrGfRPbbPDdRNFvdiA74S%2FFdpG9vXzaU1bqiAKQYCHLkMZaFz4HB%2B%2FFiBcr9DnFSvJO41ugbZ%2FU4ggst0Te%2FnyvA0BquLifZAyy314XsBn%2FKwl7PwDv23T7CWmdHsjw6twly%2FuzzQYqbUvlYl%2BdCAY8pnL9lKWj6dm4KM2WEbEDu49BawEB%2B7vqYuHb%2F4fcbVH1P4LIdT5e%2Bk%2B7xj8hNy3L%2F7nrmo3huKk%2B4c5eWMHETQK8%2Bj9gpPe%2Fb3Pl%2Fz8ZBfBJfmEBfd3e0GV%2FJJCBX9CujKQYQ3z1k4RM6crax0wimm4IQ%2BPwkPZnvv79yq%2FL8tu46zy0UfC%2BMAWmDFfN7M1HGLcrR8FRSLkOyrA4wcgNtpmM28rarX3SYS%2Fv0CUh1AeaNM2VRVDisSTtB5XjprAxBpRmotgb8iOe5RCv7pEvQOxL76aVP8WxK78f0sPgUAsCilN4483LsA7F4dLF8VExUqJ5UFPLnubjisFUFZePFQOpj4hBURgB8gmkkzfljKFH1NXUarrSqaDNR485ZYxWVAbwiFD283Uro6lnieOwQcnsvhMIDxxYCtDYzG%2FctuakJ8FUunz8WEApd2hvzuWxXeeAMI1Las7AgXrv5SntsW%2BLrTV6u8mvWvwREjWXyrwX45kZjjfP%2BjozspAeOhQ09P47Kc25Yru%2B%2B8v13Qmurt25ffqgX7Tn6rr%2BOcwRrewxWx7vX9mPGew1e9IA6QQR30JbROxw8NXoKT%2B7uQJZm3RyfS6Q3vY%2BNl%2BDNTYpYWsl30gnH%2B%2F2CUkBnt%2BkFPz16CrHGfrclf34iMvtpP7MDdfX%2BFaOaalTdxnU0BrGX2y71q4LITNVm5jHX3w1cXmp%2FvPBVAa8sPCjh57y0Z3xeEzhHd7u7u7vWFIIhHiWGOPcN67DGkryCuXUs2tVYZgvK%2FMpp%2B7kLbMZdv1ZYgheLxOnFs%2Fk%2FUJJkERhVdmO%2B6Stl07tq7y%2BY1SkKFC3cR8k1LaP5HYo1F4k4UGX5DSzoIGZCN%2BQeG%2FSRrHVjQjaIJkN%2B7%2FRekL%2F%2Buu74m7JG%2Ff32Qj77BbqsVlzY0%2BHM2IKH3yITVo29aIkCnit33bl3pzT2IKJfvNB7k%2B07N%2BT76kWusOCbu8rkl%2BsNCA1JqRFqPEuxry1fL6%2FoIdl8tdwQ%2Bx3NZ7ShywWyZ457wzJ7uFLuHOWlQd9KZQdRNy7aRmOEuHtHg7Y1dkQIMl7YaOL%2BfH5bFW3DWXdtabOH7su7vTKQbiGhzkc%2FltssqO9YuvScl5PL9q9S3YaK1SrHvW1%2Fn9onXaJ1fVrl8u0QQiED3e9k177YJQlkvP%2FmNTh6CGLidLPtakhe0FRNKgZkCCodX13xoth73bEMOAAAWfUGaMIwqBXXoTFdNiF%2BIr1aub4%2B7u5qvi1bf13%2F%2F79rXaxfLz%2F367natjFnr9akuvV75AwTLj4Nv2IpB%2F4NI5ZsNhgwSlodOuRFFzfr3gjgg834OlqQvF8Ruga2miBjCPJooqARnWLeVL8oP248o3hx8SMbh3vLcJyXcK8A%2Fgoy36faoLnvfHgOA69Pn4mGWNyEsMoWIQXCR%2Fpu3Qdm7RCAw7BuHTA38RcHpQ%2F25to25JXrv8zITUk9LCzxthlSizXcnrKvV%2B1ixRPyY75ir777Vuia4Rv1qWde1jglY27u8dQMNf50O2VjumMbRRf%2BXxw4cOlAhAuC8yUSctQX6JTrjBSY3sHzBhbZXtoVb6pu0SLuT8HDhQgFwQDZRsvezoI4OwGLGI%2BERbFYrNRdzMo8lPi2VSaYybKqifKTcqJb6oUYSJG1dyjwBXJzjgk7fS3bHTBn885EHHAtvoPIjuMaJC5EXxoHVZo1SLomT9mC5pwtBBmoHBqwIWa2PURqOIr2gA8WfoSm9L1iz4sdsDVt1n2yj%2FQmsM%2BsyDrej%2Bgv7hxtKDsS%2BIKZAkQPGNhINLYr63ywdKcx83LVF7cZPC9q7qhNj9u1ojhDsW%2BUM7zsY%2BDhysYSBxoPf%2FyHSr7hl%2BWfzhMsN2sUQsbwFz47WTKxHBjr4s0E91KhaG8qsuEvZxIgiYZAhEYWOvAH1NAPa8nVPiDXWAtqZ33%2BXEWP1fsGTGl4MAVQHABqbIAYtoESeDm0kNsSE0DvAV1JgdK4OvNsTaO%2FIyWr1Uvd4r%2FWv1r9e%2FXUtq%2F69%2Br%2FEzrfCt23cSwbzS8FC2d%2F9QWGd7u%2B750JkuUNGe%2BK2Id%2F3gQShCNPd72DxsYo93AG39QupSpMxjNOd27b9Np7BNiWZV1Za1XMyT274skMseXC5FZDWCR7awnMYMHB3Qqxzjj%2FWKsNTlJMfDBxsdH3UHT6r5MTIvS%2BLMUbcFZbhI2xcKQ6DiJxnljOPAaHx2XIZfySWw7VVGimg3Jur%2FEcv4nRNDd03lPKTjZknkAlgxMgQYWLja6%2FH3mbfXChI33j2j79OotelCXfpv%2BVb%2BCir36I%2FTRF91a5d5PP%2F773kqYZe9cJuQTRpn%2FfPgmptrqqpB5YIquuJ14k5xQjwDta9Xw06X3axVfS364c61fr1erFWpaTi1l33LffPl8UU4tGArxsBCLS%2BgFHC%2BjjQuR%2FB6oiAbBx9C2A%2FznKkjvY85Uq5EDxi%2FwpAyKVlTe3rmVO%2FuJloMA0v98IuEc0eYJZg3NQoyYAMNTwjEooGB%2F%2BP3afg71XmnFFddVKA8V1YdlsAKK%2FFcwn17w9qIdZ8BBaGLC5s%2F1A%2F3jhgxKNY9WBypCq6A0oJS4RY%2Fql8ci7vz%2FhPECQVUBFeFqiEr0PYF0AYn6Q4BK2kD8gjyDr9WKv9W7r16e1r9XLEclEfr0mSCjjkesLPJbEE9q6UrQRUEjb82Yen8n64XKGB0amOWor%2F5YYMRnGJGMeukzg1sn2HqvwnJeOl90lzqer1bml6Qd%2BiKJr1cJcpihjxlcrfhz5hxs2FcR%2Feao3wNiFVB1Gtj2EAAQAeI8Z86D2nwP8VUTjANZyx4IZrdFAMjaGpymgXG581mIxmjY6X1W3HXoDdb2zllHTVv1Xoe1Ec%2BiL6grhA40yg8FFY0B1%2BLRqPS44Y1IUVTYZf8jsME3DBB0swdWNIbX8Q1Dw09OQg0sOCbgguaeBiovy0H2F3w4XML8s6zRvPsW19kSLX1NzkwnxHPkxLSprD8ONtBVyEW38VnLBQqznz6qirjXWNfJpEleuJ61e79k%2BS6bqku5ZLvL1ziChzLYcaQGvznXFsQ8XICN656t98v2R9hiV7A%2BBBpvHjTK0qPV4nDw1CF5o%3D&media_id=1254206535166763008&segment_index=31" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:32:11 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:32:11 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_D67vLVKLcDBrdt0\/+zwywA==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:11 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786113111947894; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:11 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "b6bec65fa7585c6ee43b82b75e3deb25", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19921", - "x-rate-limit-reset": "1587864356", - "x-response-time": "40", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "00eb298800bc5625", - "x-tsa-request-body-time": "64", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"xwYf7TyiVWODvWVfy1mzcgxFdyQ%3D\"", - "Expect": null - }, - "body": "command=APPEND&media_data=wFfQ052%2BZ6CsMDUnINV2%2F%2FisTjU9%2F7GzG3%2BtA1sOe933MWxshMFGhFZvdMyM%2B%2BHd9TLJAmr%2FQHcV1bV8t%2BcnZjw62kg9IJwWKpFlayF7auawZYpvCo8%2BR234xiUD41SN6KWjrKNJEfvqhvkkl0NXjudPy2P2FgZ2i1PB%2FOW552YKHNIeliDKdv4%2BtuT8Kr8bPQa5qtyPTFjppg5wpsI8SaS0C%2BkUYMBhtMobkoIMxp5V2w3kqB2PUP%2BIuA7EUiffuRVESPIJB3I%2BEMjnvQg9ocvRbuQma8GrG8eb7OTYGQhPfeQg55li66pmjNJ6Xq4o73RHUdfHQ9WGkaPNBz3DRt%2BT7wanrDsaI6DKobUiiPP0nfYlr27oIuYyyf8W9L6vu%2BXl79vtYz9Yr9a%2FUt6F%2Frl2rVh3vDZgUiwQVrq%2FEOAHSX47vBCy9uAQtW%2FaXwqJEFDBMEHZD4%2BECyhCkHVHapMGbhGf5ASsELU4PQ73%2F%2BNnFygrHm1AsSuqGug2IBKbxz68zz4%2BbNAQBPU0%2BS80uXAf7XLz39942fCdpiRV4%2F%2Bo28RJfSV9FO4usf8dzUUF9v3UFdhmozOg%2FHWHAZsbzfGf%2FVXPg8h%2FAVxRwSkWDL%2FfjdRusggOrJJpQhu9X2otcRqmoLK7UnWB8jH5Nbeqfd717%2F8Zvj3M7H9hhD7UKvd7YWrJ235aA3nMZOOAb913iczauVP4cvev6HDOOZPV8lwQVSz9%2BYMwYwgNeEjtx%2BTxcusP2ChCwC8nUL7A2wcIuTAIXtezhPKB6JA1YwlgzlGNxkQ1PhXuGVVqpjSy7waf5Pcu6GsMYAtdJRo3IsTjTptWO%2BRSuEPqitDw1rxha88iDEgygn2FnKfeUYuR3H2e0yCvnfDafZ%2FGlDqf4uvZI5%2FwQu6n%2By%2BrBnLhSMtvpBuLBxYxwOMWG%2F70sKkYmmFPqFdPCL3NDUOynTJtT%2F9e4elL4dtocS2M2SqKEQFpoE3u%2FOYfv3U4qtSXfau77rkkveowOCPL3f3qMCQIrvvvJhBCGN%2FGIQx8QqVcEA0aEaijLguKG7s4gAHDJGKACcxsD6V9neMyrY48oMRhKNsB7yMw%2BRYJPx6HdJ7GxIGgWA%2BK6WSMYOQslVJaV1xfQ1TfT5rEOQ30BpEGBquMokrvq1Qg5zRUoMzVvf44vbIeyYEQdh7QLlnl%2F9xvcLPLrgc3iWQFwBs02wNsbXhg7i0Mxz5IMBf7vfnhpYwtuxWlFjhiYquGbi7tnK2MbjA2AV9G%2F%2FLiixmPh8lxeg4ZogjVz1PgLs8QgZ%2FoZuM2eXoWiI0%2FjcKj7fqP%2F8Ow3DV6j0ykQ2u%2B2G9n%2FhlFT0FNl8LS%2Bmxu4%2FiH3RSKHDyzP%2F8QV3rkx5fveguSOyqB3kzK9Bb4%2B18dTbHGkGURN8%2Flq3jAepjX80GbBlaB9td4882Gumfe%2FEIKwgYu8cuMR9hfuIUDXCrt0iLfdeiXfP5fv8O5qEfqGstssD8chBU3EMXSgTRDHmhFTdgkel9nHPhde%2Bf9q5f38PYDA7W650BbjB3GIGXmbgSSBrWmfasD18FvLNIw6FW%2BNlWIjS8JkWDhV9kPyCWnqR1%2FU9NAOd9Olj7MDiuuzv%2BFeDmJA%2FIKY4D16aHPyzC54fg4ZfTgZvf3HrDKsO%2FVifByE%2F1yq%2FHohXPfxLCIhV3vd9d%2BdfjeER%2BAQypM2BgYqAxQoiMDBL%2BANDnUf3%2FnzcoOsqCkoeqJT9Y1Ph9gbYR%2BNhHgP5YII5ISm9hXgGNaUH1r8tysfEJuDA5bs0YjTZszEL%2FpODAp8yVqT8aWEYIGhRmHkAhXQEQGrniXGmOlRZJl9tHe7I2I5ivShhKJwP%2BtYVhP7t08UUlRg%2FC0D%2BIlbDcvdKrWN6BvOaHQ213eT%2BUsJy6iXuH4%2BMnu%2B8tjhrEqOoRd7v66w51U4qGlZ32i%2B%2FZ0Tt8RRKwOXbXwTFZosPJ%2Ft93x%2FhyWmwUY%2FlDBPt%2FnsMdfLdw1gMHbK53k4Y5aASfz9nP0IuSUPw8eloWevQc5eIYN%2BlWGW61k4YymXCcf6Pu8PhYCWNZMEhCq95QmeZkBR%2FqynyQicMByeTVW0G6J3m7mjjq3RgObfPv%2FuEM7L46%2B3%2FqCax7scZy7p8uxRMlffgf%2FoeuGwJtQSdm7bqw8Ss3x59nMW0DoiHFwIReColVMq1F4Hgpi7EJGvlcL9w8VOPU0qUkSMiIoFDnIJ4UUIgn%2FtUb6qDzhXoqOQ0M4bl9BHvspQ3P4D93yW%2Bu3%2F9tMaH18pQ6QCMvNbp5FeFMavXIXY6WeBwS31wS8atgYC1OdTL%2F9hi%2BbHLWAqAl2CBHsb3yjgSsGXuew7s2EajqMzLzPAkH%2Fofuaqex90%2FUNZGJ950VDoKi2U%2Fe9DK3f5IMCi6ru1y%2FtDa0ytAnuOq8E92Nj8dJhLMHPue30Mxb1kv6GytkDu3Lbd69lGkgox9C9oupzNBFEKzF8T2L4HoaYT1BH8x5NWNpj5I9Rom7DaufG9todURn%2B41rhMJI5NLAsOadce53aBJ3T%2Bkvty5zDSXoi7Q%2BeOCMdy5hyXLdVGTkoJME0NGbWz0YnruJJOnW5Cjard%2BdDhsNUNiT6XoJPqT2cV1sOP5IvX9%2BDB7%2FYd9HxsVZC2Z7zV%2FIbpeGI8FDRnKPEwtpyKmfUk%2Bf%2FXuH%2FVYIXWwyUHyC68cqKtIh4aD%2BUEoBb11v51pfXEpikyDFbNIGb4rZOfepaBAwaTB2G3Pt9zlW9Ty33jsV9XCfxPWi9pzr3BEId3xepCXvf0hLZPXStkDXQJCYBazJn7vxpP91YWJRxgFShqwQrIPgrB4nK1OGCI8v4PoEQMI%2BJBSzl%2BvcPl6OAV6JoQkiQYEzI8Sdxw8EHg2%2FMibMPb0WxRD08ax%2BiAoKrFwOtB4C2K5Uz9WWCfGstQJWxZvN9axi%2Fc6K29qwQEJZLHjB2LHBBZ8uvKFigac%2BELtrBnK0Q%2FsO8VsaGZjCyx4bDl%2BBMmwbD6Eaye7BFuoLalMdalMd7pcvjEVeNLHdI8sEYdxdYf%2BG0T4tBCfzB80HLRB0bPA2lfGZi%2B0DDrJX2RJd%2F7ky%2F8LnwgaxqjAXAkbuIPWAqcNhECeufHST%2FS0XcWHJX%2F4ILx5VgwjQa6i4AzRocib4P4fF2Nuj5%2FAe%2F9XU51Lf8n3f0CAxj2MCTwK%2B3Cp1W%2BQodp888rxte%2BzRc3EibYYZSmYqnwucNiaoHequfeU3U8oHtOv8DA1Tbn%2F1%2BTwISqcbNeIcNDz2bhB8JffLb9lq8TXExN23IGpoDkuyiYKw9739kOR%2Fqe0SfS5Se71RepDqEtXvvR57%2Fty7l7J4vyMbnxdppVSnw8MuOvtDkhK%2BIIyetfIHiVwgLtygMYikYTY%2BbuNUsH1Wg%2FJ0u3pftTv3vjsNe%2BO20buZe8v%2BCORRHoRV25EUbtiSEXDoL2K6JFo3sidrtd2BEh6h2dzCbX%2BT7TtqhxXfy5nxvqnoL4D%2BycaaT%2BDb6%2FXb8zEz5P35MEvpZslgIbzN%2FIGeRAHWpbHwkcqU7i6zS%2FYvggIDO0EJsvU3Ik5HjJ5GQWMV2CMYlsbofsPWiAr1v3e7hIxPGqa%2BRiWyMbXnH0dDcbMA94pzy%2BgQEN3M3%2BzSQgfr5%2F8wphhKs6ggaURPvye7siLjZzTHiuRiduP6e6lGn4RNcB%2FNlGMISBUxC9f%2BgPIVUlrDghFpmXPgP%2FZBsWZ%2Fiisudjgw7n3DgfK9Z%2BAfNbomsxu%2BK2h6fhuH3uR2HQZIHI85GXJD1G0eh%2FOgD4t1rYFlFS%2Bmrbc%2BCIaDm7sVb0M2oXxw1KpbIGlbF1fsgNaE1VHKbj1P%2BZzOxL4%2FSLcj0yR7y%2BlVFMHqzPCF3Rr5vDgyxM%2Bt%2FwSE0xK2jhpZt%2F1tSjbr8JTPBQSv%2FeWcO53Sr95G2rItlSaprTLtrmn1pKH9UBdya2HP7C87mXSfM5rvJVRrxo%2BB0ChTAq9RZx0hWwYo11D06ys11azcKm7u5%2FIvIqs5mfJqfJ6Zbqa%2Bzk%2BvRqBBYLAx5nolMMEZaOLnSzMMRoo2agJih6%2Fl6C2NaBs3aaqg7EY6ebNtXqpPs%2B7wQYBggOZQHVcg%2BSx9s0L8404FRYrWGsVBsMWqScO25W7Z8dfNN9SdCr7Mbf6Bx%2BusNWY2MV6DzD449LFfcXqfG7d%2BaF3e%2FDqPNArsTWNVhG659s2hVrDEEjks1%2BXB6tP3D5ymsN4KoFvdoeuhuF86KXf9HHTZL8tp4wkxNdNEOwuuhLH6nG8SkEuIjFn6j5fnnJcdGxL47S1rjhQkjjyg0DWyOtpMqXbKCtpWHOv5Awj1DCy%2FqiyjbtqMnMPZ4vm7io9MCXPt9hPoN%2Fjlxuan60TGVKyuJKkzv9VZLfEKjvhWFhifyArLKaIQxFpVEX2YHHA6GLrnfQKTGkJkjx5foZ5JxDeCVdv1XmG3BGTeOIGRQV2r3g%2ForZd%2FrAhoF4kFN3HVRpJ3t93yy%2FzsJCQkGJLJuzac%2BLn0pn68yFll4Yn%2B93nunA1BwXW6Bp6RjV4HAGXXq9S1UCMtm%2BV2THmr3vf%2BplxQgoTzyMdE%2F8c5%2F%2FDf0h2ILasWMiB1%2F6DsEbReb9vJmQ4PJNr8FHFwOsJEUnhXeGCkQT4EtnLWskOHE3tzoRMzonlpdBrCJxlLqmIqf10SEQu5s5j%2BVh2tWLpRMgiElkj8HC161JoCXiXVmnYWp0gVESS2totkvfFrvDl46qtXl2U%2BMBh0wnYfbyffUthU8928dz8H5Ul%2BzuEFOghUWXy0ktrAVe5%2BxU9KcxQQZyC1Z53YrQmIReYja%2FaNt0thQxXyuHknQkc9AO1rN%2BoS9WZ2TQC%2FngVZY3QbmV7V9HMntibPQKaPoUkcXrM%2Bthr6D2kAq9aocnmIXi%2B1M84VK%2BohVM6zvNIJM9ZgqV9FqrX%2FBKTAxupPghG5EQ%2FfCrf7svuuYgJaP9U%2BiNm%2FbpiCxrtQV302g6zV9OY2BnqbDdroTCm7vu2PePpg6yTfb7VejmX6YhJxh3teJYUcEgOrAd8pMxkK462uBtCoU31NO%2FpnvqbMLmxLP4e2MvuONS2%2F2rUHb1TCkprKGmhhM%2BeNfdJQ65QR15iysz5buubz%2BXurR6%2BQhj4BR96%2F9BUmxiZafXPSSoq%2Fhy%2FB5f9Iiyfvk4Jjnrx2Ub0KQ7D4L5unQ22mriQYMmlRurFVvXR6%2BOIbhyC%2BocxlfDHLUdK3No2CvpAoJzMXb2fQaLrZOuk6%2F9BUm6fdHF8fG3DY7k9BR3jMEtJI%2Ba6wgzM0frJ9HjjWE4VryMV80e3H4zoGvpv3uxBBHGJS8hFu0I0lRJk%2FSxyWgT0xyrnIjjJKJ2otGGwWaoFbR0HcDrfgTzdzB6vKPfQe6Pb82p8nuyiRZ3mxvQZ98KjQUcxEbaPd8vCAkX4Yyw61%2F1u4Le382RzL86YVCIMCD%2FmsvifQncu7%2BcKe%2F8MjR0nFbZtW8Xsows7KxfVSsJmi9bllpjTR7CBJY1KwOVKzc%2FIFlpCJsOJMjxVfSK366u5LpeX6olfuznw%2BS%2F14MO56Hwflevx6RuuvwUY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8Pw%2FxY%2FhXtFY2POhUfHDVv9a9NfL836v0%3D&media_id=1254206535166763008&segment_index=32" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:32:11 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:32:11 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_sPtkYBQwqr2JsQjNTnco+g==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:11 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786113173181716; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:11 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "bc6ae6c592e5f967e286c387d2af69f5", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19920", - "x-rate-limit-reset": "1587864356", - "x-response-time": "29", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "00b4e86400736033", - "x-tsa-request-body-time": "63", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"u5p0zGnwSZ%2FshDG2EmuOjv7J%2BA4%3D\"", - "Expect": null - }, - "body": "command=APPEND&media_data=X6xSea97uvZLbpMv6%2B9AOS%2FglLn837V61%2Brq8WR6aHecVXgr6bnpQHjgw%2FQOuw1nUa%2FQGxBvL%2FwvutK0xVLzBAH%2F89SWhV%2F7vJ%2F11dcRz1JX5bnIP9fd14ndPpFn8EPYI19XrqS%2Fz1w6nB%2BvHibv3fdn89%2F45dSfsn7%2Fho0s7r7YnrsB%2FBDsilpbL9X4mtU6U5B%2BCTj5cPl%2Bbevwzu1UqQel%2F%2BGhgY7vd7mobnf5EvlLpnyl66b9W72%2Ftb1fvuXxRsex6pXYJCtr4frL89S6wZN%2F%2BsVeuFejayea%2F%2Fo6RV7q35COQkgV%2FcnQf2IKQmVuYlpMH8hBxo9K7cl3IMxdy3a0%2FoER%2BNm7OPasfr0lVYV1d%2BvX4UM7HykEqTcai%2Bot%2BFeisfmvbX6xfq5fny%2FmXJMvlI5yC%2BtQlykF3SMR36ysv6e5C6r9Ecri69FqXLRSp35Mno3Sef0eNDaf%2Frl%2BEi81pb%2FEUhh6e3BuV16678vkJrwqR3uzauxbNf%2FwyTizUcnWmv4kV916EvGT%2FuOe%2F85VvNT%2FqVO42AEqFIhIVgqFhSGBMFQuFgoFQkFxKIQmJQmIQmITrrNPnrmZv29%2BLVHHaXGXRUjW7eRt1cU7vtt3%2FQ7D7ScvRiJLv2%2Fu5gnLja1B%2BtkfXUIdn60rS5%2FknSFI%2B8LpUorxNjab%2Fv6EdX4eEDGovkTPrDjh18jXeNLtT0%2FR4%2FUYVz8YtQBC8oe330%2B5BVuGX1Z4xoZ%2B69n3J3sl3R4cErk7J3gSWU4YQStKIoVWmjUM6NoxBwEsFIgqEioNQuFg0FBKIgqEQqFwqExCEwiEgitO%2Bqnzet53%2BP26tKnn5q%2BtZlXRWqF6Hf2NXZyx8Oz9Hl%2F0ryZ%2B6%2FeRbYkufC%2FlOl7yoPd7G9LzlNHugPLUv9x14rD9DET9%2F3N2LZXtLJxe1SaSGA8tKspfOO3SCMwEp1P0gOZfKLpZnluFIxJQk6BBWwUTIxFFZrAIVqQCN0wcASoUiEoSGoSCg1C4ZCgTCoTGQVC4VCMWTd1687nfPn7a83SX4qddZzLpWaXVTgZOHBk3uOz28Hseum23%2BfmuVYfOcdPlPsIeW18%2B%2FRn4wS1gX9Nit3qQvy8ZuwHp5gx7GncqP9F886UhMIEKzQQsDBQWuvOwIJG3GCpSYRha5EMkQFC64UKrA4ABLhSIahQJBQJBUKCYKhkLBcKhQKiIKBcKhMIiMQjMIhMImKu32%2BPV778%2FNy7kbXesqcbpXGUl6GTJ6dLy8vFfLpeWe4iac%2BqWvfP5DVrqHendyJelf%2BWj9w0eoKraVfbsgDP58ERPwdGbCU9HvyXUlneTRELy1fR6s5cfuBWk0l9cCFCmfCJu6R0dMxM0hX9waE0gYJLFkQbUFAL0lJQOIDgBJhSISBISBUJDMLhYNBQLhUKBMSBUKCMQhIItc68cX9utzfjXcmtTJvNdXvL4qs31rcT4GbX3fRz7Q6%2Bnx3eSomfbSUNwPUDQeq%2Ba%2Bh2jg6FdsT5TxP8C0PruTOFR5zu6T2eSaQ9fWdkd%2BXdNh1tp%2BGKRBJ7Kufa%2FlcWORjbYWIDbgFZiNd8FvZyLGgEYRTv2ICiCNIBVITggqIr1RBwBLhSUKBIShQKhQRBULhUMBYLhYKhQJhQThUJBMQhMIiUJjEpha74me%2F17ze%2BO6nEic1PN73riu5nmpUfAcPB6tDn4zq511Oj%2BhVTj31dzgDtprrH8lv7RQqWhc4j8C%2FT7N%2Fvl%2BD9ePsBan839vJLG%2Bxl1Jz3kRvBJfDIvC%2BYn1sE9yT%2F8834t7oUaRav5kG6g3oa0XwD2%2F7sWkaPwuo5Cx41RVK01I2E4NNxawoXKwC0ojvAOASgUlCgyCoUGwVC4SC4UC4UCoUEoUC4UCYRCYSCYREYxOZuX7%2FXvuc%2FX7W85POeF%2BZzV8V61XQPYOHp9z6PS7uLeHzQd%2F7l4PE2o93%2FHa%2BsbH%2BBBt%2FDnO4%2BJXL1eguBPAj2UQ8X4lrhu019E8phXjyWhsWVeUn8uDmHUpDvsvHIFHKgEHeQ44Txu6feGOKxZoeQCCojWgVknUTTgXVJJhKVQgggDgAAABetBmjIMigV%2FoXFXS%2FKGa%2B%2FXv179a7Xq9ev1b9eu5bknXu1aovvte6lb9e67ql9eiOReqq%2FVMvnlGfQTREs%2FKQblem6Req0XOyef%2Brdat%2Bvu67Vupe%2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LmJaXPNcTVXqitXrFinr0SqurkuX0XU3rKtH8Ry%2F%2BGpM1L%2FQiqgBKBSQJFUJBUbhILhYLhUKBYLhUKBUKBUJkEJiUQnOfr3339d%2BL58%2FOpeVxrxWuJm79u9q8oldDw%2FT21afN25OZ5fkuld1oeVd%2F%2FUj5Tez2ob%2FtOA%2F8p30RUU%2Fj2scvaOPGVD6O%2BCfr0qEeFL%2B0MUrgG9l%2BB4gn9u3i1ZJx3XgfnPk%2FGaaZEk33MDvcMTgr1lZd0359sapQ1qHPlpXrzVgCgcFIQiCKsSt4yAnOQ3ogwgOAR4UiKgVCgmC4WCgYCwnCwUCYVCgXCozCohCYVCgVCJ3rbrffmvfM9vzPjmnEytSbzXnxW30KvoeujNu8u2cNH%2BXHL2jECy1cBTB%2B0Cu%2Bx%2FZ%2FgpX9wkqLZA3fC6PzXH%2FszuuaZ0tU8S77XilYTHUX5STAZ0c3ZzAL4ntGbAheoNYZcufu2LgTBcwll%2B4%2FMziM8fC91zKgR1Rs2b84e8ZO7PV3AAkvUrBYSLQAMFprTCc0AisDgEoFJQkFQkNREFguJQ0GAoFQuFBKFAqQwqIQmJRCd3eJ443fqvPy%2B%2FbPasycTKr28VWr1kToOGfqadPk6elyq4e0ZL8XbXmwFn4whLb%2Fi4xB9IuLxvv%2Fr9vLOr%2BLQbr1jhozb%2FovQ99O%2BWvYMg7tnN0%2FABFbbQene65GoNr5UXyDgOJNaIkdx%2BV34GbF4vsA2PHqbHdonh46XExIDPUKk4JEyFwkoUljCggTgL2BwE0FIiKFBqFguJAwFwyFQsFBuJRiEgqEQmFQmFRCZ1O%2Bt91Ovy49PjJk1znTjmpxzkrjSk8jZt0bHV6fEd461vZ7ScVe4k1%2FA3%2BEGDibn1vUYbux1AgT5WAdHXh%2FpvZq5O9RGPXHzPOor185S8usYBvtvkjgsEPf1ZMGReeN1Sz9GMhwESEOlFT7js4e4ova41Y7ibcT8Z%2FFanHwXWPaAHX4AAvBRWZEvFEndWBEmouaAvYDgEmFJAkJRIFQoNxIGgwFwmFwsFQuGQuJQiExiEwqIwqETPFamd6nfM1735velctX1vbjea51ZqvI8bz7uh2PEeHYeD4%2FtIuXhxHzRL9IFEyIf0%2FID9CF9rpIQns5%2BAjyTkKxMlenYJHwpmzj%2B0AKxz4Gl8np7jW%2BDVqkuX72f73Naawz7Ekz%2F%2Bb0tMoVCIyPjAFZjxCD2ffn9xgO7xgCBVQYUFVAXTiJlaISnQgfmA4ASQUiEoiCgVEQWC4WFAWDIUCw1DAXCoUCoiCYVCYUCYVEJnvxknv5c8td%2Be%2BJCt6msyXteavF1wM%2F0dXJk3J8fFvt9H3KzIX8bDPlaL1X0fb%2Brv%2Be%2BShX9eEoRPn1MITNIwJHL98ZEEB4Fidneablfparc6%2FD%2FWBiod2d%2FV2UhNc5Cv87oOPXRuSJ%2B9PiU9PAHE2qVm6H1v2ZPDKov3%2B50q9VdB49J%2BJvhXsO3KuQBz9fVAAIWWzhfyTEhCk0SPMUgTXbdgOASQUkCQVCgSCYWCgoC4kDIYCwVCwUEwlCgVEQUCoTCoUCYVEJnrz68z7e3e6r4%2B13Eq8iaykZK1ZJY7f6vDq%2F3%2BZPd%2Fs1kHU%2FgEHceev%2Bxj%2BzbSI0tN%2FFAXHl0iBXN%2Bv6fZ2BMN8Xz8FEDPWxiJSfcujHIH5l%2BVW7bosrjdWVhC3rIO5Q24OUuv2y59%2FKpbjQHsLzg72wTWtJG%2FuMq6ZI3WeJfuh7B3PNfYWVwAW3%2FIBBAlTCRleYrMmVLyCJKJBCoHAAAADt0GaNA0KBX2hOU3r3698103Ovf%2BssE%2Fqtj9Zf9F9Ivf%2F9q%2F%2FS%2FEK52rn%2Fuiudd%2BiN3Ja%2Bq69erJ6eW1ccIVg4IfCFUpX0O7fa5fNVyXfN%2BtV6s%2FVyT11W6vL6uZP39a90CSf8EcZEX8Ha5fq39Du1bPXr0k6%2FqWM9bT%2BqQHKrd2KV1I%2FffVPzdXd%2Brn69fSwip1dN56jTWP%2BTWI5V74uvU1%2BuV%2Bp0ye%2F%2FL69drlfr1erD5b6Xi79Yv%2B6ov9XSL%2BrWK9Vq7x3w%2Blb9cq9e7V5PWvyn43qfLq%2Fiax2vRnO%2FCFXPnrmvCO7l9Yq9bBe84IAy39xocvzWsq9avl5nXKT1sluI9X%2FWL8MTw9Y6ZrTLcXr3TsDX7noQll8ElJ9qt0DSrtddyWvd7P77Wu1f1VqJ%2Bf1VE161V165fm45MM%2Fx%2B2yGn%2BwTJeMWgNWk%2F%2BMl3pNsSsW5r8i9A%2Fqxfnr46mPry06dX%2BuvzeVQ4hf1qrXu%2B%2Bv1Xq9ak8Edd7lvr%2FXD8u9%2ForknojHeT6%2F3e%2F4mc6j3vXq4%2Bc%3D&media_id=1254206535166763008&segment_index=33" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:32:12 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:32:12 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_LeknfK9dQwZSovacV8++5A==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:12 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786113236480030; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:12 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "60d3866bcb46b8e22ecc495dc593a980", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19919", - "x-rate-limit-reset": "1587864356", - "x-response-time": "34", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "00dc5a2200042a35", - "x-tsa-request-body-time": "101", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"joWsCAjLP4KAy3o7y5hTgsRIvXY%3D\"", - "Expect": null - }, - "body": "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" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:32:13 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:32:13 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_sPZseav4pgpuY36mSmyWmg==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:13 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786113300928181; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:13 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "41fb9c88dcebd7dbf17116c5d943f468", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19918", - "x-rate-limit-reset": "1587864356", - "x-response-time": "31", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "005f7d3d00262995", - "x-tsa-request-body-time": "96", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"1k4bVPzPmjF9bEiiMhNM91kel38%3D\"", - "Expect": null - }, - "body": "command=APPEND&media_data=FrzIUEA35hfUKG5UuITZqR3xIfoa2io2qxvVUiDfcYcqMY80m%2BNtwxl4E4ZEMYLqoT88Tn5lU%2BN1i%2FhSacUO4uiXCmtCE7dxEAkuOBIx3JRJZjO1%2FTIXYfx6Q9X5h6PaL%2FZJTXAO7sHAe8eCB7Ra57wgbJnAASzUlCgVCglCwYCgmDAmFAUFAUCQVCQTCRFCIVDAUCwUCJmuZe%2Fdrjut%2Bd5d5fUUiuePCk81aaDlx92aH3p2v%2F%2FTPfTtdyDwsyio3j1LGLFCvYVqZdqN5LUaS%2BLcj8TRJgovZ0AV5IrhrTnHvQRNNW6bz3NxhstuUg1HMhcrFxjrIeB%2BFXtvJZS%2BXB2e8IbPWAzj6e3%2B3h80hskm0wCsO2pAcqFbu9Ia2%2BtWfdpVRVzFagjXbhIJADjfo%2FNX7S316KxoSj5yTLoqDHXkL4JQUikinPBAHAEmFJCqFgwEwsVAsJAwJBKFBkFBqFgoFgqETJ3Uv1nxW78WNcz2zWF8tbzLaXU0OIaM5ztGt3Zf3w9D%2FAO8F9XGxN6f5ZZgWiPz9e%2BxJw%2FmfhjdH03%2F2NBadVbilmAlxGFdIEEsNg8hHcb8WNukqnbhD%2Ffh4SsXB2u4nprkT2yc8Gd0vld7xGrmpa8kGyt2ZoMfgFcC%2FLv35e%2BKzJ7pkO4PucyAeKBF2fyW569Rv7ltSDNQD9fwp2AQAHPp7fYOjle1cUbI2qtc4y%2Bys4L3%2BtJ27x4HjZSpk8sAcAEkVJDQJBuFiIFgoFgoMgoIwqFAqJBqETPF1Un6ddcszUrWSGrqbXukaqSWOIcm1RyTl%2F7eX2elzP%2F3%2B30d9kVq%2FZ9Me%2F9vLH1fcM1i601f1zTwP2DXHLNi%2FkPtGhBXs%2B%2BAObaoNoPI0nL1blHd%2BX%2BYTJaz2HSncYXf8cNlq2aukS4rVxYm%2FKYvwuAoral93qoUS52zyqo6eRVqPL%2FIXm9gLszIADOJxt1NrDRfQndReYmzvm%2FmzKM%2FASZYxqw4BjKNeW%2BAWaoaSXOoOAEomf6MGjBoynLFSZUtyEutOABq4f20baeSgkOvkHTiTT1dt%2F38bHP1M6xt7MnIlfoKNoB0gM%2Bm3qYzFYGfG5XC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%2B3dL2IrWUsbR2NetvJ6%2F5tu8nz6qabNBZd%2BsR61VCPTRcoS3j%2BUE2a6j2VMp2w%2Fd%2FhZiDF4EAYzqnmW444QaNfsFRGPDsWB0Y0DhQGTYT%2FXY2HRcZhBA3Mv6wwjnbcowWGAHD%2F3rzBgN0gwaDPD%2B7OPv%2Fq%2B3wT00uAx5E%2F5qCiIzsIEdyqNl6f4bkRhlNT4R7vlUe4%2FT7lhx7b%2Fxfk%2BMyvYSLHLjO8uJSfT%2FIsHqKJnwnp0361N69dxGoKNhB5uF8t3XAhd9z4IM%2FPC46cLUmfuW1nZeTVTRfXYIsMCugvbvsv7%2BbjAyewRz58tO25fL68VkN4PWrwe1zYKMS1vXczFhJSeS%2Fgi4%2BJw4Yv9alf3fd%2Fkj%2Bi%2BlLexdevSXN6L1ehGW%2BupRpSibEKOgqH%2ByZkanyghyhlylYt3AY5ZPy1QLVEpIf2%2BCmN9gVats90esWITMLD2FcJlq1BJMGwtxBFzIKSXZcXPCnfs3NDJ%2Bf4IdZMy0r9RLmLk7c9V6%2FKXgn8dMuoq9%2BaWrwUZ2zqc4yPDs78EPGdNFzk8vlz8vnhGyRkwluEeuriSef9gnNLtDcCM1p7eAUuxHp5GWhkER%2B9uubBJl%2B%2FKbnkvwl5KhNi4b%2F1TLX2cqyvjxv%2FYTob%2B77BIYGamKFJn36F9yiDVwPfobT%2FnrkGCWv7JGYz%2BwSbIhj9EevV69LcqW%2Fe3Q6mwwKNO%2F4yMnAHYGDEubvBXKyHoBCHhCw1YpGOunA4T7K4uzkX4al2PZuU%2Bq917W9GLxmbr0woaq83n9O9lYhp2K%2B7BHMx04NcrWT6fhKLIIjp6NjAQHx3D%2Fx0ZEqJD%2BsZHyOFOAv32IO5UnlMXvdQjwk4ddODGHEn9gawXWs%2BT6f8SIh5WUzsAPuTOEUZB7FCT4j3DTvNxyrwTkCLBezmdROouCXVxD9aupewrhCWFIl1sgInzAs09rlSzCf5S5PHwVfljtnIuWtfoZonDsXGo96RydgjhkdZ71agn3MSKIMOmNuO4JSqxAd%2F4YibPZ2C7kZGQLPjqB34Ia68%2B6kwWEQZo2BwyvoGzb8d5217QLoR2Uxnu%2FDwakxUPtr4RJy0zfJLv8E3jgiJTCQ%2FZPt%2FceUdChpXDyZqA8GJmB0wb4dI9Root3Cl4gM1YoHODcmZBvZZo%2FW5LGVUmOqOFn7J4%2FuvbvBLM6yYysTL%2FzxDYIezMfcfKcn0A16N0mIyei1Jrbd9vQokuc6SyqpQh2SnDAlNOXq21fHzZ8JVtFqJfmT7s1PuXBJXSbJ7f0XJ2nNSU8drB2YcrqXvf%2FYe83AvjLrGRWLTNCKZ3Nn3zL1ehLCx1MTHzipp3BVOYothkhZXse%2BSUakCHA2pF8QSg5OzyHl%2Fh6maBdwRTbJ7nZdymPR0JLjNI4OInU7fEkwvuY1kmZPTG72rlLMbf%2BrKou9VLT%2BEzY6QsYLOgvdtgk4dZu5atIO3z%2FzeZhvg%2FHL7cLKFim%2B3L8ahCyZji%2FUWk9cv5u69%2BVe72%2BrHr%2BjRaldC4svqu%2FZ65Nb%2BT79XIYgYGUQEdInd5DGe5X9XS1n34LM3m9mUx49Tu16hM8bsZ3v6RLnx%2F6s1alM7dSXJaPK%2FIax8ZP8JTUQNk1R3k9%2FfVmX93XlFXY3uT6su3b2Cgq125%2BUuwlvcOVOR9adxBHOY770t0EsmyqGUn1vhDnXn7uK3sq9cMvr%2Fr1BL3PzMY0WXu6V68J%2BXGr3928nk%2F0d3emurWKS572795PL32Zcv%2FetOX%2B%2FRT0l36LlEXJfyV6I1F8bX7te7RUo%2BT43he%2FRHH0WKvUoJuJvwSXflfkFPvAAAAzFBmjmOagV3f7Eu%2FXzL13fq5LxSvJ6vUvh7%2F%2F%2F3%2F%2F1f99%2Fq77VyrkELfqYH61W1Vq1XT43U1%2Btdqw%2BsMy%2F%2F5PcEPV1yonlX%2FBvNAp3aLFNxNbE16Jr4lWJfJz5%2BtVb8YjMuX9X%2FdWPc9ZIkIYP%2FHK%2Fdc0w756ur5ZPWqvL9fyerzeiXqxB0EM5bqabXYZmwu9Sq1Ef%2Fk8f%2B8fVi%2FWu1ruxz2l9e7ifWL4lXiLt7hP7NitRXE9%2FrB%2BsH6naXde91ik9ZfEq8nE%2FE3a4Uv%2FYib1iriVftXLu%2FVyS7lXrdr%2BUkeFn99r1deGcvEczd99ovSesX61fEr1Rcg7cqfl8eGg%2FcPdz7BP2SVFYycTVz3d1pRxf%2Fmr1gvxXZukk9LfrD%2F3rQirivRXSeesaZp%2F%2FMRu%2BX%2FrPVBDVuf%2BeqGXQtwhzxGxrIJPXl%2FJVtF%2BOv4JNqRQwfgjMnHUHK%2FRTlJRPzyXfa9fOvV6%2BJfBN4zOUakY6vzU0kAf1%2BO6u19728ljgo0mH65fhK%2BG23s38omgZs7e%2F1c3rnuPhmLP%2BS%2BJjZZfROk9CdV5DZPJ5e7%2FWqXr%2BtanX9Yrj5L7vdF6XpcpPKTmUfLRSqq8%2BLTHjQ4voxo0PzXf%2BbKpfXnIpPZL%2B0L6vKZzL68ksOtS8vu5dkkya1V0vmuz%2Fvm7bu%2FP1%2BOaPr0Kqpfw4PTOXQFr6GVKuTzkX7KPmxv%2BsMub1q%2FLd%2FrJ6wV4I%2BxnSa%2FDeOg5dS3r%2B%2F1yy%2F%2BqL1etfiSTt%2BaPyZfrxUkQiYOIyaEEuRonXisdECwCnfOv9a%2FNSu6L9%2F1EP1r1Cvvwr%2FRZVcut%2BQjsBOgP7sp%2Fklkgrn8ORuTrqo8mP69FSJeCUiAUNw0NNr6nWZiX6xS%2BTd79Hxt%2BO16v4n4nL65cuneTzkX0OG7l%2F1cE9WV5jap%2FQuY5fUJd23ayLxW%2FBIbmk1eY56%2Fen%2F17%2FyV1Jfat2vfrUnkJdP89fngZVAGvDN73fHhed36JKLuvBCW68PVX%2FNVdWrl3P6K1KXn9xynb%2FJy0%2Fdb%2BI9r3y%2Fr0R5TZdr69HYyfP%2FL6Jr9F6rVyrv33dO%2F9FTtc0mK1dQihEv0U9JATCZ%2Fow6MJkpQmUqrqWuWAp2%2B3gHtYVBgHaRaapHdmvEFw8UDWqmJ1%2BLV9Si3pC8M%2FLtMzbETrQuok5dE9ayhbb9lmd3qtLoX5m8uWpmROYmIzDCayeKOEjNkJJ2BwOZGToX455wc%2BNO%2FSg2imxbQSqbabqQgncscIwpF660pQ2uTNNSCbDAZQgQgsmkktSKV7qSCcgw6FBmp6gYQChGSq07hHjM9eZS2DU%2BgiSloKuGafgYOZ6GnYAluA%2BQRxmohFRCersYT84VFe%2Fa9V1dsxDr5QRSOdLZlZY26OihpW10dl9pPFk9nTu4cY0Yn3fgMNTgxHZxNbCcATLUjCoWCgmIgWHAWGgWOhRCoTEJ2dzW3Px66re9XkvKtCGm5XTJdcD8x5OT%2FH9L%2B5NN2v4%2B23%2Bp1Hd3cZNxZ%2FnzhB6G6fp7P5kKU%2B2a6zhxL6r%2BIbdxaqGwbU4SdKAt4z4Ci7CJQkkforTfQZmvC1LnHnjaUySGDBIUK1VDbnN2HBfAwsL6Nolfk2mdB1nimpdVVwow4VanvsxZ1jV32GaJXPf8rRF6N4mjL%2BZ%2FU%2FaKkZIIXnCwlgMf4SupyI3leM6ikok42I5K3BwBMBSYSBYbhgKBYMCYMBYMBZCFUSBMKBERBEjm8453Xnma5iYkmXKlJqqVpCaB601%2F1nQ0a8N8dyT53%2Ft9zG5nqRgGzPtJX4aIgMs%2F%2FSLCH8US7dtVreWNOOi%2F1XpdrxwTc6E0%2FZodaLe15KXve%2Fck7xfMIV9YEOpwUN0r1BUHWd%2FF%2BroRZfi9zonQ9HsUFRjjvZQ4ZdTVO3VWojMVF%2BUrsZUrdcmRITS83LD3e3%2BOJas4R%2FcNUtYdONeBSWDpa8lp5l1SkpLthtFnrE0VzTjvy68LrH61uDgBGBSYKBYKhYUDQLhYMDYSBYMBYKDYJBQSiQSiE7%2BnmZXPf7%2BFz51KlpkRM1MqLC%2BhVt%2F%2Bege1yPeiXk9W214tct%2B7ufq7%2BGps8TT%2Flm1LovMCBq%2BumJ9dehfxH5ebCa63fo0XlPluBW7s%2F%2FloLai3C8qHad%2BCX%2BSFgL1zEJhObKIffL9OA5TJ343XOj2OPTS9Vd%2BORXTNIuwvSfmuEzTywxq4%2BAX8phV3Gp3aSDY7jp1uUcOJVDJm%2BSbjCLpCi94mCrNh0FOk1tdBmnK6vKv6YIWEOFwcASIUlCgWCgmFIWCoWCgWFAUEwoCg2Cg1CwVEwUEoSEJHNUeK6VJuuFK1V5dEVVOFLrgPPQPGb5T%2Fso3N%2Fn5GZPU96R68dq%2Fmclr%2Bv%2FXktuueQZN8d49pu2KdkxD%2BiNu%2F0GCFLN4av1EX%2F2m%2Fld36YH9pXUyHAJNt0RprHuq%2FBiiVG5oA8gUHY8rR3e2tanuMMwPXoqNJqEQDMlC0%2FC%2BvptDcpb3rm5FCgDGBnCw1E9t4HYvjwv9xod0%2FX3o%2BE8nozOdR6euYZwEQo%2FWXeMBA9Wa5hg2XpgK8Y6NcZmPReKRw9swcASYUkEwUHQZCwkCwoCwUEwnCgWCoUIoUCoWCgmCoRGQTCIXi3GPt1FFcbuVJUomTKXIidD5n9Io2fi%2FoP5M3vnwMU6KNvMf1uTZ2xQX1riZyj93jInAbb9z%2BcR20HWM1bUh%2B%2Fy605tR1l90C3f3KQS%2B9edL5Xknt%2B06skLRff%2F2yDFBsAAN93iDEz8T8L3cUTuul0dJoP68gDd9eWtKc9r6OrxZlcSW0yFtMAhS6t5d9r4XT8fq15tfzj%2F%2Bc%2B7B5v1lHsCYKd1942oAi8HHr5SRmyKZ4s3a8a9d3wxKM%2B%2BkF8pCSTathP2NO%2FXqzy%2B0DgAEqFJhoExQGQsJAsGAsZwolgoFgoMhiIwudVHx%2FT2qpVSRMuVe7qsulNSpHkHut7PW%2FwL%2BB%2FET%2Ft%2BRRtHr%2Fg%2FBFafvEnmA5F9L3%2F1r5bW4%2BRLarGtLWMsv4Vvj7LS3Gj%2BXY%2BwJtO2ekwL1NyRXzX39NFDv3yHnaXobm2CBScdL6RHZJeReEjnOc%2FfZfA0j%2FOtuY2sFgjcoVc2WWqxoXRm6ds%2F%2FLTnPSgN%2BK1C%2B03SHhTWnNDiPT2vXxMB%2Bq%2FU0HH1eGWkU8ZXAmbiHA9NaKFwA8TK1FFWkR71eKlXb8VaaDPk%2BaBwAABBZBmjoOigVxdoT1%2BvVclr1evfrKT16vVu11Sa0WY8D0CLv4JVOn6J3f69Qhe66Xv1i7%2FXu16sv9erVfH69y0T%2B%2F7uhy%2BrdexS%2Fr14Pa%2B%2FVsdl7J%2BJVna%2FD9dfLfE%2FqyT33cl9rysgpXXq2K8ct%2BrJ7%2F6tfE%2FLLfVFX3%2Buv1y8lFq%2FRHO6vv9esUv6ufr3%2FtXS16%2Bmut1b9e7V1eQiyM%2BquF6OW7VKBL%2BIr1aX1y9Hq%2B%2B1qafl%2FXpPX2T3%2FWXtWKtaqdel9Xfr6T1qT11V363%2FWVRP61IuTr1qWJVq5qtXr1i6K%2FWCS5LWLu%2FWNfhslNDdZ41%2F6yt%2Br8foIhHtfFX%2BvVLE2rS%2BCTusW%2FU28N1tep0r0XV%2BQmOpjL69d1P83XxK98svr0%2Fgkj4gPAL34m0kwNAO9P4I5WP1eYvPla4c0OVLJx41Y9v1y%2F%2Bv5M6jvXcblXXN69NnrX6xyvXKvBJdvcl8WRE9AcwYaluvFY0tq8Qr2Pr%2Bi9IrxF6XDyEd076x%2Fu7v16vWq4ubzGhPyj57%2BPsAxiDzw0AzwQeZQdD828OJML2J2nfkFbuvRa1a1692cvf44vy3svw3Y%3D&media_id=1254206535166763008&segment_index=35" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:32:13 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:32:13 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_aJQMklx7Tiw90ID5EjVhWw==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:13 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786113365613628; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:13 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "dd58c9d151e4bbc61166b1ef80ed86fb", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19917", - "x-rate-limit-reset": "1587864356", - "x-response-time": "34", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "008a6f770012022e", - "x-tsa-request-body-time": "101", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"PvsKYgEj6JMj%2Fxpadfwg2JaitDc%3D\"", - "Expect": null - }, - "body": "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Pb%2BB6Ht5QsvxtMbba5PE%2BXeauiZfFg1H8fTh3ENKg8%2Fh8%2F5l6Zkgjm4JonSng8ZNOpF9kGbUmKUyoZSyQeeOvHSBjSKvUAwl4T2eUFxV%2F46fjqyKUD5npnrAy%2F5m2eX8sJjfuCR1uGkJqEdNP6lE9R58fL33LDhXCco1zSrVBajNli1N2KXiVax1yJS1UtYNGt7zo8k39TGwOAASoUjCgWEgmDQWLAmEoWEhSCgmChFCISCITCIjC3vrPjv56JvWStc3cKvCqJqFPYfnv6nNv8Lv0WuT8pPIKtms3s8YSiT1WbqPlnARfzAtvT76Y%2BD0Z48vq6SLBym7LHDPhl%2FZ5iCd2jRh%2BurhUMg5Dt1AHDw%2FyOpqK7fnh%2BDbaeVhq7qanYUskekB5i4b0sOGmMT6obYU3p%2FgfGz%2Fd7B%2BnsFcxw1MWcX0X9%2BaeMKA71zRvoRuHfp2YrqUqi0%2BUrb4i2JrDTBaUaRrWvsFMbj254ONeM12%2BCmmbL%2FWPFBwEuFJhIFQoFgwJgmFhQFgwJhQFhIVgmFQoNgqEQmEgiRuus1nv9czxaa5SusTXHO5fKr1BfAHr8I%2Fpv0tKppI0uqzfdL%2FCwx7v2%2BdHZ%2FbA9wlN5PF5CWhX30DGn%2B%2Bdn9%2BPO2upqDC9pjbsfDJ5QF8uc3xPV7%2FU%2F9nFgnhJ%2Fd2H9IDcL1cSVBsz17niZWwxsTBeQb%2FkDQ9v%2FD%2Fd%2FzOni6tTwSr116xAZnPZy1fVcJ38NGt0jb%2FSdl5bWcCmvDB6b6tVDVAXz4c%2BCkU4%2FXGS37%2F%2Be9N%2B7RJwbGqSCVmOClFHypcK0rxrCpbfRQ8umYOABKhSULCQbGgTCgaBULBQShQKiQJBQKhQYhUIkd3rnXO11tMkkkLuNmTL4pUdB799fOP%2Fno%2FTy8NdvttLla3w09wfDyp0foaS2Garf2e3bX%2FzTejS0CX46AZBYdOoEIkvk3mbeh7ejifv%2B41BA9tyDzUCB%2FsG73rfXwIiaVCM8alk1It2p%2BvrzZWCforvZUPXc1lJm3ChO%2BfsP5RMnFbjVsuLW16eHRVwuCJDlnI6yTBzO7rW%2FzlqPs5JYHge%2FT7zIyKbQ4QtaFosx9541Rh59tFciUmNpBwEwVJDuFhIFhQFhUGwwFAsQhoEwqEgoFRCdaTOe64psrz3NSoec3WqqpdSpOBw2vNFeD4mvPzT32fr705l%2FnaPiO%2BXr1q3TwKflyl7NOq5bQR27f4Lkgi4r14qlwkaS2%2FqyApi66cK%2Bc4AWycLoC1RM16wFiq7vvEzSc0hfRbk2RijYnsRmHGxD4lfeff0FW2PLlZoq0wpH0tfN4Wxq2hd66lv2RNW7WyjpFCe454aFzZ5HgqoJepzicU6WWS6XlERSTkQ1zBwBJpn%2BFSgs3RFS3zfGlZXGgCyFIdqgeI%2BUAbkx8vd2mjO%2FqsrIBQnFNtY0tH0EbipPDRZpJb4055hwTHvXLANAc1RZWTO8r9IdKC3B8NIOIvOPIVJM%2B5FbFTA%2BWmZ2O4%2B2QnrOct5MMxoOy65SS3xBl4gBzCjISNbALmoRWiQRXEPIzNpASkxI0BDNbrIBjaMblnM1E3tpnNzDFWc4b5bUYxt6%2FTyzx4PB%2B1cRW%2FwpzDAFoFWCBfibM8z%2Fv73RrLLuNHbhbtlqYEWLBiRR9mLHjGz6YpwigNRIKATcAUBN2D28tgxdA4ABJpn9zBowWcFjJUmW93rTdVOg%2BrPFrsI8a%2BI8LP13dx7tppFknqZMiJ8Elp15LzAD1BJ5st50Y82N7MTphIDie0JdYlWo%2Bgn2iFaeoUcieAfUbn0H7asi6%2BYVcKza0acsKFhab7%2Bkozu8pFAOgCSIY1rj6PIDRE6piEKRNKRGzjGYayFn1VSNpRBSIDHVILOdJ8YgEucDvACQWVnL3cYwT%2FNc546kCiZsaL6UEogSE%2BQihmvS4yXnJV%2F6Dp9DK8fWemxwnZrbYg14CsZAgA0aqePp93x%2FR29np69fH9CJqoMBcTrIXchz%2FQH%2F8Lxz7F4p6lQ2hs4yuE4AAARkQZo8DwoFfaEvfrF%2BrlWuv17url9YpLXv1ftSg7%2FWv1I36xdqS7Xu64%2F2%2F0XvCVcmX1clqon5%2F%2FonTevX6lSnpat2rjff56%2FjaD3ilf65fr1z1nGUElr%2Byx2lKe%2F1KORJP3%2FeNm%2F%2FJba36udhucxf3Poowk%2Bz8v53tri4qpWdrXXXrquou57UqSv%2F9EerR9frFy%2Fa2C9dSX2sOT1S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" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:32:14 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:32:14 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_RJ1HqzciWxnQE3UVX\/qwlg==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:14 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786113431585987; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:14 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "b42018183e0f571868fea227c91736a0", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19916", - "x-rate-limit-reset": "1587864356", - "x-response-time": "32", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "00a68c7200021694", - "x-tsa-request-body-time": "97", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"bim5zzZc2t84q%2B9ZHIw5FcEpz6I%3D\"", - "Expect": null - }, - "body": "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BFh5fVn6F1F3Xo3frUgrrJ9b9atPgkJHjh4pfDZ1nnX5hcfF3ksu3MlfjDUU0BiT48Y2pbuwDk%2Bf%2B9uSE5fR%2BvxddLNRpX3fhmxPOwpWA8l%2FSq1oh%2F3q%2F8tp9esvxe7%2BVg3j45E3NEMhBa%2BJHQ4BcGmCn9EYLz1%2BPJj%2FVj9CcqxH9GbvxNe8V%2FVy7lvJ5b%2FfgktY2D5lV6F6sl9%2Bzb3d%2Frr9XDvuvEXPTfdbq%2BotUXzVEqXe43yCBscmpMfybI5bq5PQl5PLd%2Fcl99q%2Fr38X0q1%2BvXa9forS%2Bcyjp9C2v%2BevzjkdNt3q9N8Elt%2FDuL8l3%2Fl7uS5qpLl8K72Z8wFXyJWV14ujo0r2fz3%2FDVjayeiuSYispfBCYv%2Ftb9euVf8uKfFISn1Vu59VqvXCW1wiMRrEZYABKNSQTBQThYkDYLhgNCULhYLhgKhYKDYKDYRBEJDEJhXW3Ob%2Bt7q6qb4q5l65u8zrkzgy70OKfsd9XR9Aux9N3n%2BGrpT%2Bu9RIgfiWWs%2FEp%2FiXur1e98KDWtJcfKkuZ8phLsKAXuX1Po46fDU7b6Ta6idHz%2FUVG6YOo%2BMKjB8zhm1RkQPU6UT1B6grXJGK9m6zoJtByHvnG7ZrtGRIQa6HXWx9xHPlZO2miTGOL%2BHc%2FHQrUX%2FMM7yucRMytE3RoBNFOweBoqO97E4my5kYkyT3j0yY5JgCfNJxznbETfvkXM8TFMWVe8sqBXwtsHABHhSQJhQKhQLCgTHoLEcKLUQlML5rU5rnjetypO%2BGqq5mqm9Zl1clScDW%2F8D9P4tRJu1Jh7%2BieH3fXhURdt%2B%2FnXrsx9c0%2Fr6qolt6IKcu92PsmDvoXhoeu71JQcPbsnc0Y%2F1%2BY3T3%2FLuU56MjyT8vZDwbnNII2MUTxVNbS6DzPLEd27ErM0vJ8duS7Eu2x%2FKkLWdg984Zv7ZX%2BOvcSoP7lNe8LygfYdrfyeuvRPfI5wEdGEOhYOkJ3zs8e9LsnFSNb7BrngrYmxUsIPgT2wcBKhSMShQTCgTCgLEgNBgLBUMhQTBQKhQSiYKjERBERhZGt54%2FWvGKgaVLpdZrdRNUX0Pzv8H4v%2FLiY7ru5PpaPiT3%2Fs9tqcLffDTv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W%2BHMzEHh2qeBxb8Z13x6HACFD7HuEJ2WkVf1dO%2Bndeeo29u4HiP3azufZn%2Fh%2F2D7LdBTZVQHlhs4q4fzdyOmgtpasaKuDfNXS0DuVo7o%2BcHAEmFJgoWAsiBWFhwFhOFhqFgqFAsFQkEQkESPEL9Vrn68Uq98Soo1OZQvVVdXwD0%2FT%2FyXwf4hvgNNZ9G99nj7Fb7bbu%2FtwzPww%2Fq%2B23q78jTMHk5eKP%2FDk0BwY1pBPrts2JaN02fFAsaA44ekYcw9Om8udprZN3EaT35vH%2BBjr8s2C3UAQvkBcRJ0u2gImjQUzHSrgCYM%2FW7XznHo598CpACioCPh5twkctfYVwVxvq96e7tWJkX%2F8%2BrcY8XuAraSUeiVCFrUAD0M%2B%2FtmoWlcmWg%2FgpMcla1tPXraRxY4gMK0a%2BWzcvtjOloXY60tr3wBwBIhSQjBQLhgLHgNBsLBQTBQSiQLEUZBEJBMIjd7XfjniqvmFWtS6u90VLuoXocw3j9hp0eepZ9bj0W%2BWnf0qnr975nZxby%2Fr0DH1LrcDZ90uOB%2FG7Nbphh0XtN%2BJS7LuXnf9lnMrBpZtSYY%2Fwt9%2BC%2FKdVx58q7tV%2Fw6jpl1trj5nBRf0WNpysACIUOxD8MIFmaxeJcwGAacIkoJCavcBI7VEYSCdewJxpNQL7Ke6vhza745zD%2B3biuzfztxLT4VvqkrewqNcRjA%2Bv50coIDu%2FZBBJu5rz2SxG63C4t7JJN8uQOAEqFJBGFAsFAuGAsSBMKgoJgoFgoFgoJQoJgoFgqISEERGazJ8%2Baqpib4WyXJmFROJkToaK%2F%2FH%2BDQZ6fy99xO78ceclRee%2FO%2Fv6RcDtfrbcbX%2FvxGq%2FGXuILi92%2F7dj37735vz7%2BcRNm3Xrv2iy5CGhi6Dn8r%2Ft1eaaBcHpC3%2FPJ%2FQel6Oh8kDz7IPu4y6YmvsvHS8pndQn8x7%2BmPyIefdiaYQl37xRCLYc%2B4HPwsV%2FdmAAllUp6ecTNQ9812dcPCezisUh8rn0m%2BViq0x4rIyu%2Fat3unRrraMprxkxS3MnWoEbvpecs1rJemAOASYUmCYkGxoCwYCwaDYWIgWEoUGwUCwUC4SCJnj49Tc56mc3WXmpdIrWYm5Joq5YHj%2Bv%2FM6P%2BB%2F9s%2BuTr99EbZKR%2FO%2Buz63xPc3z909vczYqLUdd8wpP7pygA724x7rx6%2BNvdpJEcqNxBbLHfU14IMG%2FmeKI6hByLtNQFBTxPRHDp2dvakhlf3bWHY0vb6VH39l4rsX%2B4DBNben9xcK1EDfz3toN1mDzfQj%2BbfiqWlqoQbyYbq6LKG7EBkdBH8X4viYwmtDcw6D4WyJVWPSEGWYq4XeGFLRzlO7idKY8lNxKv6NSMUtiyM%2BOgHABLhSYSFgJhQLBgLDQNCYSBcLEQTBgLDQKhEJBEJBETcvXLx1TF1e61JKVGFFeYqTgW6Ok36XTfL%2Fm%2F5LD3v4v%2Fb3VHMlA919tk3u6dUlfuxafU34pMyee5fo3IE1gT8oCnIbdRZuE37DW89xOOXM3cDfAZza5iRHHSkpA0QfgkleW8BAZwUmjJPwXTfMPqbgu59gBJOUG1kjTKDt1oAOCTfcoQClT3yNjA4JrgkaqO6UYO4JwTMZEs6QN9%2BgggSyIYpgFDouymPG0D59TzfP6Ury9PBLODUExhIZNEzQUgkGr1PmshAeQqPNInHnmI232sDgBLhSQqhYMBYLhYaCYNBsLhMKBYKCUKBYKCULBQTCUKBEi8s579szJdTXr2pmqqUqbVepEnA%2FZ%2FP%2FoevdP%2Bovwezf7kdnk%2FaHOrRT76cef6n1u3%2FPC%2B1ABV6N7X3s8ioVk96qKnpfrvzLHlf%2FY%2FNitnKEvOxff9ZVBhWyZnPth5c5fTNlzV1211BIAXpRrZ1T89iMJtG%2FtF8k6L2P3JVpfSV57fLfV%2Fr4SGbBMSWvWBjmevoGrTvFuB8r9K9vofhv20Xv%2BBs5HzAlaoDCyf111t7FgigTEjEHRfy1ZuYkQNPXeJH84lHO22lmlhKQlg3nclPzg4AAAAgJBmkAQCgVxFSE9G2rzSEd%2F%2F%2Fq432veI%2FxHrVz%2Fq0X6xV0rX8nq%2FderdWO%2FS%2BrHa1XELLtWK9X7r1b9Wu%2F1wry%2Bej9WK%2B6Juqr%2FVyW%2B5dLuvPX3HwVebwQ460dzuXvx3vT%2Fa1jv1euaS65VcriIm%2F175rtXD3XZ33%2BvVySevXyz2vTY3Ewr%2Brr51Y%2BJrkkur5aFL%2BtS3VNLc15PP%2Fkprtcu1c76LWrgQ6kST174mSJXqubiV6v7k%2Bsm6WvXupemv5l6rkurktEaS5KfuuVF7vtX7kL%2F%2FVr369fq0l364V6wSeIo4w19mNtfr4H%2Fxyq7lv1YksFBJZNbMlOKrpP1asCXXr3d3N8%3D&media_id=1254206535166763008&segment_index=37" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:32:14 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:32:14 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_tpMUx5\/RAV51Bx59IdY\/gw==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:14 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786113496693119; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:14 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "8bf9af9b89a23d85eea3c29445ce071f", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19915", - "x-rate-limit-reset": "1587864356", - "x-response-time": "37", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "00bd7956002507fa", - "x-tsa-request-body-time": "96", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"H53XamprFVR96a%2FINJAQajhT1Pk%3D\"", - "Expect": null - }, - "body": "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2BH1uNt41pJBLvuBZ7CsfYoFNG%2FeABTh6uSMiPxqLov6j84F6Mx6Xm8dSA8ltugSpEJ%2BeTP6EXgcuL38fR69PpFpvsDWIOqYbewCtean6Xlg%2FZrSvtE31Beku3PKn%2FacfAchDARhKUWjK0A1k6g9zLUw8t0AaDpGjAsMx4uPoVb%2Bz0hBkJGL3vk8LdiSoS3JK3hfOKAwsFftLKo8KPKBwAEoFIwsFCMWAsRwsFBOFgoFhqFAsFQoGBMFxKEhCEwtzU3Pn22b1Uzirmbvepymaw4kk4H5rfL8Z%2Fyan1gvV1%2BuN1PZlT2VahaKH75n22Dyv19ByCsf3jxHZ7fVBMvz79ls4b%2Fg2yYetoZ9cl%2FScDf5d9T%2Bf7BQFsz3dkkw5yWx88pV29mn5KVeNeoDMaPZMvo4VH1bt0HSXOq%2Fv%2FO9%2B%2B5dfpNCO9%2ByTIPX%2FC%2F1648u31ux%2Bsf4%2Bk%2B1VfifsKTEM8BNCu86QcEZysMc%2BFTejvYDjuGFFC4iXC327sEv1HbgU3Rwujzc5u8TzOylWU1rTLDHy%2BoxLWlaNWrP3a7V2IobQQpunwCTLJnrf6nLd93RBwEoFJBMNQoGAsKAsGgwFiIFhQFiIFgoFQsRQuEgiRiTj7be3jXLzzVpK51UKmSqnUJwPoXwCNI7D3Pq%2Fnn%2B%2Bn9dmJR6X4Up2KL4REpVV3BFw18PDaFQWXfF5bcviGp%2F9n%2FuKN99QCD%2FaECdLV8ahEXT1W5a8thNv6jq2DVFVHr7PhTORhXhA02NuCDF%2Fek4Rn%2BR7rgQawvio9vxuBBv1jo%2Fm7v8F5A7%2FVP7OrPL3%2BW6FqhcJAmIu66tPklxFTTZRqpsRQAsVTnT%2Fd73F2f3wPdL2gvpd7Jg%2BYgfhPL5x7%2BrpPP1%2BLiAknPy%2BxRVQoQiyx18Z4ZKIqUT1OL7cfrkJnv28gcBJhSYKEYKBYMBcLCgNBQLFcMhYihYThULBcMBcKhErucXvnw6yc18ctZxm8tFZrJlzirqdBNn678u6DxzgmhbvUrTvIBffZ80oHSZsDyIn2nz%2BqeV6IVOGopUFff1kWoMKUFBl0nGbu%2BfPKd33ir563vIsJtug2yW%2FulnG2eP4qukGg7%2BMcHe6SsOUVQd3I6a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" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:32:15 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:32:15 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_v3OssqeHwG9jy9hbFiD3aw==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:15 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786113560974517; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:15 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "581857da964c7c95c997af1b298c5f7c", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19914", - "x-rate-limit-reset": "1587864356", - "x-response-time": "28", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "00ae1517009a6253", - "x-tsa-request-body-time": "77", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"tCBERbELTX4OGhSIJttjsmSs%2BTg%3D\"", - "Expect": null - }, - "body": "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2BfaIw38X8RP6PBa9a8pby4rv2ItVI%2FuTxfjRhPP5iQ8cr7n0ijUHj83zURk3q8loSdrtjnrJdeXqir35%2BWvOVR4jn%2F9Yt%2FfZBem5vBMa5WN6GZLW%2FaZrqL5rvvtFbvtar0XpL%2FXv1YK5PQjr8xaOv1yu9v9vKxq%2ByCMdCnDqf%2FIcuZ8%2BErnp5cfcl9o%2Fd3VJatXrht6r0MZ%2BspL7OJX8aHwWP%2BuURr3L6JaWuT0JS36yvwRHbpTpKT29Xn8xN3dkKX8nocxLtfo7y8UtVdbPWhMlkE2nu5%2FQiUlyQEkFJBsFAsFBOFhwGgoJiOGAyFgoJQoFQsJQsFxSEREERN7899c979u%2BO9%2BduKSs0kxmKk6ir4HYao%2FQ8k1vuHY%2F1x3fPwlC75XeGjx1Cxxj3Vb%2Bt%2Bu8%2B%2BMfC89EyzuC9zXL9mkYM3u4IV6TSyDAPcvmgPPte3ZU4egCCws4VOJ%2B7jxlels8%2BK99xaYthXD0u6P2npP3NH9HwXDMW5d2VL4gAbRA5Bs%2F55kyp030Jzpl0AQzFYp3dnuOLn1%2FOJ%2B0vnYITPRJxAKu0uy7lqT08nh9dFeewOt4BXvKrmnYC69O0CUzYOaWBDZSH0Mu8YdZ7Uke0%2BSqTP%2BwHABLBSQLBQrBcLBgLCoKBYUBYShcTBULhQLhUbBQKicIla7e3qd79u78V7ZealZVuGVti2pI4HIE4%2FpOi61%2Fe%2Ft41Oy15gWLNAuy7mnSeIH7t9%2FWLvohpSDTSWcCOicB7LXg4HfIA%2BrlfC1o%2BMSx%2FgaVN1gENz%2FDlOeFcPg5OMLsNfzyldtGDds2WYztnOOz2uuB4yKnxDnKuc%2B75nXr2x8TvjLf1nHEZrYDqG2B7eQSrXf1%2FecbOV%2BKej0f2Rj7n0TeYjUIdviZ%2BHLPbfI3I9PsF78kAS0XnM882OqbfygI9z60FddQcABKhSQShQbBQLBMLDsMBYSjcLBcLBQKiQJhUKBYKCUJhEqO9Tde%2Ftv2%2FOeyVqZWS9VzeVuSakuuBy7Vfm43zHm58Nfj3fm1ts2Nx5936o9bIkfLLb1lNSujA2giT4I6vEudfYrse6ynrzbgP8jEiV67G2ptQlPX%2BAvM%2Buq1vtjUUEeXwsF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" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:32:16 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:32:16 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_XFZqN0hLumLDGyS7QRh3jA==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:16 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786113624207302; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:16 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "11f90319f8e6ffa9b90c699b67ceaeb0", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19913", - "x-rate-limit-reset": "1587864356", - "x-response-time": "38", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "00b5d028003c5e89", - "x-tsa-request-body-time": "66", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"3hAPCbV0ZqoOz6k3FLpOlUfkbH0%3D\"", - "Expect": null - }, - "body": "command=APPEND&media_data=Z1HmD%2FkqPlff6v83V8V0Z3zE93asr16XVev1YviLy%2F0bL85mPl0u62%2Fa5xAuY1arv7bmkXfto%2Bvkr0TvCDu1dXr74n4T%2BarsUT%2BvROyXWvXZ6lwLZf9S3XfJy3eKJ%2BK%2FXqh35plzcuieSvdr3po506iDMfIn8Xcs8faP%2Bfv57pq9Hb9ekFdcytXrX61cjd9rLuua%2Bby%2FzGw4yziPa8vs3mv2%2FKoV%2BP1Xz1aOdK6VpLv1ZP6vJE6XPDhJMGVOcW3GUP5PlFrz9Taja%2F%2BT338Iz8EZeQ9syY9sxQy4d6kQQp56kM%2Bh5BeMMVXjLVFP9byeP5WM1Cf3d0DUNfZheYvbUFqPlTkgrssItXeDjNhCZNM44ZcDiWpFeJ9U6frFWq1XNfEdoSYFE%2FcvaFhDjhzagzZ6DfNSvpMjjL50vopW29Aq6mhcoYHZJ02baLDuN5d5I9JeOvtaXS%2FTHZfebjyktj2jGmcxZe7yev%2BIEXSQM5mD75b2Og7W4161lx8lwF5Pf1oRyNUk%2Bv%2FINNVn2EOMsuQ9luwg5CVlOEqBiYtPmYyWlu2JiwaCaQWEctvJ7d%2FXfgj8hFURUFdDokv6TEiO%2B5XuVFJe8n05Vdh%2FY72Ay0pDgPWvBR1tR0fXyfG64XMatirAd6c8GYEL%2BXDF%2BOg8Bcr9zbh38nd2sdO%2BpmDiI%2BUtcU3wjX63tqJEm175c%2FBIV33yfrpOmFzQ9PL7uGBIKxk23wjwXTye2d7hMkQ%2BP8PJdD5YRtBWSo%2FjYwoD474%2F%2BT91o8s3IRGkHzy0DxylPgtPGPfCFnU0bAjLb2IxPpkpYMHalu4cyeTkFaDmp3P%2FEEdzwa%2FNLtU%2FSrBf14LIYI7bxojwrn1a6jI2fl8qavDWPJOganSMsyT%2Fho7htD09Al%2BxB3j1yfv0pSOgUefkns6lSgwlY2aYrOIGNTZCNgvNv%2BTyI6fEXaRlGMV9fYZ6Rd5Vh9bj%2BT%2BdUsh73k%2Fv3FCI7qIHbTGjXqBCcOWNQev8R7hWQlSpnp2%2BRKGma%2B5LZgIXukP%2BWX396kvpj3pu3CtNMz%2BnRkujUdfLDX%2Bq8RLRguO%2B3kjV6hmXC4Vdq8k343p%2FnPF9roxc7%2FWKsXW%2FfFNxd%2Btb53V5H9ViX1UmjQ8IMwek6TjGLHDgNvnSHPcqQaZANU8cQ%2F8TRoMVgj%2FF2KRDVXTD7dFPheYlDzUoHlDAabFs4QDKr%2FWuev4bdp%2B0N7qMIaav7BNt3Cj6%2FhU3k%2BPb33enbNJeIc7YY0rWfL%2FzIhyWtRZ932RUkvuS1gkM%2BPecfC3d7upu%2BEedxuHvc5U%2Fzr4YdfvJnrUi%2FVevTqpHPvFUb5XnES0TheDMJD5PSl8RKQbzbvbuUpQgDGQWYF85lHxIcjQ5%2Fv1XLvsKlZtUtVUPuL%2F7XLs9fxuW1H8KwV59Uyf8weqlogb%2FF1Eo06V8r%2Fk%2Fen2S2DJcXzj8PpUJhBxg1qDQoYBB%2FWSZQ05L%2F2EN6mp8mfwr5tOVaPNprGczjF1%2FL7u6QKPNQPIxXhov%2FfnsPaijr39wR%2BO%2B79Ce8tWJqXu75a8ojd%2FvapL%2F0Q4NtfEEfhs6DhDg5ZvwQNLOv6auCQW%2B2mN%2FZxy%2BVQTDvavs5V9iuiUjJ%2BTb0cUs753%2FtFw2%2FtrDh10SyJJa%2F8V3PUbNvsHL%2FXhY3DAxF60gwVwzX%2Fy%2BXXgnFhz8gnq%2BBNuH0fy%2FOZU0UkDmQJG%2FzrHTF%2B6uFl8X3WTMos8hXe1SpFp%2FQVPp2wQ3f7Sv%2BFyIaaoMmeUsE%2F1ndcl%2FT4apEEB1xg0cP0T1%2Bs%2FVSM9PBErX6ktZFC8VhuRNHMx3%2BFSwCnXmNBM8wz6g1dz%2F%2FE25PcuevrvJ6doRnMoevk8dGx9WoJeIcGcqVsNIZPD9QtQdDMvGogY9ntkGGfaH974%2BBDjOTuH7BDr4wmklAgNy8yj4%2FLRgQDAIEO2SguHj2LfeuIw3pN6tq7P8KzZq2xqcmsJm8v%2B93BMXZnMY88e4zgkPmu6KR1RP376yu9zCHS5f989Qiz8jWov6J675IL8fBAdPRjEpeCVsXsal%2Bnwl1FyZ7Sf7DlTZCXTWvxxIrBt7DfQZaJWcI8Fy8BJJHdezlFImTNH%2F5SLNL8N9Vcy0o%2Fc%2F2ExpA2%2Fk2rCQyHlJfNZhr4nXclR1s%2F8sdwpZe%2FJZhtnX5fCffG9mE7vV1hKUPVWW5IbZv6qptn3t1OIGH3mv7flyT7yCNQvn9DpgiGUHrjAkLRf%2FhuMDhiJEDgDpcAzWY8Kz%2F5P3esMxlo%2Bz%2FiGgbJZj7%2FnKv5VAak9%2FVxTX970rDVqMRVj6YeEvmQvIu31t5CXa%2FFzU%2BkvwVC5duzLD0m69WSq%2Frt1CIgvYypOF765zg749r%2FVqWTGPfOIPlzDuW73%2BIxoYTB5FVZnkcpBb9bshz5f7MKc%2BaFLdoXrv3WLkq9a7IbBKb23ziTdv3vT5N08n90WWi9KX%2FrNnx%2BusldZPdOqs%2Fs0EU44n%2FxBMH38eIOyYSMvx69TXU0mJfclA5%2FU%2B4t69ntP71ZiO%2B%2FkmT8g139LUiayV0xHW%2FuQVe%2FcEU8TGeWv1Yy%2F756%2BiCVvy%2Fz3Hg%2F9MhaPUGSvuvqE%2F6fIXk89%2F78Ru3QN72K9O33%2FzZiO%2B%2BZCWCtXrdcsd3q170kSC6aSrzfe6Qwl707f579G6Rd9a1AEoFJBGFBKFhQFguFhSFhIFgqFhQFQsFBsFQoJgoFguFQiU5vnr7fXz8epvPK9tTlEmTFZevO4mhxXf%2FzfGdWeIft6oB4%2FdLtV8hm28fR%2FjDVfu%2FwsdhBdqGmX4KjGnz%2Bn83PDmlB8J0BrdYmpS9NWgfPX%2FVaI%2Bk7xJ%2Bj0aynt57pX7JTa3vL2Bj7O%2Fjfx8wAlPcZTk8HnIVqOuPV1TeyY0dN98e9n%2B7mxq9qbVa1fhTEqrpxOoJQtpTUym%2BN%2F5B6%2Fz%2FzH8Tn8dMpUAEswA71nbp0KAeJ5P1WpzzyjBO0YVtXEdodVi0rSsWOSCCMudQcABJhSQ0BYLhYMBQMhoMBYiCYSBUKDULBQLBQLBUThEjxU1nvxv49Xm%2Fx4q7rXKUvZTJfttbobFqP5j900x%2BOHok4u4%2Fqg44Oz%2FQfgtX2jAgb5z4XgZ0XDy9MLDV%2BFMVl%2BrSLUcp8l5eE3Uv8cDr58GmrJqqAin9%2BpZA9DdxlCZ644faBoOf%2BqDfcO5tA%2F2q8tO3Gdh0b1PTAMcXo8uWBQXxeQw3zAHdOYs96GoxS4OQZCDi5E%2BggemaT%2F5cc%2Fquw%2FWUKDWt0vgXdVWgNbUBgHyqenykA6u786kiMqaRJJ48QXdpS6SwSuPDimFZCMr846gcAEmFJAsJAmFhIGAoGgoGA0FiIFiOFAsFQsFQoFiKJwiRzC%2Fte%2Fv765rgLovLUyVjXGXV9D4RvhtH5783b7PPq%2Fng8v5wO5I3LQ3yey7kRjA%2BB1HnNZV6PTesqcrsomfXdob43qj3JW8ouTj2ZgEfr%2FZkzt48JTE8c71NZ9jkmeha4opeG3FTIzMImxr65M69%2FGFQDQFBJ18SUZ57AVnl9nXzx1Hedb73Ldq4LxErqG4UkmvEAv7ufKDOKNIa9wAbXJ5yrqymCEmPtlnZZcDso1yUcKqUAKA%2Bz8vf35%2FhACo9phmN1KdGMLrP3PDGQJ0YYqZaNQxSTMdey1vvgzA4AEmFJBsFBsGBSFg0GAsGBMFAqJwsJAuFQsFAqFBMJRiR3I18%2Bff499bz68apxmQ0yqUjqrq%2Bh%2Fp%2FF%2FoH5891P%2FQOMwthoyWXN%2Bg8X2ziciLdM5TPM1x2qT5hBlCh791U9fu%2FG99f9P%2BtHLJg%2F%2FzCs%2F8UT19e7gbVAuwb6GtEL7e9o%2FMORbJ3uFbcisMW0zND6fx3UBrZxJLEILh%2F2KLY1O%2B37C%2B7rPN1%2FBvr0tkMf6ilHlmmpan%2FdSueX6%2BhsIVWsNs9fLThKHOiGvf7STPGoCZg%2BHj2%2BHt%2BCpgDGxK%2FPlaoES%2B38SSzLmhZOtZsbLeqj0yVm9UwOABIBSQKhQLBMLDcUhYMBoUBYSBYKhkLCQKiQKhQbCUYkeryvr9tc63eVxvRdZIl7VQl3E4G5vjozgv8Yec2%2FdU993l21v8ix%2BcsvyRwID33M%2BbmW5yv%2BgeEN%2FZUdxX9vBcq%2FgN0GiCk19f6Dfv%2B456iY%2FqNJBfnoaa4UKA6PqAiABmO1JVb8MRtct6cfWXRfHceyo7JxdzvzFi6he4qi8jo3yF4jXgf4odTT3BgnV2jEZ5r6RKKyEMWmOnMoFNJTXELszcQD8iXu7p6uGHU74DPojaqPOBIpn9vZRouyyF5ZVlP2d4SrC9LzJ%2B6gHAASIUkCwUIoUCwoC4WDYaDAXCwUE4WCgVCgSCYUMoTCoRK8Z1zO535rHj68cZLxZd7pVVck1U4HHk0853vTu6vq%2B6D3fgxJPZ%2FqFCs9bmKo3InsBnRDK5RBjf2eQFA%2Bbg9FAPyrhIBGt4AgYeXjNL178P5Ue%2FpIx00HcrhEZ9kXZWbVyC%2Fsd4pNoyqWRZ5L59T6e2rU5%2Bq2xAar4ZnsSusJ6013rpE5T1CfCuKKtwEC%2FbcfC%2BBpSkPSt5HzH4weAWnjwKFlMEKktsWEDDKc5%2FwThcYLAcASYUkOxaHAWEgmC4VCwUEYUCokCoUCYlCJXKSu5r54173mrqpx3a3Hq2TL1dReh%2Fo1jwO%2B9jo3bn4Sd3R5r29P8ijgTOjoorhfbv9DyhwpaAYK3k5ypOu7afwn2%2F5TxnyTEFx74g6n3n%2FdSPL%2BvSscvxBgFM9bb%2F7%2FKK6Oh8xhMa4yn4fzibnntDcYQZn5p9C4N5SOJycem8TziJd%2FnCiv7b8T0F92NSv53Lzn7cLttN7ZpjfP0j2r5eGZm%2FHL32KslSOPgla71leGSaSekuk9m0Jp3ZEfYmDgAACJVBmkYRigV10hddq5XrFQj7u69ev1zFzrXyK5%2Btf%2FrB0b%2Btf%2FXf612rH%2F%2FffakUVrVrlJVL6yvLV%2FL243xdZSokXFKCPhHhuzhtzhzd6%2FjlyH0K6aTkRa7%2FXKt1SpUslX61XrURqrbxfRO48IwWOJq0g8%2BPyX7Fy0HGvWtDyD9ugh4BGwMHaxztXOwz488NU3a%2FyubLuk%2FRXMc9puIvlqiFe7uyGd8jj%2FvJ4q7qILK%2BzQ3fs%2BEUQTb2bOsPkvS12O%2BYu%2Bkqk6VX61eulq%2FWv1Jd361Lav71P2r8vZRD312BGel9Xu0Jrd9%2Btd0K20O6fie69Yov6mVe7Vv1fshsfIns0fa8AtUUb4M6PFdE%2FSvw0nfXUXITy%2F7uLvl5Sk3GSq11ZZSCgUow3JnifDSmYIg%2FTL6LFJV3z86tLc3r0nrljlvznIw4wj%2Fpnr42n%2FQrhTKb7wGF88pYRaoDeGGJNs%2BPyg6b8oK6RY%2FAZQbu0gPLQZlVqUkpd15PHJdMIG5WCXAXiN6%2FF46mEoD40mMkqO4t%2BWdeul7%2FWv1ru5Vfnr168TPXOlPf48Lm0i5ahA7qq22DCDjHH5Qx8eMRXSGjju%2FYbn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tOsVMRnjr0vzTz4%3D&media_id=1254206535166763008&segment_index=40" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:32:16 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:32:16 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_B+U5CBri0wLopheYxCA+Qg==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:16 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786113689601206; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:16 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "bd4faddebcadd8a630c4157c84ff8462", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19912", - "x-rate-limit-reset": "1587864356", - "x-response-time": "38", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "0038f9c800bb6c95", - "x-tsa-request-body-time": "63", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"ygio3ywPYDgPQxoXkiEzieIks9o%3D\"", - "Expect": null - }, - "body": "command=APPEND&media_data=fKjNo4CpcnuQuSp5wceSGp4SvpUMnovqFL3%2BsVS99%2FEr18q5VlrB2rH61L6tXr3OciqWfHNfJ%2BtP2Iw9i%2BsEv9%2BZAhox1rhnRgl8yJewzjQQNwJX6ufsk%2BNmTVHrEUg3PR9TGhwF%2F%2F8fbtDJc72UxG%2FcEdBjfN7H4b5bQTuR42%2B%2F6tF93d30ua7qmltWvlVy7rL76zimPjat31%2FXlyKOrsNibvW1Lf5M9fHJ2fV4ISDpc33GCGrR6u5vXLp%2F1lEevSzq1VWT7hf%2Fb0hUvc518%2Bt%2FzkX0hkz9v9oSfSevdr1dL2OJuumlu8uT17lXq9fVfgv6cGHsEZkDSlDAXSbE%2FovVanvE%2B%2FVeq1Yq168I1Ok91fcm0bgP%2BloCk%2B%2FThEp8uFzusu9MjQkZOomXiUNemR3u1y%2BarViSeS1ZJavd%2FrUsurdEw07QK%2B0nm1uWlMomHYKpBE%2BlN7CCpLzjjghZyDWT1%2FSdQRYE0l3pOiv2HDZB4Pz0V2k01St19iYeMszMqihKFYaJRPLd9%2Fo9VaxSWrpifn%2F2tdF1EqxtzQwbmy0VdcOx%2BkEjvGabRUVL4bvYIDX5iI%2FqiRd%2B1Ln12ZPDS8Ly%2FuLfYDTE27Nq6GmN2cP0NOK0DP9GTS652J%2BbMxJ4tkpp%2Ft8K2D5hrKYspySQT6PYof%2FfJ9%2F6M%2BlXCta0OGfhuIrAa%2BmEv%2FTMn6TpuW0NMvVpkhxiq1qmhS65J4Jpe%2FFUPXNy338sty%2BhLryfwiazRHuszGIeg8RhyYMYIex%2FjNVj2ATlxPgOtroDVHpSJWTC5r0x8YsVAx8v%2FF03TZT%2Bz3QrJhq6db%2BlSVDPe%2FYZEhr76%2FHNmN3sOFe7r9NDLqFeRfljxD27rNj1m8yGF4gOwvx9l5lNz4lkdK60ZP3tzQ3Dybhg9HqNS9dG%2BTCEd9glK5yWUfBrl7%2B9p1pl7WUL3oE9udnU2hxNSpueS6urmFLxC%2BZ8Z135JiAZ%2BWfgFvNGel%2BIzyFmYKrcMG6a7BOcaEqnjVvd2ZPOt8Mk3pU1zVw9ovIf9gv0mCDaGCjxL52%2BwYbiREVp5b9z4Zu1AFKEWhAoqN%2BEbBgToIz7DNmu4%2F04io7BEe7djcXhcR5mJmNZXxxOmfW3aHHGWr74w17PTTfuFbBtK2WYmv34%2Bu5PXeishrmz2FblIPIkjggLlGCFp9v%2Bwrj769pdHqdNcltcnwu7hrje3jFfbCX2Z9hXgf7Jf692lMvptMgUbeOLYc04lffBNrG7u%2B%2F0Q133JX9cI1tomXYXJ5L5j18EEH8EDLOr9vgINUb%2Bl%2Bz1bbhoSy%2F2cslFhsLGqvL6hodj2hPd7cs5tk4yag8uOon9mvvR0eUGdWsv2emEckq%2F3drhtyLvtHc7OZMfoMNxSykz7nwfDeH2wNtafLWHUEZ3d6eS7nktav6z7ZWGRWq5TThw1fgZmIMwvsM5DRxg7BAw5g7j%2FZyvctKdLt%2F7OaGEq%2BhyakSdBKBsUT1Hs%2FDsEHk%2Bn6cq78vs4ln8umJ7BKRyEUDoMdarWuvaChOzk19EiREfyw0Pae7OY0OGvyeX1nFOfsINpq%2FZ8UqNsqXfGRPs%2BC48CDwH%2FWrgu8co80BjLvz19GmHu7anhDReYFd3%2Br1ctoTXl3kfZxhrR278MqU%2BzkODowZQkP8nl0dWcq%2FMrsx4r6kbusol4Ykx727SPB9AvFab3u5mq6gZAynW%2BirvOV37BUjqLVnGbJoTQX%2FnOtDfIMnvi%2Bjs4nL8Y9%2FYX401yjl1QfWPvuRM5eg6mIsiLYcvZjpdL10pYOX9nFasSq7n%2Bw0LPEOMrupnNW5Ibe3e8qIzkX4ENJc9hwiEbp%2BlRWl9FasT4j73G6KwrI31%2BUVu%2FL06hUkMIkMAexnScFeQl429wgPyeH19nKuFI1%2F0dAwNXkgq%2FTqKkV%2FRy9nvjd%2B1%2F7OJX8zCs9K3LOgzw9DctfIj6Td%2Fo884bxd3PD2c1UZJMSoZPt8NbvVNfJ%2BHEngfS%2FXZcfEC8nhX4bxh%2FDD7zimh0ipZ%2B6sRCdntFOnDTLejnyr32SDtmS9hXjDVVvRJo1hzlf7dMGBWtRsuu%2BFE7HyBIcHwbVcvmfuUSyw9lyWjVEeQ77rIuvvr7Cwrd8%2BHhKH5Yka4Q5C3vEBRkZ0i7WwV22GlowrxHnoUQEoNRVnuIZFqLa%2Fs9fzImo85%2Fj4cRPrk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mvVhRqKoMwg0Gf5PqzpNQQ23Vxeozu%2B7qaksFA%2F7q3JRQSg3jGrDQxQ2VhFpzXKMMeu8%2FHfV1oTVevd3T%2FrFEao5byf8n50VUCQYFen9bvFEA3wUjAhqRgoZ9LAwL432Ft7dZcr8XzLppn%2FTQl%2BSyeWknYJCZaHhAqoegYSj5xkDfiUsJR64W1FCrhVKKBaP6yskEPQMts2niYuGYRAfp9tU%2B7%2B4YvOSNuMkRa0L%2BC3jjpawkVmPOD7kRck9nfx1wxebvmoaj39Q10iKFjOlrH7iqSrr2Xd80Qjv778v1MRnBGZkF%2BVZUCju27cua5w0dzw1jn%2F8nvbaknIv1GSkxcn8muJQRvvHyv%2BeDexkajYb%2B0xZtZu%2B72700RBmFlbjrg1hn%2Fl%2BieVFY7BOaOpiP2IsdDRb7hk5oOL6Tst3xR8ccz%2FOCWiaaqzntLk%2FTLW8njVtKFTP0dq4mtyXzX5bWf%2BojTppBqhRcppr0lShWOvv7Rbs1OaDej%2Fd0%2BC7xROy3JQl1VSK351TSeuUrvsnz9OC4Y2b2UBHrYG8%2B2e2a8kTOP4yu5bnhG2KlWxUxIw8%2FHwVK8HgNW6y99PRi433ndNvl%2Fvrd0TNLzrFtsz376cnlOJ7%2BUyFEua1KjmcfZmfeKKStxYZ4zpWnPhFwle%2B%2BSip5LXpJ16rXqxWS0eLxXUI%2B22wVDrK8fJE9JO2A6Lgbht9YVvzeCuEZsoHUI2seChfXgwhiTH5ZXUOL5KCaroL7%2FPXhxOp%2F4Vt3JlVQyiyjAINiPnGjJhCxP6Y%2Bld93d9LacFJ0pUuRFY0U1LnYVIwZSSNg8B%2FtAfzV5Kg9Q7udW%2F27hkg%2FJDZYaDi3h%2FTboGY%2FuGx%2BVhHDMplCWGuWBqcn8WKdrd%2BlpT4PsoqMe3aDkI%2B%2BKkIHxKjNbAadLJSpqU9n89foBsQz7o2jlX8LqLl9eriJifP9eTT%2FKZ37f0PkLmfHsSeN1kZzd8wYCRWPiQ7qKjlVFDCfevEh8nj2pwmcywa4kOfqHaOJw%2BGLa%2BHZqVd9RbgkE7jwqnHoNjL7xqM1YwMg2SY5RS%2F9PVnNr6JEWDH1JJostX5PIvI1yfsrv7ssFeVDV6Bnx776ye%2B%2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" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:32:17 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:32:17 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_eyevWj4PsKP3R1fBVeLFig==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:17 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786113758739987; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:17 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "831f695e92e64890edbd097ebfd39f84", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19911", - "x-rate-limit-reset": "1587864356", - "x-response-time": "36", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "00d83b29000e3a6e", - "x-tsa-request-body-time": "102", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"rsHro9kKYu8TQBquyGoG1%2BxSW30%3D\"", - "Expect": null - }, - "body": "command=APPEND&media_data=ERDMU9ofQt6HJRUEgSwhROJHE3Bu8LTdn9TRnGX6JLUKGvVDroMBvuj9hvmtV13VcGdnbmYU0MJu8FYuFVkpaPb0gviuL3ZgH0yfc%2BFrCSksrmJFAepkwYufIcn23X9y7U1o%2FVRNerK9Xu1InTeIOiMbCtQuTDSZlxHVAZQ2wFRaCRgmbHep%2BT8Me%2FDe5RnPdMhEPUtvRjpVvnT%2B8jsFF77HAjXudEhppIaUOoVhOMt6%2FJsv0vPQkT1aJllzLcQw0N%2F3e5aDMGB5PPvEQqZEbSYpaA%2BxXH5014r9odr%2FxFg6kkDOkm3mEBr1BhHsiHvZegMlmN2vwi89fqDFAz5KSpDLJEzqC3G52A0TAbjT%2B09zRpbBO4PyQFW6cZOOn42pUO2D3nw5JzGZprpAj0Lj6iISgrH5IpBaXaXd4dTk1%2F4e9zjiF9w3XH3Td9q5eI9WX8QdJdC2CAyM0%2BaJaYRcpjoDfKMGiqiDpfWhFMu8QGTzvJw8S1HQexN3HXNwPZ6GVUZEbh8WuBhhH%2FYkn%2F2FvXwh%2BgS%2FrdPf%2BDgKx8FyS%2Bv6cjDgl7uo4faFzIf%2FRX9wQGXsnjfzD4Bne5kzRdMJWOsClukUysHPAKvUNqN0UnxjSjFQegh%2FPItBhJ%2FS8ualx0uHZQIohmvAIaZG2DnkqwE%2Bdh%2BM7HV30D118n2buyhagh31aiVuKpTIv6eDpymo6pPoW7kCcFBEIGFeft3pVeW4ugZbp4y0dOoLDq2XAfzDCGmWfby5Q9RJ8mkGnrWu%2FL33hjAaZnI%2BttNc55ElqH39heoK6tTpFXsnXWnfJoyVa0IfwJdCX2iUdC7nGIWThh7LMwhtr%2F%2FfJ6tffYaEjWZuMU0dB7D48lEryeFdONJ3TbZjAyVUvjQWFqhKSrYNQW2DkOMB%2Fk%2Ff8GFt859goQ4Vs1tmYwZ9ZVGVKZT2vhaU%2BjHiY5rhKdg2xRw%2BwI9liz5f40mPUCMr7p1X4JzYNxYoH2mcE51AhOE2P9680i9h6gaTBucIvu6T18OYDJmL8n99OFSBN3l%2BgfDuLXxZ5dpn5oK4bZdCy2Vo8fFwOvKJwNSlY4fDurcZ9SqHa4iYmigmjJi4g5Kn%2Bvu98Js8%2BMNcZnY%2F1D0f0Dyf4w4aIZZb5xFe1MafnAgwGN77QQPBn%2BoV4aZYHf5boMx87ftfr0e%2FRkHA76z8mK69F6WyE0ksvVxUusn7umo0ldthqcNh4wKv2ANnWtfjrdX8maYwkLmf3q2Jgi8Bfd7Qi8L%2BP9R63i7kB1JSB6VCUP2WEbvdvMcHpJBVRMLDiKdYL6lbWYcrDg18uLOejP79Til4bdP%2Fqzr2Net1dg0lW0t1cb7PX82jpr3OJY5tVvhvAcnna6nEL9BuHVcTftHr4T7fPgf3elxkqE9ITz%2F%2FMVZiqg4MD8SEeGJMLRcGYSHyfav4eKvGC81oxxNocB5WNR%2BekuDdf9F335f%2FIg3fLmHOlCOxnT%2BoJESNB8mevSZSS3%2BHIrf7%2FGzFnZszC0dbwXAlhWXSaf6lhBcPoGo9E%2FqEyWDDGWlDjCZ8obH5mpbH6IP0ZeRye9tKmCMVucxl%2BCLjokLKm0twXwXK2ICUR2h752O%2B%2F7HUOQIjKNwlmGFdghPTgjnz6ipP%2FDfoZqr6MZBTA1orrsMcHBlVI%2BU%2Fr1XVo8HiP9Toz9ZzLRL9n%2FYTJnh4N5HJ7cqNhgrDOiaCAabAprqUdKLj3miCZXjAkPW%2FwR9tZeosr7mDSdoXaMfjWOmUZfem85XfZTLFh12l5xT%2FkfI%2Fv77S8OCwm0BlASfWETcv%2F26gv7h5KPaQSgABd5fDUVCpNYpUjbPJ9fuDARfTwmYUpsuV6s0f1VgvGgpUsYaeBe9GjX1XLxcHjl9U1wQm4carbjDp6cPeMETWEtCiZPRXvm9Lha8b8yyfm5Z2Sq9WvYVNYEbNgPHwcHUd42csr0DNw42e9h3OY3hvYFeXlbrBytin%2F2cqjAmdQbP6dMMGjIIbnvcjNAalF8NS4vyeP5IgW78%2F6KwTmvTdaJFzoaff3BKUGOIDnvlHxwsuzL%2B606OLWdPaW0ef%2Fdzw%2BmGjCph1fy6o7M1P%2BHOMiA6o2eHEnj6k2wrzzQOY3fMByBNUaGX7dsxmusP5l7AkZCpSDhplmL09fRol07A%2Fj4sGdGQxPUuIo4%2BkTN4P%2FneETDV6GhHUfG8EP%2Fs4MB3nS7%2BpwR%2BrEvM2J%2BOcMBuuMpTKl%2FxHNRgWUuW%2Bt8Kx3akTF7vbrDydP%2FhwoMlNSk2mJGal9Op8LItKBFYdgoKnpZY3V61V169J69cJfnf6N3Fq%2FHeTz6XDV8Ms1OCUQR0yR39nhPuBAQssj1zhKT7k7UEWEzhv077nJ9cn0m%2B4XsiHaNAjkWbxhXgO6sr%2B4bhplqPr8O31%2FrWzlgnSrR%2FY7iSODsyVhZROPsVFBBojwJ%2FdydLdfyQrJ4r1YJBuXKVfMIx8cCZ3juOu%2B0RuUXH0xm6wLPSXjjbhgOAMOJCpmGXsK71Pi8OtGOjnxHVX2JEy3hlTP8iBeaMtHMoh6malUJsv1Cfw3t64qBGV57137yaVor4Z6u0Tu17b2HNICUjiePcwZhITLv0fJ8fpBaWU%2F47wyAAJ7itF2eqXMGI8g8n7%2FiYTMNT%2Btj3bhvubzvpwiwS%2FV0GS3v38yYaUzuTPRFdv7JEvw1PR0EP%2BOmHDc8f5wqS9Pc2eF2lNV8umTjq8MTEFc0c%2FgpWwzO7%2BX%2FbwUi3vtGsPllpzsE5HvzD7vz5PZyXUJCA0kxqwgF%2BQ8xPyfv798WCUrZvjT4rWv92CLe1ly7H8nupP0hqgSCbvy3yV32req9eXV1Xsr7IMLSgtedgguwaeSnyEiYvltmklJ7PZ%2BGS0O6%2Biml5TXsFm6lYy496TtlVk%2B9%2F1%2FXnIvw0k8%2BT2%2B6WWX5fwl48P9771d0EXH577FdmUve9Pkq%2FUT%2BLYI7v9WMRab7c9o7dfpmM7%2BXtDWe3V3dZvLyr3av9eJaEP55N1ak96xM%2FXTiL7vfsLdN9pr2HFKeNpRt6vPVYgv%2FWR16F1y9rKmiK%2B%2BT0PFv6i%2B%2B9UXoZ3NSehffq1ete1TRX3f2id%2Bj3f%2Bb32qfs5O%2FEu%2FrvtHKnd13xPOjRd%2Bmvc5%2FZ9X%2BnBF7wAAAoyQZpJkmoFd83%2FxHToT01X2uV1K3zqyr%2FVq9c9Wr%2Fr1euupWk5vj0V3v81eid9%2Fa5d4pXfrh0yyrmXKncdU9VK%2B189z%2BITVb9hgmGZVacdZ%2BL7JNMkt16K0988vy8R8fJfquXsRpTcNcNtN7MIRtZ%2Fqeg1RnzXDaIM%2Fye9laY1hqZ1KxqEtGv5PFe7G2DAo8M7tweViS%2BPPrrCNgmXhhyvf2GOXMfx9cptt2f7grxzdDgIs3K2FqrfW2nC3gNbp78jtlqkV8vuLY6CFhN4ZRVVLl9q1X3LxPz%2BFj9OrF33XKr36sSS1auchJ6w1n3w03T%2B1v%2Fqyel3%2F4q7%2BWGrVXe4Jp7DbLYcdk6ceWit2iMXa%2FO7qXrqloia7rXDtWlTy9XOGbrv9gxCZ6u%2BqT1q%2FWu%2B%2B1ruqa%2FWKruWp1%2FJ9ZfjfYeJGH1vnILlwO%2B0bVmGkf%2B4rSCl3OQbOEkd1bR7j7R9yr%2BIntFaW7uS1a7WVTVq%2FYS4JCYDsuWMPs2W3iyicOra9r%2F2GxQ4XX1yd%2Fs%2F7QvonZKur6vVXJ9UR1%2BrddPLbRGFz4J8ufOu45WNyFkn0aX%2BAxlkc3MBo0lJfng8ksYlpRfSuC6YsV6VNHZt5hblJwEwyl460cv4pNuM4yP6Ckzw0hsLC3XSHCFWWoJoNpkOSz5j53ZhbvvriNiu0XLn516W75pIlayemVkpCzcOo%2FDUL40E4I5zToU%2Bvrq2NpE3RJyeG7bYKSoIPst61RcPWjGZTi7wQw1um63Pr8Kk3RlOMEUgtJadB9ljTha%2F%2FJCOWwxTTCTbHu8lMkN5G5hKLxqOJn0dZYcCeQUdOts1wH9u2G8GvKugqVhhpM7ZrRCup76sI5SQ%2B1fec0WlwHTyfvkW4Mdo32cQX6PFNRFWvX61%2Btd%2Fqxd97itw4ajuspIeNt%2FzsMeV4mF9AbA1SeA6ufX9WkHvglfAv4k4BbmRM1AffagibGixWNAajhMIIHxhzRe%2BiyI4DwIXaCtaBwF8b2B4mtIgZrhEwdiAi%2B1dTQyWJ1KSUPEb6ctggm%2FDZgqsZFBQhE9%2FR8Nl3Y5BRgfk83d%2B7u2RLNyeCybor7rJDBs%2BMHwV5EX0469OT938PyDIen%2BghbZtSKdWX0bxwHodtWC6eHaSocA0WNkR2%2FBXxhqoI4PuKinX1uysEZC8HxIaTOcuKxfk%2BFFouT9%2FUFIk5N5B4ahaX8CRuO%2FzcvjOaHUhMxBZ2dAq2DZip0HKxQ5WKkv4mWkv0cjU4vy%2Ftt192T5%2FKwwIeZBZxkICjXZgD%2F3dfQ1gh6N4vwkcqgy4%2F5aFkg8n1%2BoICS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POBaSi%2B3sx%2FW9coXqXoO5cbDHLiaGP3vZTW479kiZrFNeRfFYC2mh7L5aamDl45nfyYANQALJfmlMkZl6KAqoACySLFeX2kLQ%2BbPfWizVXkYKSMlrVRMCUvSyA4AEaFJAsFAsFQsGAuFgoFgoGgsGAsZAsFAsFQsNwsVwiV9uvf2vv59t1ruVw2i5UvKyYJxInQ6G%2B791xd5HpK1X37nz%2FnaLPLqJf0DnKZKQ9a%2F7qe9BKt4FdDeISG3THNtVslP458drxVPOO6tL3yn4%2FtI08BlkdCXL6eohQyUI5hwlm%2Bn2pFpjgBCTldX3ZocwOa1AVYIejC%2FXMGAUBqioQLSzAvk%2BTQ5uzrAACtBXxTWVVPKvusoreqOtA81mE0hW6woi2fdjZjTeSjXnAJ%2FIAB9UJZqw8h216JnOgPLMoF2noMNBL7kCM83WNV4Xn79APdJJL1QRnsa%2Bpxx2BwAEgFJCMQwsJAsNAsGBIFgoFgoVjuEgiR4ycb3nW813U1S6lXTXJVbkrq4vQ599G%2FEfX9hJx20exP0Og6cfgur9y2eq2gPrN5v%2F9uJ6V4MSy7jNGfnbHcgOQJn9b2QFqe8udHDfpfntzfFFRHBbYvugDhvtlb9%2F1ue%2BC3eDwxntH%2FIPhj%2B79vux5ffv10%2Byi7LgZgwgZGgSoQHbJX6Zv5nnILcQqvsX0z1vzwq9dxOG%2BTRb3F2BL4PgSPvR%2BFk%2FbmuSHhnyuoAFu687Db%2F%2FPhXyo%2FbP8zHnoAD3eU6OCamuDu9OeSYV1C%2Fqx8bk15Imau2v5KqnbPAHAASwUkMYUCxoCxUGwUCoUGwoEwnCIzCIRVcb3V5rtXDa9blOO6lGSuODVjkOptq%2FP%2FceB%2FhfXuSjqP88Huo2%2B7%2B9AxJ6k27uECPO%2Bu4D2e2ndZqpCqSrbJTV5r0A%2FCu%2BCEgH1ck38w74GE2qb6jm9n%2BDo%2F7iXaf3Y34CkGFPQ%2B1fY%2Bs9LLrIeo%2FmeVcu9Wv6HDt60dQnAALvOTy9W3gpVWfa8QvO%2FjXt17qYAPJsS73mXn0rIZO%2BA7gMzBYM8ZBWJPM0xdViEpFl35T%2FjrotBy3VT2401c41IAS53xuGbsgv1%2BGnlrxqrfPdetKbydPw6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" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:32:18 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:32:18 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_6+Q4YpPWZXxDcwtJUivN+w==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:18 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786113829532842; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:18 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "1c38c63d94d23ec0e727c6c785c68d0d", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19910", - "x-rate-limit-reset": "1587864356", - "x-response-time": "34", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "00216fb1003b89d0", - "x-tsa-request-body-time": "100", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"V7QwdMiNKEu3fWwcR7fkuuy45Es%3D\"", - "Expect": null - }, - "body": "command=APPEND&media_data=fJ97aqrGTz39FY533e6371f%2BCO78HlKI3uXdtyfEr9nxcs1%2Br%2FxF5QVQGWXjSUCHWX679%2FUFFmYf5iT76nJH3pXe1d%2BVfHquvUXyXz0r33cvoS5JaxVWveXtPXa%2F2rav9fWteK%2FRA2Ku7S%2BGVsf2i9eWjy5V%2F2r99kK9%2B%2Feok45Z9Sj%2Frr%2Bf0LfuVLN%2FonfSOW8I7aT%2BpDT0v37RzgvPVKlfkyE9%2F%2FxVZSQAAAX1QZpKkqoFf6Fv%2BvUX%2F%2BvWu69ev1qKurWD9aviVfnV%2FVWPrpffr6qtal6XK9CZLm9XPf3RrC7z19qODNGnVo71a5dr3PJct3alv1iu%2FdXv1at0R2Twfyfcnd9q%2BT73V1w3eCO975PBffs3SfRco79VoqXte7XbtXMJbr9vVrGP1fteiLq1Y6J7ZL3%2BjPv%2BkOveT9f0%2FzHveoslFYq1yq1bte6vdcu1roUVyief%2Fdq%2F6uH6v%2BvTWsEvq%2FaGdykKf26tXlonHT%2Bq%2B65lcu5II4vCH9aq%2BwSEe9%2BGaousMZPl9HrvonuJ9ffq%2Fpfqx%2BsuymxuwubeXVhHu50aBXukzqbcKaFFiOv9EQEBpjg4OgvSX34T%2BTVor9Nr9aq1avVy%2FXpvVy%2Bly6N2RFGJxn2wT4cSEV25P85x%2FoSBclxLdjBGumpr6NQQzJGVNjwyePu%2Flgrwq0krQMtX%2BgimKHWMMmGUE2HmyaLYQSRj%2FoeRKxuS%2Bfiekrk76q9CrzcXJfZjUDKyZdNTFFrDdl1b8s9fDj79iuUuYGB5P8e5IZSy%2FQP4ghCFtsqb5UknuT%2BCWjaiJIZaw8xmWl%2FywR5qIFcIUEuCKzHoo8MHv2JuuzYCPTZmpbFvd9o9S%2Bqe7rDf8vdzWCMzvy0bhCYeOc5wlcAX%2BL1vz8oICsvbHk44O2yKOk4Sy5%2FYne6nIPtiX3u8QXd73zijMGPkL8QsyenqoklCRghe%2FPf%2Fqfyenk4bnrbrl5zX%2FBNd8ueq8QUMS0FDtHqPek%2Bjcb3HH10%2BXu%2BIm5JbtX9gg3fLESw2jSBjJChL%2BWg4adhInOwqv2KE0RpUBu95PRS%2F7MZqTE9gtpLvfKyfCS7gnw8objVF452Fi0DH2pGeN06j7n3%2BovcpNAiGvYa5LBfS1j43Lr92Ts3Gx4iLvetOEB5xASF2mZfd3ceYibf4IaMbjLYMYufnXK8R5bwl6Lvlkte8TRu7pOWHrtugKGP%2B7gieHUuqpkUf6fC1eMm8xfLB9AdSKGCHDwxIxRo1VaSfRetGnkl0eG4xl%2BX6jZ7%2BXqyf1erJdu9D%2Fe76tC%2ByemS%2BLNTp6bewt5WMeaNfHO4Ei3NqsX65VKi9WRXffaLXfezoUOjXr8hDnFfXo6DZxhBrcqG7hlbz%2FqCZhgFXx8TmPgh%2FYu%2B%2B5THYi%2B0t6vvQ%2BTLnvUJ4aH5b5bkuhfvtCu7JDKdHeovCO73xtkEOgyT6bcIdQqr9oS8mJz83zyerjloxiyeVX5TLmCDUV4TLkYob42JxVAjlCAMgSeXegv7Dd51Fz44LzzMSfJflgjq%2Bw332Ql0kA6fyeG9ZzxfGRkrqQt5PB03USI8vg16V9nZBu2ZDkgga4Ivsn%2Fu8v%2B5Z6tHb9dSWTc2e0aLzyid32CTLTY7p3giFEDaQaS4OQHfZSlY3srMYcBAd4S77Id3nUUVhezCfP8%2FpJZTwv%2FbmTyf3k8%2FKqDRBoYjs653lf9uVHrw4tx%2BsIdzW6BCmdTKp77CMcESsODAzsZpHzX6e9RdCIk3i9tBn7BokDCFhxjKSHmNR%2FZJCCOL9hW7MmPZGsO8X%2BTw9UmXO58vCPkyWi9Xr1X5askvur77CRpIbxkZlLRJ7u%2BvfYJ55q7jHy3ONMNqe2vfYbyQ4P4aifGJd9nGsfam1PfZBU7HtkYDxhF2EZ%2FP5cLlPj%2FlJE2i92i92FTUZM581eeH8X33yiy3Pmjf2Ur03%2BspeT9Fg%2BXtTp3bHzDs2ZPlr77ZVpd%2F2XNS%2B%2B8nq9eFy5fe3l%2FDs6tPKa9rsERGpKe1H%2Fff6L3at32C0zBEz0b95e71hu%2B%2BUtrJdT4Ij5fOXa979hMzvpHzXoS1Za99LXdXRPX%2F78vs4rCpKYyIC2OnRv2Gi7sbKMcuYL999S5dve%2BwzvdfzTPST56p%2BxJMMUzYottLPqz1%2BO5e%2Fd3Sv3ksx93333d0KlFa9Fyr5PVL7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bu93f6Es%2FBHveuK9ZtmEQ0rn%2BhcV2bd6vtW49a4%2Fr7IIDLV0vlDRL2mfhy2Xk%2BJXUkt35Pzrdlocvk9nvw5ddfnsPNdq%2FYavuvyrK2EnyvuL6pSZ08p5RR3lpR71EPTuDJwpPL0mgT%2BNUuZjSZKG9NEl2TC778yyfOTL62yzR%2Fydlvy98u8RXi62yHe%2FUbc9Oim%2F0Vir8M4i1qpy3f3xOj8nwTb5BB8%2Bo9fQYd7T2%2BCPu7jPXL4lIbqlfdgiFRrHy3F%2FfKr8uxyIEvad738R%2FQlpMeEPCP9X7WDnqPXqaq1y85N7qP5SEYMdX3ZUsHMiPL3UqVEU11fL2CEYDrz9zgnvgd67o7nTAAAG50GaS5LqBXXoXXd30vUtfrUl1d3Na4dy8J%2FItf9%2FDXg2qZO%2B1l%2BtfrFfrlLfFySZScdZS%2F%2BdLXy9oten%2BCg2AdtV9PBIuHZvuK7svd381X7Fo9fS1X1xHfa1zrX6sSc03q13WmQmUxPK%2B7CsS4lcvsAmunOjP%2B35Jv9Vc1UoIcQ3BK0XVTq%2FaNINFp9MFW8o9l6VG98nqTdqC274eZrGqh6b%2Bk7v7V5RX8ZKOlnRUT1qT1eIl08ehTZPD%2F1daqybv39o7e2evjyTSgW9Y%2BXibv9FqrVKfq%2F6xSaq1etV69Nrdq3fucQrt3VNf0VyT1e%2B5BxCttVrF%2BvT8XLnE3fz1f4REY57lIN3EjEuX0dl37qnX1qT1rpfiZ7751g6L3%2BvdX6t8vk6cSQWTYQ211TKdoTLvsEYow%2BW%2BVzE9y3J6OlW%2FZLovn7V64vvuquv4teon3yW0LJuye0bPgo5bKzcm5C%2FGaBRNeVEHumQgjfi3c%2BVT38TKYvsD5cvNLyeeW%2BMyqGOCKXLThy8rc0VmfF7KTyJJ8LQZ2hCy1wRCMId8finlHo38RWi9fanvVekv4ivWU6ZHDflzv5tMRk%2B9CGqFmd8Ps7yjCA9LWahvEa0kefs0y0%2F2eoYvIN%2B3TCm3Xn16hIoD9c0B62jxL4l%2BTyJX1l54TI1OXLiI%2BfyUlvq9ovLcFV1tzvDaf%2B4gxMx4Xh7QKJ7ghpDxh9%2Fh7SaCMZ2ZHFLZeH3GmV5FtL%2BE4%2FspxT5owRplC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23RSV26zXWlL2Tac%2FRWCJvkebQrN4ZDsfWJc8Zhm4UfHldKp6Nl62cd79UgX07PW8vKuibG7hKgvH1vR1AWpazBzURiv9O8c7191pJ%2FhMHATAUjChWEoWHAWC4UCwoCwkEwUKwYCwoCwXEJErrm%2FTU5XVJV1aM4ysOdU8l15H6jRmneZag%2BdU%2FP9i9BPdln5q7fU3LRxIXt%2F%2BVWvJ3mt9g%2Fqk4dFtupjD2%2BMlZK4F2YC9TOWulgDWXJTXS7Lv9gOefJGeotS4E%2BE%2Beh%2FSkhKoD89gZh%2Fa09xheshZP1hutLQfcgm45KAhIE93laXj1fYInVSZTngoPU006Hqyc0jfdJNfdmom0lOdohaLY2R7qi5q32zTSdgqRUpkEhBFFy42pjT8XmOGoCu3R5f1CVUITUkabje3ld4h%2B2gNtZ3Qo86EpOkDpGwOAAS4UkKYYC4UCoWQgVCgWCgWC4UEw4Ew3EIjCIUyW91%2B3qVSE1VSZxumKqtcJL0NMa2%2Fac547%2FBP2X0n6r72%2FlZQfwCcu4tVvf5KGm6vxlSG%2BbsCiPvvqSb5NsW2t%2FXlpJo2SEqqA%2BpurDreMJdLqJydr79XfWRV1eejjXE4l3a9mnbfP3GgJK6wqB7Alu375hkaaZbbnYAdxAAYKjy2XY5dz6KL63OnLoRHYSNhbSvsFjco9kpiLA9BJLbFiB2DC%2BnKo%2BRZZj2ccbK%2Bf4sGTAX0LniVvbDiiODBOr%2BqZrF1UXKvcbWpwlRILxhRmkjG0Y5r%2Bw0MtLjBXYDgBKhSQLBQJhYKBYaBYKCYSBYaFYJBQLBQKhYMBYMBcKhcIkZpU9K1l5kSLYi6qm0rWlpofONabx%2Fi0n0cffou8JP4T%2F47fBNcfFvhmXDnMumu7%2BgaT9NCSPGi2w1ibaDcw1sW9Mcl%2Bp7EBlPn7VLVPt%2FG68qwl4GJoNF716nfBfflhzDWUHXnFNyoIa6phCNHpv6NUZahgltXv9L19P%2Fn2cCS3rGEkDj9b5vlx8KilxkJNG%2FArANQxIkFkSAABrbV3Cfli8y9HuEQE6jSKNKfew6X4%2FT2svGwvCQL%2Fn9BAEziIn6yZzsKTOUOlJC5%2BrZVW3HQRhw5A4AEsFIwoFgoFjuFAshAsFCMFws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206535166763008&segment_index=43" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:32:19 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:32:19 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_zlVo9sSOOSFMpnzV4U4g6A==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:19 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786113897996441; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:19 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "39c115f6270d073e625b567931d2bd50", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19909", - "x-rate-limit-reset": "1587864356", - "x-response-time": "36", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "00ea6b4100dd066f", - "x-tsa-request-body-time": "63", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"ZwZgMZ1fCJvs3wwVfpH2R1JG0Gc%3D\"", - "Expect": null - }, - "body": "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iIGgNmJsYzYifhxycJwAEimf4jZyZVVyVlNewQuldVZKXiTKR5LtoV9WJJ2k7By0qOl2b8UWcxMSV8aXbU2ZuMDgvf7j00KmqvnScw%2FVHulRQ6QZKRlllVd%2B9G57pfLvrmPCgqLF3pwmqfbdCVNQWeNleMvbS8VcDrICqvzp6rjF949rWmzH332NNotm0wskrZY7diXdz11eFO6jyFdlrEZHLunu0e%2Bzu9r89iapFo1Nyyt8NUW0T%2Bfqs1N8Le%2BdF95WddnH0%2FL0dWdsenf5NR3vdNrCXTV2dz0TsY0yn1y7Tuuscqt0sWV027p%2FDvIVlY7Cg0YKe9B5tsDjImnq9lriUT7vChjHQh2g8CJ03GcAEk1JDMGAmFhIGBsJAsFCqFCMVAsFQiR3rj31z31u2ZqKrhRMGKpJxqp5HB8JyTqdl4Jv37wf4sumYuD%2FaOM6KtMEl0vyNCXjv3j1LD1dND6M%2FUM4rX2AUCOV7L0eQJ5p3IweCdh2ncVOB2QXrwi3HdNg5iLd%2Bb9e2Y64X5LRkH8ZPU05vMfC93ab67sqJLlnOSBcSOgtCWNOgQ7%2Bu7ZRAEFFJ5RZcuOC8p%2F0lkZ4%2BB23VFm4aLBZgXQCU5zDLNtU%2B46wr7esAYAHPBFQBCpJUB93H0%2FuiHu2oBOd5VgX7KsWhVVybTTgBwAR4UkCoUCoUFAmCgWHAkCoUEwUUwoCoWCohI%2BeJzVeukvxdOuVyqlQZVRV%2BRocZdPF%2BLd%2FDV1s4HJuiG28TSTpg%2FlAk3J%2FT1yAv%2FsOXvPlPjcl3jo3ufKzvSraST8Xb7nNS%2Fr23gQaLIPHav8DwxloGMHtv%2F76NVc9w9B1OevEBp8voWhUHuyr%2FUNi1h32s%2Fg3%2BWTsdsZC4FEK7nnbMGLSdo2UUVPJiM9rdBgKdJLMFRD%2BwmASESF36ufr%2Bv6f%2BJzKBgApCm8eeON1R6%2FazA%2BqQ8vR7PgROOrwamMnZerpGtoUjdvkhDEqbdUAcBIBSQ7BQKhYqBYSDYKEYKhQLGUQketZeb8cXvXjXOpktMlLqqZEu9VNDkvhax3nhuPf93lq1C%2BQn6NnMXrr0dKqBn4%2Fq%2Fof7jSG0ngZ81q9I7%2Bx%2FOeN%2FUykf6RGj2SfV0Cj5Oj%2FhmwawM9ZZqBFRDvmevs4TIZv8omhQG8LWSjFcHf4Yic9%2FU3Oan%2Fn5T8NTQR2YCgCIdGk6jqR2Nbcpu25BYLWKm2baRFK01Fq1G5vFj9jZrt79gB1ADLl6JseQD2ANZCBO2Y1c%2Fv8KZ4zE3A%2FeEcvo6%2FqkMcCqIte7y0e195RkVRstZauvYDgEsFJQoMhMNAsFAsKAsNBKJCqFAqFgoFgqJxCRNy8fPXHanPU3KtTVGzJHXPUeQ79I8q5R7%2FeOHZRyXaRDrm4xrWkfUF8fIvVKhKovHTseyFcfYc37XjoZuqT33P5%2BDfOOmr8izjR7%2FtrcCb3XtPoPh9Ogw5XxysujF%2Flli97yVqcNcLYxua%2BmSz19T8q8%2BD5SayPsmuzv7djSaAaHyu4lLfSNYK%2Bf9l037n%2Bz0Cbg2gJcAoVPbgV4Mnf%2Bnu93T0jhr4Ar6uvqnjU5jy5OOMQKkR9rD2uxB2EgFTWhk%2FeoTruKJEY3BwAEsFIgoRQsGAoJwoFhQFhINQuFAuFCqFgoFgoFQuFQiRnG%2BOdfpoisl1WqupSVUrcqdb8q8j38rhNq2bod3s0ytT67T6TcY%2BUJl9Xy0EMvj74uC6qT8FL%2BB%2B8q%2FwLfqu8fh92uPZxXWnl6dJZ9Q0FTqPSbLwuc5COsy%2FJTgiPupOx3DZ6HheC1UcZxmthsEWGv9q0GLkh7IrfWHrN9ONVOqidDcO0zrY6v8QrYv817j%2BsvzLlGRUSI40e4qdcedQ5FsBlWvfrIOPw6%2FWz3yd%2B0oIB43ger7foofCQFcqHaC9k0E3rQIq1%2FcDgAABoZBmk4TigV1aF1%2BrklrXd1Ll7auTetd%2FrVX%2BqR7Wv1rqWu%2B1S1x3xPa12rj%2Fa1SfWfta%2FV5PVi6NWpd1fy%2F1qr8spOX8sEfDaVv0qzq9ccr9deisN3asd%2FOtZPyvv9ddzXVCSxd3fxXv2QgZ08B%2B9y%2FLeBL7PW3QNKw3KZKQ6%2BQqqa7Cfl3xr3LPiyQjBS%2BOlbm7lyj%2Fj16X1lzr1X32rkl3Bv8XSFjad96mJnYff4Wx01896opueZ4VJd31ePorHauWX1%2FXKb1eS73XUvPfo0X55FBoPNx%2F6Pd9zWi1fF1ayiL%2FWpbpa%2BX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" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:32:19 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:32:19 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_pRNwpIs0rqtt+nhyxYmdqg==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:19 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786113965614326; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:19 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "395b0371e2fc50f9cf03d627921ca3e2", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19908", - "x-rate-limit-reset": "1587864356", - "x-response-time": "32", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "00f195f000b50623", - "x-tsa-request-body-time": "61", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"cgGQn3hX9hiwo7menxsKREvCvwY%3D\"", - "Expect": null - }, - "body": "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Hg%2B3d8hBZKSH1WE7kk6ttlTgqDgAEqFJAqEgoEhKFhIFgoJgyFBQFBsFBmFDMFROESl4eu%2Fv6E5u8l3su6xTFzUSdDwHDz4zt8Xzz46Z9ODdoP7P0T0vzQHJ2Pk01qfy%2FL0MAaROjEi171nDc0fPmrJJN1SCbccAWuc8%2F03MjTdMAgvXYfBPiEWOBfmTWQ%2BFW9Wet5qg3gXxhArrheGqfcgW5rigf7vHbU0%2BANV8VXUrTI4hHFWZguUI4XXd9X39fbqAKRfkqF%2BMCiuy6RQCMmcsWrVAIcUFYCtGDQBwEkFJAkFCwFAqFwoFkKJCKFAqFAsJAuFQuESu5eM9%2Bvj7XjNKavmRpjcqnEkToeJ%2Fey4t0PtfE1T%2F%2FzeMavyAL98X73BvYZN3yqvbbFlFvMRjq2U081zGS%2Fyo1QEl7F2%2Bnl3cF8UQ4dJNopk927V38jtdnIlIPSfM1Tn1FXy%2FJROCRNV7deMHBqDfq8FcPla99wchJaokpktesIpHtvMBS0ZiED5nm1tf3r3AlJ8S7HAndwdbt%2BICy4vtiTf8syB0ezkAFL0pCxebmnOSXUTjSgS9AHASQUlCQ0HAUE4UCwUDAUEwkEwUGoTCgVCgWGgVEJWc8N8%2BOqr299ZCamCVdbMmtRJoOzR9O3XW779pj62%2BeK%2FNr3Nkl5embVXZo6uOL%2FPv3t%2F%2Fdb8wtqjoZnZx7YrLe8ABp0DgoL5OgZ%2Fe%2FtFBvfdoBNNbDl2Rqp87ldp1fS7%2BWWhy1JTWRqNZ996XMHFVVfspgoniwAYixWItIKMmhCMgItS0oN4eaSSDG8BJCXc5LkBv%2Fuq6xU%2FeFxf7A9ea0lOafyASWmlhmHLcITKOIuUor0WBwBKhSIKFILBQUBYMBYMBQyhQZBUSBUKBYRiEyXvWePHVVNyusNVAk5mErqLWPjfeK9D0b4P%2F%2B48z%2BnHHzhuG6hH1zLrx0Nh3QVa47XWfFOO%2F0RnU%2F32994rKt2rk777dreQnQRSzbG7kN4%2FV61FW8YuAyLU2iOJCluIiIRsupxPfo7LLHdq1s9nUuQFu%2Fgd75tzkFFgAZ2tMYHDUoViwgVid0lKg%2Fqf7X4Cw8N5554fOeuX9YxwvZtjOplqIXJSlfUuKQRxKg4ASgUiC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" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:32:20 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:32:20 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_vI1KjXeGGI3FxMX1nLy+5w==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:20 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786114035721136; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:20 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "294f8cd9ff67736a60d711b50b97effc", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19907", - "x-rate-limit-reset": "1587864356", - "x-response-time": "34", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "00ce83dd00e2ec0e", - "x-tsa-request-body-time": "64", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"QWAfE182LMO14prmP5CpZWU%2BGWU%3D\"", - "Expect": null - }, - "body": "command=APPEND&media_data=600tWQJMiw8tqv5dv%2FnK756PpD0SzNnq%2FDhpb1um37vbVblXnyei%2F%2BCETJaCe%2FdU3dY%2FXfldb0x6ufvryevvlHUyXqvvRt5f%2FzFx2w1ircmhvLpeXxffkJwnejob36vXIr%2Fcn057FBQ4YDfdrvvs51%2FGM%2FXpdfaqcnJnEW3K%2FXup5nFm9JxFz91LXoIsiJLJ%2B64166XR11UX67%2Fo4QX0WOGETzt0nmvhr78QqzfKuXelfaHt81etdxOX5c63Nrb4KUU9o77XWjj1Z35XWLfDX7f5gpy%2F%2F6CbVn9%2FrhL6%2Bufxn01eepS02TVywAEiFJQkFBEFQoFRMGAqGAsGAqFBKRAqFBKEwoFRoFQid64yc3603fMz2243rday6m7yZrgR0Hd9tv8fp5vqX1nbtRa9e89uLDybwGo6pl%2F5Er8Wa%2Fcyae7HrLZ8M34y4OI3HU30U%2BWWe1iueZ259ArjzZKpFzb97OpTgw7HZ8y8nrp%2FHelFbf4poNidxBDlBz8fn1joXjlxtmk5554DXt7YKo%2Bu%2BMItsZE276LuPKYAVGbCxm5RItElNK0UqVL2eZXOLOyA2VBwASoUlCgiGoTCgWEgZCgXCgTCgzCg1CgSCYUCQUCoUCoROqoyvHne%2BO7zqlpuxKyVMviCcBw5H3Hj1e73%2Fr9x1iV38Jc%2BCz1PtL8B%2BKf7dG%2F3VD9f4ulev6v5Zej%2B5jI2h%2Bcu6ZMnK%2Fe3ySa0hnrrXE7tJc%2Bplf3RgSLEeKSed0v7D5rHXDdQ81q4KPyHLzCcjdxkbSF6lLXilwxfhk6ir%2Bq3eusDq9vLDe5%2B4AQ1p2CCn2E0Lqm3EBZPiA6QUUYwcAEqFJCEFBMFBQFgwFgwFCmFgoJRoJQoMwidGuU9%2BOc68a3xUlqTJeZDL4lJOhxfg%2BI%2BHw7fqO9ORdEcj%2BhVYU%2Be%2Fg9EqPLZIbk3w8p9g39NV2T%2FRtuHh%2FFkNjU%2FspVkib7g8HHtqH4CwNrMxH00xU3czkjivAizdcNWOs7DzAXUp9xT%2FGmVud%2BTuZ9%2FELV%2BBFMZ60qsxm%2FtOZHrcF6r%2B91enZD2LfE%2F2XpwJc15i7cqMlIzQI0hMKqXmAzsz7LA4AEoVJBkFBsFAsOAsGAoJhIJgoRRIVQid595rtzec%2B3rjninFUiJTcpOElTQ7fwOTf7n3d9E5Hse8T3%2F%2BlVLvnM1FuX8L2vg2HGvoXkdRqtXsHdXsyucg8KkAaxxvGEJbR2QxB%2BjI89p9EwLmuYkDKjCHb3vtVClumeIN91x1MEui61su13xcMGVn62owtZRvkdu7tQWLr899Sf6%2BA7hitQ3LHlV9M5BnkCaDGEZUkRrcRkF73EFuy3YSL%2FoBwEemf4bKCzUinaWmL1oO04bEqMBYyAYBgSTo3UHrXWfdE0psa09Uvky9kxpw1iWw0ySOrdW37ArWmiM9HYfdo627e%2FVisFV1o%2FBsO8Ley4b5ZkFsiWtblgWM9ByABQLPMG2l50pMpKSmsBEzkuCAeEuclRhGKfTdFP8oJAq2MMl88aYkqHNxkQYvsvt3cpTNzV1gnpck5xwFwmrseDdvAd5C4lWddmYc58MMX9HfZO%2BIOYcMwwzhBrJD4dtaMfDFVJbVp338E9q%2FeglKn59%2B%2B73wMA8kDwRLxLxPnAYTgEm1JQoEgoFQoJgoKAoFwsGAoFgoFgoFQoUgoVQoFQiYrOvXO%2Bq5vd7%2BOadVu5kqlQnSE4Do6vu547%2BN8OfDnOs1o6qAK1Rpva%2B7HhMdKVoQ9cHvtBf2f0Hkeg8DtDogjsJ%2BakR9P8YFThuwsiQeqk5b12kUDDr010T12m%2Fl%2FQfGWwajZ9%2BMRgC%2Fh5M%2FgdNcOqk5BXuU0ijv6Ka0EY%2FzW1uP%2Bn2gC%2FDVHe3apbVPFo7cH9qnGi1B64lRZKpVOUkozWsFN1BUklcxWA4ATBUlCglCgVCwTCwUDAUCwUDAWCgWEglCgSEhGCg1EJmsknfdznXN5xRZV1NyVUTV5croc3HvE7HIHAuX6zavMXB3RBL4o3s3aNf%2FHlfbvGeNhcU%2FYnKTfdRU8tjBBr7CmGcRnT7q3T9rvNaiXx20Lv7Fo4dPgMWGMchQLux%2B1%2BeCE51BDVobD13beSAKFpuJFWEIjcj%2FyIMfT6WpCEUZu8kg9%2Br%2BI01n5%2F5xwjeXc9p93HtgxIDKGw%2FZCMVsI4WLlV0SNoQC9r3IBruDgAAAmdBmlIUigV%2FSE5X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AAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAGGlvZHMAAAAAEICAgAcAT%2F%2F%2FD3%2F%2FAAAGCnRyYWsAAABcdGtoZAAAAAHHyu6nx8ruqAAAAAEAAAAAAAeZUAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAACMAAAAUAAAAAABaZtZGlhAAAAIG1kaGQAAAAAx8rup8fK7qgAAV%2BQAAeZUFXEAAAAAAAhaGRscgAAAAAAAAAAdmlkZQAAAAAAAAAAAAAAAAAAAAVdbWluZgAAABR2bWhkAAAAAQAAAAAAAAAAAAAAJGRpbmYAAAAcZHJlZgAAAAAAAAABAAAADHVybCAAAAABAAAFHXN0YmwAAACrc3RzZAAAAAAAAAABAAAAm2F2YzEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAACMAFAAEgAAABIAAAAAAAAAAEOSlZUL0FWQyBDb2RpbmcAAAAAAAAAAAAAAAAAAAAAAAAY%2F%2F8AAAAzYXZjQwFCwB7%2F4QAbZ0LAHp4hgRhTTUBAQFAAAAMAEAAAAwPI8WLuAQAFaM4GyyAAAAASY29scm5jbGMAAQABAAEAAAAYc3R0cwAAAAAAAAABAAAApgAAC7gAAAKsc3RzegAAAAAAAAAAAAAApgAAVicAAAsgAAAFvAAABeIAAAXBAAAENwAABAcAAAO2AAAGRQAAA3MAAAUSAAADJgAAAukAAAN7AAADSgAAA2sAAAK2AAADTAAAAnoAAALHAAACLgAAAxYAAAImAAACfwAAAewAAAHqAAAB9QAAAesAAAH6AAAB5wAAAfwAAAHdAAABxgAAAa4AAAHIAAABuQAAAZAAAAGTAAABjAAAAdoAAAHCAAAF0AAAB7gAAAZ6AAAJqQAACiwAAAp8AAAMswAACYwAAAlSAAAMBAAADcEAAA90AAAQSAAAEQYAABBhAAAMYwAADDEAAAtCAAAMDQAADzIAAAp7AAANDwAACuAAAAoOAAALawAACHQAAAw2AAAJ5gAABo0AAAT4AAAHigAAB8EAAAnzAAAHxwAACssAAArSAAALdAAADCgAAAqaAAAMYAAADW0AAAw%2BAAAP%2FAAADoIAAAt5AAAN5AAADSQAAAoXAAARqgAAEmUAAA17AAASoAAAE9gAABFJAAAOWQAAEBUAABaBAAAJtAAABusAAAXvAAAFigAAA9cAAAQNAAADuwAABGsAAANAAAADMAAAAt4AAAOuAAAFzwAABGwAAAVpAAAFAAAABqEAAAM1AAAEGgAAA%2FoAAAY9AAAF1gAABGgAAALWAAAEtQAAAtkAAAJ%2FAAACTQAAAn0AAAOMAAACBgAAAgEAAAd%2FAAAF7wAABbgAAAQKAAACmQAAAx0AAAfFAAAFrAAABHgAAAhxAAAImQAACOkAAAiZAAAFcwAAB8cAAAg9AAALWQAACjYAAAa6AAAF%2BQAABy4AAAbrAAAExgAABLoAAAVmAAAEMQAABooAAAbPAAAG%2FgAABJcAAAJDAAAD4gAABAYAAALmAAACawAAAnUAAAAoc3RzYwAAAAAAAAACAAAAAQAAAAQAAAABAAAAKgAAAAIAAAABAAAAuHN0Y28AAAAAAAAAKgAAAKgAAHPmAACL9AAApAgAALdkAADIpQAA19gAAOSlAADsXwAA%2BF8AAQRBAAEfwwABUYUAAYR%2BAAHMpgACA8AAAjxSAAJmdQACihwAArSmAALnZgADIwEAA12sAAOelwAD6mQABCYKAAQ%2BaQAETP8ABGPZAAR%2BQwAEmJsABK2pAAS%2B9wAE15QABO1sAAUOOwAFLckABVnwAAV7ggAFlSsABbPaAAXGZwAAABRzdHNzAAAAAAAAAAEAAAABAAAAsnNkdHAAAAAABERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERAAABn50cmFrAAAAXHRraGQAAAADx8rup8fK7qgAAAACAAAAAAAHpYAAAAAAAAAAAAAAAAABAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAYEbWRpYQAAACBtZGhkAAAAAMfK7qfHyu6oAAC7gAAEFAAVxwAAAAAAIWhkbHIAAAAAAAAAAHNvdW4AAAAAAAAAAAAAAAAAAAAFu21pbmYAAAAQc21oZAAAAAAAAAAAAAAAJGRpbmYAAAAcZHJlZgAAAAAAAAABAAAADHVybCAAAAABAAAFf3N0YmwAAABnc3RzZAAAAAAAAAABAAAAV21wNGEAAAAAAAAAAQAAAAAAAAAAAAEAEAAAAAC7gAAAAAAAM2VzZHMAAAAAA4CAgCIAAAAEgICAFEAVAAEYAAFl8AABRGsFgICAAhGIBoCAgAECAAAAGHN0dHMAAAAAAAAAAQAAAQUAAAQAAAAEKHN0c3oAAAAAAAAAAAAAAQUAAAD3AAAA2wAAAOEAAADlAAAA6QAAAOgAAADwAAAA8QAAAO8AAADYAAAA5gAAAOcAAADpAAAA6wAAAOoAAADoAAAA4QAAAOcAAADXAAAA2gAAANkAAADbAAAA6QAAAO4AAADlAAAA4QAAAOYAAADlAAAA2AAAAN0AAADdAAAA1QAAAOoAAADdAAAA0AAAANYAAADpAAAAvAAAAKsAAACzAAAAtQAAALwAAADOAAAAtAAAALYAAACzAAAAtgAAALcAAAC%2FAAAAtwAAAM0AAADBAAAAugAAAKcAAAC0AAAAsQAAAL4AAADQAAAAugAAALwAAADEAAAAxgAAAMsAAADEAAAAwwAAAMgAAADSAAAA0gAAANYAAAD1AAAA%2BgAAAPYAAAECAAAA%2FAAAAPwAAADuAAAA5gAAAOoAAADqAAAA6AAAAN4AAADfAAAA5wAAAPYAAAD%2FAAABAwAAAPYAAAEIAAABAwAAAP0AAAEFAAABAgAAAQAAAAEUAAABGAAAAP0AAAD7AAABEQAAAQUAAAEFAAABCgAAAQEAAADzAAAA9wAAAPcAAAEBAAABAgAAAPgAAAD4AAAA7wAAAO0AAADjAAAA7AAAAOIAAADoAAAA3AAAAOAAAADzAAAA3wAAAOEAAADPAAAAzgAAANgAAADOAAAAxwAAAM0AAAC3AAAArwAAAMgAAADXAAAA5QAAAOQAAADGAAAA0QAAANUAAADlAAAA2AAAAMgAAAC%2BAAAAvwAAAMsAAADSAAAAyAAAAMoAAACxAAAAowAAAMcAAADcAAAA2QAAAN0AAADRAAAA0gAAAMIAAAC8AAAAsQAAAJsAAACJAAAAogAAAJ8AAAC1AAAApgAAALIAAAC1AAAArgAAALQAAACwAAAAxgAAAMMAAADVAAAA5AAAAPYAAADWAAAA2wAAAMwAAADnAAAA%2BQAAAMsAAADYAAAA1gAAAOQAAADxAAAA5AAAAOYAAADfAAAA7gAAANcAAADHAAAA5wAAAPkAAADtAAAAzwAAAPEAAADmAAAA3AAAAOQAAADvAAAA5QAAAPEAAADjAAAA7AAAAOwAAADzAAAA9QAAAP0AAAELAAABEAAAAREAAAEDAAABAQAAAPsAAAD6AAAA5wAAAOUAAADwAAAA0gAAAOUAAADzAAAA8QAAAPIAAAD%2FAAAA9wAAAO4AAADVAAAA2QAAAOoAAADjAAAA3wAAAPcAAAD%2FAAAA%2BAAAAPoAAAD9AAAA9wAAAPkAAAD7AAAA%2BAAAAPYAAADwAAAA%2FgAAAQIAAADpAAAA7AAAAOwAAADnAAAA6gAAAN4AAADiAAAAyQAAANQAAADUAAAAxwAAAMkAAADIAAAAwQAAAMAAAAC9AAAA3gAAAMsAAADNAAAA1AAAAG0AAAAoc3RzYwAAAAAAAAACAAAAAQAAAAcAAAABAAAAJgAAAAIAAAABAAAAqHN0Y28AAAAAAAAAJgAAbY0AAIWbAACd5AAAsSEAAMKnAADSjgAA344AAPNUAAD%2B6AABGgUAAUrHAAF%2BKAABxaEAAfyJAAI1XAACg2oAAq5iAALhrgADHW0AA1gEAAOZTQAD5LEABCGZAAQ5ZwAEXcYABHgYAASSagAEp2cABLh%2BAATQbAAE5wwABQfGAAVTXAAFdLwABY6ZAAWuGQAFwOsABctHAAAAFnVkdGEAAAAObmFtZVN0ZXJlbwAAAG91ZHRhAAAAZ21ldGEAAAAAAAAAIWhkbHIAAAAAAAAAAG1kaXIAAAAAAAAAAAAAAAAAAAAAOmlsc3QAAAAyqXRvbwAAACpkYXRhAAAAAQAAAABIYW5kQnJha2UgMC45LjQgMjAwOTExMjMwMAAAAIRmcmVlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA%3D%3D&media_id=1254206535166763008&segment_index=46" - }, - "response": { - "status": { - "http_version": "2", - "code": "204", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-security-policy": "default-src 'self'; connect-src 'self'; font-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; frame-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; img-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com data:; media-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; object-src 'none'; script-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; style-src 'self' https:\/\/*.twimg.com https:\/\/twitter.com https:\/\/ton.twitter.com; report-uri https:\/\/twitter.com\/i\/csp_report?a=OBZG6ZTJNRSWE2LSMQ%3D%3D%3D%3D%3D%3D&ro=false;", - "content-type": "text\/html;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:32:21 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:32:21 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_HPbaNZ+DeDAAtrFzHvR9CA==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:21 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786114105175417; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:21 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "204 No Content", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "5faa60936f0095cdada36f89628ae0ec", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "20000", - "x-rate-limit-remaining": "19906", - "x-rate-limit-reset": "1587864356", - "x-response-time": "30", - "x-segmentcount": "0", - "x-totalbytes": "0", - "x-transaction": "00583d5a0012a058", - "x-tsa-request-body-time": "65", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - } - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/upload.twitter.com\/1.1\/media\/upload.json", - "headers": { - "Host": "upload.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"xMvogq%2FzzAEKO8pJIrksDYlKOqk%3D\"", - "Expect": null - }, - "body": "command=FINALIZE&media_id=1254206535166763008" - }, - "response": { - "status": { - "http_version": "2", - "code": "201", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-disposition": "attachment; filename=json.json", - "content-encoding": "gzip", - "content-length": "135", - "content-type": "application\/json;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:32:22 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:32:22 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_qkMgnhcw2O5dlZYspX5K7g==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:22 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786114169332176; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:22 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "201 Created", - "strict-transport-security": "max-age=631138519", - "vary": "Origin", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "bf196b3247af9e6bf4d8fe8f07e205ba", - "x-frame-options": "SAMEORIGIN", - "x-mediaid": "1254206535166763008", - "x-rate-limit-limit": "615", - "x-rate-limit-remaining": "613", - "x-rate-limit-reset": "1587864382", - "x-response-time": "324", - "x-transaction": "007a2eaf00daa375", - "x-tsa-request-body-time": "0", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "1; mode=block" - }, - "body": "{\"media_id\":1254206535166763008,\"media_id_string\":\"1254206535166763008\",\"size\":383631,\"expires_after_secs\":86400,\"video\":{\"video_type\":\"video\\\/mp4\"}}" - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/api.twitter.com\/1.1\/statuses\/update.json", - "headers": { - "Host": "api.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"pWkPa%2BUCAF4iAZkx9QI2IeFUwRI%3D\"", - "Expect": null - }, - "body": "media_ids=1254206535166763008&status=Hello%20World%201587861062" - }, - "response": { - "status": { - "http_version": "2", - "code": "200", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-disposition": "attachment; filename=json.json", - "content-encoding": "gzip", - "content-length": "1240", - "content-type": "application\/json;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:32:22 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:32:22 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_TcHNmSK1nE37GCWbPpQbuQ==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:22 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786114261320282; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:22 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "200 OK", - "strict-transport-security": "max-age=631138519", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "ca0d9e1ce5dd591b36e8b6f2887e1730", - "x-content-type-options": "nosniff", - "x-frame-options": "SAMEORIGIN", - "x-response-time": "167", - "x-transaction": "0070a65d0013f72b", - "x-tsa-request-body-time": "0", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "0" - }, - "body": "{\"created_at\":\"Sun Apr 26 00:32:22 +0000 2020\",\"id\":1254206652397617152,\"id_str\":\"1254206652397617152\",\"text\":\"Hello World 1587861062 https:\\\/\\\/t.co\\\/nQbFmnj7Dq\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[],\"media\":[{\"id\":1254206535166763008,\"id_str\":\"1254206535166763008\",\"indices\":[23,46],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254206535166763008\\\/pu\\\/img\\\/MKS-slO_VH066gld.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254206535166763008\\\/pu\\\/img\\\/MKS-slO_VH066gld.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/nQbFmnj7Dq\",\"display_url\":\"pic.twitter.com\\\/nQbFmnj7Dq\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/oauthlibtest\\\/status\\\/1254206652397617152\\\/video\\\/1\",\"type\":\"photo\",\"sizes\":{\"large\":{\"w\":560,\"h\":320,\"resize\":\"fit\"},\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":560,\"h\":320,\"resize\":\"fit\"},\"medium\":{\"w\":560,\"h\":320,\"resize\":\"fit\"}}}]},\"extended_entities\":{\"media\":[{\"id\":1254206535166763008,\"id_str\":\"1254206535166763008\",\"indices\":[23,46],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254206535166763008\\\/pu\\\/img\\\/MKS-slO_VH066gld.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254206535166763008\\\/pu\\\/img\\\/MKS-slO_VH066gld.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/nQbFmnj7Dq\",\"display_url\":\"pic.twitter.com\\\/nQbFmnj7Dq\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/oauthlibtest\\\/status\\\/1254206652397617152\\\/video\\\/1\",\"type\":\"video\",\"sizes\":{\"large\":{\"w\":560,\"h\":320,\"resize\":\"fit\"},\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":560,\"h\":320,\"resize\":\"fit\"},\"medium\":{\"w\":560,\"h\":320,\"resize\":\"fit\"}},\"video_info\":{\"aspect_ratio\":[7,4],\"duration_millis\":5568,\"variants\":[{\"bitrate\":256000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254206535166763008\\\/pu\\\/vid\\\/314x180\\\/HtzyDH6Gqdl5UDwM.mp4?tag=1\"},{\"content_type\":\"application\\\/x-mpegURL\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254206535166763008\\\/pu\\\/pl\\\/RPouBvpOym-0X8Yr.m3u8?tag=1\"}]},\"additional_media_info\":{\"monetizable\":false}}]},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/twitteroauth.com\\\" rel=\\\"nofollow\\\"\\u003eTwitterOAuth dev\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":93915746,\"id_str\":\"93915746\",\"name\":\"OAuth Library Test\",\"screen_name\":\"oauthlibtest\",\"location\":\"\",\"description\":\"\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":58,\"friends_count\":2,\"listed_count\":6,\"created_at\":\"Tue Dec 01 18:37:44 +0000 2009\",\"favourites_count\":0,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":6,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/sticky\\\/default_profile_images\\\/default_profile_normal.png\",\"profile_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/sticky\\\/default_profile_images\\\/default_profile_normal.png\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":true,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":0,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"en\"}" - } -},{ - "request": { - "method": "POST", - "url": "https:\/\/api.twitter.com\/1.1\/statuses\/destroy\/1254206652397617152.json", - "headers": { - "Host": "api.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"AicdilxiX%2F%2FyTYLn4%2FHVYw7iuiE%3D\"", - "Expect": null - } - }, - "response": { - "status": { - "http_version": "2", - "code": "200", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-disposition": "attachment; filename=json.json", - "content-encoding": "gzip", - "content-length": "1240", - "content-type": "application\/json;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:32:23 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:32:23 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_a6ZVfkcIDM\/aQYmimBf2fw==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:23 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786114334116680; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:32:23 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "200 OK", - "strict-transport-security": "max-age=631138519", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "bf0b263f4d51d45af76df75606016456", - "x-content-type-options": "nosniff", - "x-frame-options": "SAMEORIGIN", - "x-response-time": "54", - "x-transaction": "00c7bdbf003e3a48", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "0" - }, - "body": "{\"created_at\":\"Sun Apr 26 00:32:22 +0000 2020\",\"id\":1254206652397617152,\"id_str\":\"1254206652397617152\",\"text\":\"Hello World 1587861062 https:\\\/\\\/t.co\\\/nQbFmnj7Dq\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[],\"media\":[{\"id\":1254206535166763008,\"id_str\":\"1254206535166763008\",\"indices\":[23,46],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254206535166763008\\\/pu\\\/img\\\/MKS-slO_VH066gld.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254206535166763008\\\/pu\\\/img\\\/MKS-slO_VH066gld.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/nQbFmnj7Dq\",\"display_url\":\"pic.twitter.com\\\/nQbFmnj7Dq\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/oauthlibtest\\\/status\\\/1254206652397617152\\\/video\\\/1\",\"type\":\"photo\",\"sizes\":{\"large\":{\"w\":560,\"h\":320,\"resize\":\"fit\"},\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":560,\"h\":320,\"resize\":\"fit\"},\"medium\":{\"w\":560,\"h\":320,\"resize\":\"fit\"}}}]},\"extended_entities\":{\"media\":[{\"id\":1254206535166763008,\"id_str\":\"1254206535166763008\",\"indices\":[23,46],\"media_url\":\"http:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254206535166763008\\\/pu\\\/img\\\/MKS-slO_VH066gld.jpg\",\"media_url_https\":\"https:\\\/\\\/pbs.twimg.com\\\/ext_tw_video_thumb\\\/1254206535166763008\\\/pu\\\/img\\\/MKS-slO_VH066gld.jpg\",\"url\":\"https:\\\/\\\/t.co\\\/nQbFmnj7Dq\",\"display_url\":\"pic.twitter.com\\\/nQbFmnj7Dq\",\"expanded_url\":\"https:\\\/\\\/twitter.com\\\/oauthlibtest\\\/status\\\/1254206652397617152\\\/video\\\/1\",\"type\":\"video\",\"sizes\":{\"large\":{\"w\":560,\"h\":320,\"resize\":\"fit\"},\"thumb\":{\"w\":150,\"h\":150,\"resize\":\"crop\"},\"small\":{\"w\":560,\"h\":320,\"resize\":\"fit\"},\"medium\":{\"w\":560,\"h\":320,\"resize\":\"fit\"}},\"video_info\":{\"aspect_ratio\":[7,4],\"duration_millis\":5568,\"variants\":[{\"bitrate\":256000,\"content_type\":\"video\\\/mp4\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254206535166763008\\\/pu\\\/vid\\\/314x180\\\/HtzyDH6Gqdl5UDwM.mp4?tag=1\"},{\"content_type\":\"application\\\/x-mpegURL\",\"url\":\"https:\\\/\\\/video.twimg.com\\\/ext_tw_video\\\/1254206535166763008\\\/pu\\\/pl\\\/RPouBvpOym-0X8Yr.m3u8?tag=1\"}]},\"additional_media_info\":{\"monetizable\":false}}]},\"source\":\"\\u003ca href=\\\"https:\\\/\\\/twitteroauth.com\\\" rel=\\\"nofollow\\\"\\u003eTwitterOAuth dev\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"user\":{\"id\":93915746,\"id_str\":\"93915746\",\"name\":\"OAuth Library Test\",\"screen_name\":\"oauthlibtest\",\"location\":\"\",\"description\":\"\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":58,\"friends_count\":2,\"listed_count\":6,\"created_at\":\"Tue Dec 01 18:37:44 +0000 2009\",\"favourites_count\":0,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":6,\"lang\":null,\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/sticky\\\/default_profile_images\\\/default_profile_normal.png\",\"profile_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/sticky\\\/default_profile_images\\\/default_profile_normal.png\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":true,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\"},\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":0,\"favorite_count\":0,\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"en\"}" - } -}] \ No newline at end of file diff --git a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testResetLastResponse.json b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testResetLastResponse.json deleted file mode 100644 index 0637a088a..000000000 --- a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testResetLastResponse.json +++ /dev/null @@ -1 +0,0 @@ -[] \ No newline at end of file diff --git a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testSetOauthToken.json b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testSetOauthToken.json deleted file mode 100644 index 572e6b85c..000000000 --- a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testSetOauthToken.json +++ /dev/null @@ -1,46 +0,0 @@ -[{ - "request": { - "method": "GET", - "url": "https:\/\/api.twitter.com\/1.1\/friendships\/show.json?target_screen_name=twitterapi", - "headers": { - "Host": "api.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"TzPCDLbvxIAlxBqg5Fpf4JZpFJo%3D\"", - "Expect": null - } - }, - "response": { - "status": { - "http_version": "2", - "code": "200", - "message": "" - }, - "headers": { - "cache-control": "no-cache, no-store, must-revalidate, pre-check=0, post-check=0", - "content-disposition": "attachment; filename=json.json", - "content-encoding": "gzip", - "content-length": "246", - "content-type": "application\/json;charset=utf-8", - "date": "Sun, 26 Apr 2020 00:31:09 GMT", - "expires": "Tue, 31 Mar 1981 05:00:00 GMT", - "last-modified": "Sun, 26 Apr 2020 00:31:09 GMT", - "pragma": "no-cache", - "server": "tsa_b", - "set-cookie": "personalization_id=\"v1_1Yr9ogG1fxy1wdDOY63jAw==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:09 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None, lang=en; Path=\/, guest_id=v1%3A158786106956820884; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:09 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None", - "status": "200 OK", - "strict-transport-security": "max-age=631138519", - "x-access-level": "read-write-directmessages", - "x-connection-hash": "e8b1e309982b5c1d1adedc814fa2e6c3", - "x-content-type-options": "nosniff", - "x-frame-options": "SAMEORIGIN", - "x-rate-limit-limit": "180", - "x-rate-limit-remaining": "178", - "x-rate-limit-reset": "1587861610", - "x-response-time": "20", - "x-transaction": "0075ffd2008ff583", - "x-twitter-response-tags": "BouncerCompliant", - "x-xss-protection": "0" - }, - "body": "{\"relationship\":{\"source\":{\"id\":93915746,\"id_str\":\"93915746\",\"screen_name\":\"oauthlibtest\",\"following\":false,\"followed_by\":false,\"live_following\":false,\"following_received\":false,\"following_requested\":false,\"notifications_enabled\":false,\"can_dm\":false,\"blocking\":false,\"blocked_by\":false,\"muting\":false,\"want_retweets\":false,\"all_replies\":false,\"marked_spam\":false},\"target\":{\"id\":6253282,\"id_str\":\"6253282\",\"screen_name\":\"TwitterAPI\",\"following\":false,\"followed_by\":false,\"following_received\":false,\"following_requested\":false}}}" - } -}] \ No newline at end of file diff --git a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testSetProxy.json b/twitter/vendor/abraham/twitteroauth/tests/fixtures/testSetProxy.json deleted file mode 100644 index 6a5c021e4..000000000 --- a/twitter/vendor/abraham/twitteroauth/tests/fixtures/testSetProxy.json +++ /dev/null @@ -1,20 +0,0 @@ -[{ - "request": { - "method": "GET", - "url": "https:\/\/api.twitter.com\/1.1\/account\/verify_credentials.json", - "headers": { - "Host": "api.twitter.com", - "Accept": "application\/json", - "Authorization": "OAuth oauth_version=\"1.0\", oauth_nonce=\"2b67ebbeace76543f356ba8bbd59abde\", oauth_timestamp=\"1587861062\", oauth_consumer_key=\"awJfND4zFGapGOFKfdjg\", oauth_token=\"93915746-KjE3c27dCt8awONxuUAaJ00yishXXwcH5CdLBnO1x\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"ZN1bM0df5EPRy1d7oYcoZfj3Mpw%3D\"", - "Expect": null - } - }, - "response": { - "status": { - "http_version": "1.1", - "code": "200", - "message": "OK" - }, - "body": "HTTP\/2 200 \r\ncache-control: no-cache, no-store, must-revalidate, pre-check=0, post-check=0\r\ncontent-disposition: attachment; filename=json.json\r\ncontent-encoding: gzip\r\ncontent-length: 778\r\ncontent-type: application\/json;charset=utf-8\r\ndate: Sun, 26 Apr 2020 00:31:49 GMT\r\nexpires: Tue, 31 Mar 1981 05:00:00 GMT\r\nlast-modified: Sun, 26 Apr 2020 00:31:49 GMT\r\npragma: no-cache\r\nserver: tsa_a\r\nset-cookie: personalization_id=\"v1_hI7rl+lJjoy5n7HgyNo9LQ==\"; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:49 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None\r\nset-cookie: lang=en; Path=\/\r\nset-cookie: guest_id=v1%3A158786110929931313; Max-Age=63072000; Expires=Tue, 26 Apr 2022 00:31:49 GMT; Path=\/; Domain=.twitter.com; Secure; SameSite=None\r\nstatus: 200 OK\r\nstrict-transport-security: max-age=631138519\r\nx-access-level: read-write-directmessages\r\nx-connection-hash: 18e8b1b5df2ee964aebf8f85055ada9c\r\nx-content-type-options: nosniff\r\nx-frame-options: SAMEORIGIN\r\nx-rate-limit-limit: 75\r\nx-rate-limit-remaining: 72\r\nx-rate-limit-reset: 1587861178\r\nx-response-time: 34\r\nx-transaction: 00716cfd00f6fd8d\r\nx-twitter-response-tags: BouncerExempt\r\nx-twitter-response-tags: BouncerCompliant\r\nx-xss-protection: 0\r\n\r\n{\"id\":93915746,\"id_str\":\"93915746\",\"name\":\"OAuth Library Test\",\"screen_name\":\"oauthlibtest\",\"location\":\"\",\"description\":\"\",\"url\":null,\"entities\":{\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":58,\"friends_count\":2,\"listed_count\":6,\"created_at\":\"Tue Dec 01 18:37:44 +0000 2009\",\"favourites_count\":0,\"utc_offset\":null,\"time_zone\":null,\"geo_enabled\":true,\"verified\":false,\"statuses_count\":1,\"lang\":null,\"status\":{\"created_at\":\"Tue Dec 01 18:38:07 +0000 2009\",\"id\":6242973112,\"id_str\":\"6242973112\",\"text\":\"Test!\",\"truncated\":false,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[]},\"source\":\"\\u003ca href=\\\"http:\\\/\\\/twitter.com\\\" rel=\\\"nofollow\\\"\\u003eTwitter Web Client\\u003c\\\/a\\u003e\",\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"is_quote_status\":false,\"retweet_count\":2258,\"favorite_count\":74,\"favorited\":false,\"retweeted\":false,\"lang\":\"en\"},\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/images\\\/themes\\\/theme1\\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\\/\\\/abs.twimg.com\\\/sticky\\\/default_profile_images\\\/default_profile_normal.png\",\"profile_image_url_https\":\"https:\\\/\\\/abs.twimg.com\\\/sticky\\\/default_profile_images\\\/default_profile_normal.png\",\"profile_link_color\":\"1DA1F2\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":true,\"default_profile_image\":true,\"following\":false,\"follow_request_sent\":false,\"notifications\":false,\"translator_type\":\"none\",\"suspended\":false,\"needs_phone_verification\":false}" - } -}] \ No newline at end of file diff --git a/twitter/vendor/abraham/twitteroauth/tests/kitten.jpg b/twitter/vendor/abraham/twitteroauth/tests/kitten.jpg deleted file mode 100644 index 9f7acf1a629d0a0d489750358ed12dc94a0e4246..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 207808 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

bk+U3 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 z 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 diff --git a/twitter/vendor/abraham/twitteroauth/tests/mocks.php b/twitter/vendor/abraham/twitteroauth/tests/mocks.php deleted file mode 100644 index b31273138..000000000 --- a/twitter/vendor/abraham/twitteroauth/tests/mocks.php +++ /dev/null @@ -1,21 +0,0 @@ -1#ccq=ZwcT?McY6g<5rI2>|96a+r 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 diff --git a/twitter/vendor/autoload.php b/twitter/vendor/autoload.php deleted file mode 100644 index b727d6602..000000000 --- a/twitter/vendor/autoload.php +++ /dev/null @@ -1,7 +0,0 @@ - - * Jordi Boggiano - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Composer\Autoload; - -/** - * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. - * - * $loader = new \Composer\Autoload\ClassLoader(); - * - * // register classes with namespaces - * $loader->add('Symfony\Component', __DIR__.'/component'); - * $loader->add('Symfony', __DIR__.'/framework'); - * - * // activate the autoloader - * $loader->register(); - * - * // to enable searching the include path (eg. for PEAR packages) - * $loader->setUseIncludePath(true); - * - * In this example, if you try to use a class in the Symfony\Component - * namespace or one of its children (Symfony\Component\Console for instance), - * the autoloader will first look for the class under the component/ - * directory, and it will then fallback to the framework/ directory if not - * found before giving up. - * - * This class is loosely based on the Symfony UniversalClassLoader. - * - * @author Fabien Potencier - * @author Jordi Boggiano - * @see http://www.php-fig.org/psr/psr-0/ - * @see http://www.php-fig.org/psr/psr-4/ - */ -class ClassLoader -{ - // PSR-4 - private $prefixLengthsPsr4 = array(); - private $prefixDirsPsr4 = array(); - private $fallbackDirsPsr4 = array(); - - // PSR-0 - private $prefixesPsr0 = array(); - private $fallbackDirsPsr0 = array(); - - private $useIncludePath = false; - private $classMap = array(); - private $classMapAuthoritative = false; - private $missingClasses = array(); - private $apcuPrefix; - - public function getPrefixes() - { - if (!empty($this->prefixesPsr0)) { - return call_user_func_array('array_merge', array_values($this->prefixesPsr0)); - } - - return array(); - } - - public function getPrefixesPsr4() - { - return $this->prefixDirsPsr4; - } - - public function getFallbackDirs() - { - return $this->fallbackDirsPsr0; - } - - public function getFallbackDirsPsr4() - { - return $this->fallbackDirsPsr4; - } - - public function getClassMap() - { - return $this->classMap; - } - - /** - * @param array $classMap Class to filename map - */ - public function addClassMap(array $classMap) - { - if ($this->classMap) { - $this->classMap = array_merge($this->classMap, $classMap); - } else { - $this->classMap = $classMap; - } - } - - /** - * Registers a set of PSR-0 directories for a given prefix, either - * appending or prepending to the ones previously set for this prefix. - * - * @param string $prefix The prefix - * @param array|string $paths The PSR-0 root directories - * @param bool $prepend Whether to prepend the directories - */ - public function add($prefix, $paths, $prepend = false) - { - if (!$prefix) { - if ($prepend) { - $this->fallbackDirsPsr0 = array_merge( - (array) $paths, - $this->fallbackDirsPsr0 - ); - } else { - $this->fallbackDirsPsr0 = array_merge( - $this->fallbackDirsPsr0, - (array) $paths - ); - } - - return; - } - - $first = $prefix[0]; - if (!isset($this->prefixesPsr0[$first][$prefix])) { - $this->prefixesPsr0[$first][$prefix] = (array) $paths; - - return; - } - if ($prepend) { - $this->prefixesPsr0[$first][$prefix] = array_merge( - (array) $paths, - $this->prefixesPsr0[$first][$prefix] - ); - } else { - $this->prefixesPsr0[$first][$prefix] = array_merge( - $this->prefixesPsr0[$first][$prefix], - (array) $paths - ); - } - } - - /** - * Registers a set of PSR-4 directories for a given namespace, either - * appending or prepending to the ones previously set for this namespace. - * - * @param string $prefix The prefix/namespace, with trailing '\\' - * @param array|string $paths The PSR-4 base directories - * @param bool $prepend Whether to prepend the directories - * - * @throws \InvalidArgumentException - */ - public function addPsr4($prefix, $paths, $prepend = false) - { - if (!$prefix) { - // Register directories for the root namespace. - if ($prepend) { - $this->fallbackDirsPsr4 = array_merge( - (array) $paths, - $this->fallbackDirsPsr4 - ); - } else { - $this->fallbackDirsPsr4 = array_merge( - $this->fallbackDirsPsr4, - (array) $paths - ); - } - } elseif (!isset($this->prefixDirsPsr4[$prefix])) { - // Register directories for a new namespace. - $length = strlen($prefix); - if ('\\' !== $prefix[$length - 1]) { - throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); - } - $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; - $this->prefixDirsPsr4[$prefix] = (array) $paths; - } elseif ($prepend) { - // Prepend directories for an already registered namespace. - $this->prefixDirsPsr4[$prefix] = array_merge( - (array) $paths, - $this->prefixDirsPsr4[$prefix] - ); - } else { - // Append directories for an already registered namespace. - $this->prefixDirsPsr4[$prefix] = array_merge( - $this->prefixDirsPsr4[$prefix], - (array) $paths - ); - } - } - - /** - * Registers a set of PSR-0 directories for a given prefix, - * replacing any others previously set for this prefix. - * - * @param string $prefix The prefix - * @param array|string $paths The PSR-0 base directories - */ - public function set($prefix, $paths) - { - if (!$prefix) { - $this->fallbackDirsPsr0 = (array) $paths; - } else { - $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; - } - } - - /** - * Registers a set of PSR-4 directories for a given namespace, - * replacing any others previously set for this namespace. - * - * @param string $prefix The prefix/namespace, with trailing '\\' - * @param array|string $paths The PSR-4 base directories - * - * @throws \InvalidArgumentException - */ - public function setPsr4($prefix, $paths) - { - if (!$prefix) { - $this->fallbackDirsPsr4 = (array) $paths; - } else { - $length = strlen($prefix); - if ('\\' !== $prefix[$length - 1]) { - throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); - } - $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; - $this->prefixDirsPsr4[$prefix] = (array) $paths; - } - } - - /** - * Turns on searching the include path for class files. - * - * @param bool $useIncludePath - */ - public function setUseIncludePath($useIncludePath) - { - $this->useIncludePath = $useIncludePath; - } - - /** - * Can be used to check if the autoloader uses the include path to check - * for classes. - * - * @return bool - */ - public function getUseIncludePath() - { - return $this->useIncludePath; - } - - /** - * Turns off searching the prefix and fallback directories for classes - * that have not been registered with the class map. - * - * @param bool $classMapAuthoritative - */ - public function setClassMapAuthoritative($classMapAuthoritative) - { - $this->classMapAuthoritative = $classMapAuthoritative; - } - - /** - * Should class lookup fail if not found in the current class map? - * - * @return bool - */ - public function isClassMapAuthoritative() - { - return $this->classMapAuthoritative; - } - - /** - * APCu prefix to use to cache found/not-found classes, if the extension is enabled. - * - * @param string|null $apcuPrefix - */ - public function setApcuPrefix($apcuPrefix) - { - $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null; - } - - /** - * The APCu prefix in use, or null if APCu caching is not enabled. - * - * @return string|null - */ - public function getApcuPrefix() - { - return $this->apcuPrefix; - } - - /** - * Registers this instance as an autoloader. - * - * @param bool $prepend Whether to prepend the autoloader or not - */ - public function register($prepend = false) - { - spl_autoload_register(array($this, 'loadClass'), true, $prepend); - } - - /** - * Unregisters this instance as an autoloader. - */ - public function unregister() - { - spl_autoload_unregister(array($this, 'loadClass')); - } - - /** - * Loads the given class or interface. - * - * @param string $class The name of the class - * @return bool|null True if loaded, null otherwise - */ - public function loadClass($class) - { - if ($file = $this->findFile($class)) { - includeFile($file); - - return true; - } - } - - /** - * Finds the path to the file where the class is defined. - * - * @param string $class The name of the class - * - * @return string|false The path if found, false otherwise - */ - public function findFile($class) - { - // class map lookup - if (isset($this->classMap[$class])) { - return $this->classMap[$class]; - } - if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) { - return false; - } - if (null !== $this->apcuPrefix) { - $file = apcu_fetch($this->apcuPrefix.$class, $hit); - if ($hit) { - return $file; - } - } - - $file = $this->findFileWithExtension($class, '.php'); - - // Search for Hack files if we are running on HHVM - if (false === $file && defined('HHVM_VERSION')) { - $file = $this->findFileWithExtension($class, '.hh'); - } - - if (null !== $this->apcuPrefix) { - apcu_add($this->apcuPrefix.$class, $file); - } - - if (false === $file) { - // Remember that this class does not exist. - $this->missingClasses[$class] = true; - } - - return $file; - } - - private function findFileWithExtension($class, $ext) - { - // PSR-4 lookup - $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; - - $first = $class[0]; - if (isset($this->prefixLengthsPsr4[$first])) { - $subPath = $class; - while (false !== $lastPos = strrpos($subPath, '\\')) { - $subPath = substr($subPath, 0, $lastPos); - $search = $subPath . '\\'; - if (isset($this->prefixDirsPsr4[$search])) { - $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); - foreach ($this->prefixDirsPsr4[$search] as $dir) { - if (file_exists($file = $dir . $pathEnd)) { - return $file; - } - } - } - } - } - - // PSR-4 fallback dirs - foreach ($this->fallbackDirsPsr4 as $dir) { - if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { - return $file; - } - } - - // PSR-0 lookup - if (false !== $pos = strrpos($class, '\\')) { - // namespaced class name - $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) - . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); - } else { - // PEAR-like class name - $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; - } - - if (isset($this->prefixesPsr0[$first])) { - foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { - if (0 === strpos($class, $prefix)) { - foreach ($dirs as $dir) { - if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { - return $file; - } - } - } - } - } - - // PSR-0 fallback dirs - foreach ($this->fallbackDirsPsr0 as $dir) { - if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { - return $file; - } - } - - // PSR-0 include paths. - if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { - return $file; - } - - return false; - } -} - -/** - * Scope isolated include. - * - * Prevents access to $this/self from included files. - */ -function includeFile($file) -{ - include $file; -} diff --git a/twitter/vendor/composer/LICENSE b/twitter/vendor/composer/LICENSE deleted file mode 100644 index f27399a04..000000000 --- a/twitter/vendor/composer/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ - -Copyright (c) Nils Adermann, Jordi Boggiano - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - diff --git a/twitter/vendor/composer/autoload_classmap.php b/twitter/vendor/composer/autoload_classmap.php deleted file mode 100644 index 1573664b1..000000000 --- a/twitter/vendor/composer/autoload_classmap.php +++ /dev/null @@ -1,14 +0,0 @@ - $vendorDir . '/jublonet/codebird-php/src/codebird.php', - 'Codebird\\CodebirdAuthException' => $vendorDir . '/jublonet/codebird-php/src/codebird.php', - 'Codebird\\CodebirdCredentialsException' => $vendorDir . '/jublonet/codebird-php/src/codebird.php', - 'Codebird\\CodebirdEndpointException' => $vendorDir . '/jublonet/codebird-php/src/codebird.php', - 'Codebird\\CodebirdMediaException' => $vendorDir . '/jublonet/codebird-php/src/codebird.php', -); diff --git a/twitter/vendor/composer/autoload_namespaces.php b/twitter/vendor/composer/autoload_namespaces.php deleted file mode 100644 index b7fc0125d..000000000 --- a/twitter/vendor/composer/autoload_namespaces.php +++ /dev/null @@ -1,9 +0,0 @@ - array($vendorDir . '/composer/installers/src/Composer/Installers'), - 'Composer\\CaBundle\\' => array($vendorDir . '/composer/ca-bundle/src'), - 'Abraham\\TwitterOAuth\\' => array($vendorDir . '/abraham/twitteroauth/src'), -); diff --git a/twitter/vendor/composer/autoload_real.php b/twitter/vendor/composer/autoload_real.php deleted file mode 100644 index 35a93688c..000000000 --- a/twitter/vendor/composer/autoload_real.php +++ /dev/null @@ -1,55 +0,0 @@ -= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); - if ($useStaticLoader) { - require_once __DIR__ . '/autoload_static.php'; - - call_user_func(\Composer\Autoload\ComposerStaticInitTwitterAddon::getInitializer($loader)); - } else { - $map = require __DIR__ . '/autoload_namespaces.php'; - foreach ($map as $namespace => $path) { - $loader->set($namespace, $path); - } - - $map = require __DIR__ . '/autoload_psr4.php'; - foreach ($map as $namespace => $path) { - $loader->setPsr4($namespace, $path); - } - - $classMap = require __DIR__ . '/autoload_classmap.php'; - if ($classMap) { - $loader->addClassMap($classMap); - } - } - - $loader->register(true); - - return $loader; - } -} diff --git a/twitter/vendor/composer/autoload_static.php b/twitter/vendor/composer/autoload_static.php deleted file mode 100644 index 740109def..000000000 --- a/twitter/vendor/composer/autoload_static.php +++ /dev/null @@ -1,53 +0,0 @@ - - array ( - 'Composer\\Installers\\' => 20, - 'Composer\\CaBundle\\' => 18, - ), - 'A' => - array ( - 'Abraham\\TwitterOAuth\\' => 21, - ), - ); - - public static $prefixDirsPsr4 = array ( - 'Composer\\Installers\\' => - array ( - 0 => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers', - ), - 'Composer\\CaBundle\\' => - array ( - 0 => __DIR__ . '/..' . '/composer/ca-bundle/src', - ), - 'Abraham\\TwitterOAuth\\' => - array ( - 0 => __DIR__ . '/..' . '/abraham/twitteroauth/src', - ), - ); - - public static $classMap = array ( - 'Codebird\\Codebird' => __DIR__ . '/..' . '/jublonet/codebird-php/src/codebird.php', - 'Codebird\\CodebirdAuthException' => __DIR__ . '/..' . '/jublonet/codebird-php/src/codebird.php', - 'Codebird\\CodebirdCredentialsException' => __DIR__ . '/..' . '/jublonet/codebird-php/src/codebird.php', - 'Codebird\\CodebirdEndpointException' => __DIR__ . '/..' . '/jublonet/codebird-php/src/codebird.php', - 'Codebird\\CodebirdMediaException' => __DIR__ . '/..' . '/jublonet/codebird-php/src/codebird.php', - ); - - public static function getInitializer(ClassLoader $loader) - { - return \Closure::bind(function () use ($loader) { - $loader->prefixLengthsPsr4 = ComposerStaticInitTwitterAddon::$prefixLengthsPsr4; - $loader->prefixDirsPsr4 = ComposerStaticInitTwitterAddon::$prefixDirsPsr4; - $loader->classMap = ComposerStaticInitTwitterAddon::$classMap; - - }, null, ClassLoader::class); - } -} diff --git a/twitter/vendor/composer/ca-bundle/LICENSE b/twitter/vendor/composer/ca-bundle/LICENSE deleted file mode 100644 index c5b5220e8..000000000 --- a/twitter/vendor/composer/ca-bundle/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (C) 2016 Composer - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/twitter/vendor/composer/ca-bundle/README.md b/twitter/vendor/composer/ca-bundle/README.md deleted file mode 100644 index d8205ec53..000000000 --- a/twitter/vendor/composer/ca-bundle/README.md +++ /dev/null @@ -1,85 +0,0 @@ -composer/ca-bundle -================== - -Small utility library that lets you find a path to the system CA bundle, -and includes a fallback to the Mozilla CA bundle. - -Originally written as part of [composer/composer](https://github.com/composer/composer), -now extracted and made available as a stand-alone library. - - -Installation ------------- - -Install the latest version with: - -```bash -$ composer require composer/ca-bundle -``` - - -Requirements ------------- - -* PHP 5.3.2 is required but using the latest version of PHP is highly recommended. - - -Basic usage ------------ - -### `Composer\CaBundle\CaBundle` - -- `CaBundle::getSystemCaRootBundlePath()`: Returns the system CA bundle path, or a path to the bundled one as fallback -- `CaBundle::getBundledCaBundlePath()`: Returns the path to the bundled CA file -- `CaBundle::validateCaFile($filename)`: Validates a CA file using openssl_x509_parse only if it is safe to use -- `CaBundle::isOpensslParseSafe()`: Test if it is safe to use the PHP function openssl_x509_parse() -- `CaBundle::reset()`: Resets the static caches - - -#### To use with curl - -```php -$curl = curl_init("https://example.org/"); - -$caPathOrFile = \Composer\CaBundle\CaBundle::getSystemCaRootBundlePath(); -if (is_dir($caPathOrFile)) { - curl_setopt($curl, CURLOPT_CAPATH, $caPathOrFile); -} else { - curl_setopt($curl, CURLOPT_CAINFO, $caPathOrFile); -} - -$result = curl_exec($curl); -``` - -#### To use with php streams - -```php -$opts = array( - 'http' => array( - 'method' => "GET" - ) -); - -$caPathOrFile = \Composer\CaBundle\CaBundle::getSystemCaRootBundlePath(); -if (is_dir($caPathOrFile)) { - $opts['ssl']['capath'] = $caPathOrFile; -} else { - $opts['ssl']['cafile'] = $caPathOrFile; -} - -$context = stream_context_create($opts); -$result = file_get_contents('https://example.com', false, $context); -``` - -#### To use with Guzzle - -```php -$client = new \GuzzleHttp\Client([ - \GuzzleHttp\RequestOptions::VERIFY => \Composer\CaBundle\CaBundle::getSystemCaRootBundlePath() -]); -``` - -License -------- - -composer/ca-bundle is licensed under the MIT License, see the LICENSE file for details. diff --git a/twitter/vendor/composer/ca-bundle/composer.json b/twitter/vendor/composer/ca-bundle/composer.json deleted file mode 100644 index 5213e9763..000000000 --- a/twitter/vendor/composer/ca-bundle/composer.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "name": "composer/ca-bundle", - "description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.", - "type": "library", - "license": "MIT", - "keywords": [ - "cabundle", - "cacert", - "certificate", - "ssl", - "tls" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - } - ], - "support": { - "irc": "irc://irc.freenode.org/composer", - "issues": "https://github.com/composer/ca-bundle/issues" - }, - "require": { - "ext-openssl": "*", - "ext-pcre": "*", - "php": "^5.3.2 || ^7.0 || ^8.0" - }, - "require-dev": { - "symfony/phpunit-bridge": "^4.2 || ^5", - "phpstan/phpstan": "^0.12.55", - "psr/log": "^1.0", - "symfony/process": "^2.5 || ^3.0 || ^4.0 || ^5.0" - }, - "autoload": { - "psr-4": { - "Composer\\CaBundle\\": "src" - } - }, - "autoload-dev": { - "psr-4": { - "Composer\\CaBundle\\": "tests" - } - }, - "extra": { - "branch-alias": { - "dev-main": "1.x-dev" - } - }, - "scripts": { - "test": "SYMFONY_PHPUNIT_REMOVE_RETURN_TYPEHINT=1 vendor/bin/simple-phpunit", - "phpstan": "vendor/bin/phpstan analyse" - } -} diff --git a/twitter/vendor/composer/ca-bundle/res/cacert.pem b/twitter/vendor/composer/ca-bundle/res/cacert.pem deleted file mode 100644 index 264923b3e..000000000 --- a/twitter/vendor/composer/ca-bundle/res/cacert.pem +++ /dev/null @@ -1,3138 +0,0 @@ -## -## Bundle of CA Root Certificates -## -## Certificate data from Mozilla as of: Tue May 25 03:12:05 2021 GMT -## -## 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: -## https://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt -## -## 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. -## -## Conversion done with mk-ca-bundle.pl version 1.28. -## SHA256: e292bd4e2d500c86df45b830d89417be5c42ee670408f1d2c454c63d8a782865 -## - - -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----- - -Entrust.net Premium 2048 Secure Server CA -========================================= ------BEGIN CERTIFICATE----- -MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVzdC5u -ZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxp -bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV -BAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQx -NzUwNTFaFw0yOTA3MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3 -d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTEl -MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5u -ZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A -MIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOL -Gp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSr -hRSGlVuXMlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzW -nLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUi -VBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQABo0IwQDAOBgNVHQ8BAf8E -BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJ -KoZIhvcNAQEFBQADggEBADubj1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPy -T/4xmf3IDExoU8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf -zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5bu/8j72gZyxKT -J1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+bYQLCIt+jerXmCHG8+c8eS9e -nNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/ErfF6adulZkMV8gzURZVE= ------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----- - -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----- - -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----- - -QuoVadis Root CA -================ ------BEGIN CERTIFICATE----- -MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJCTTEZMBcGA1UE -ChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 -eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAz -MTkxODMzMzNaFw0yMTAzMTcxODMzMzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRp -cyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQD -EyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF -AAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Ypli4kVEAkOPcahdxYTMuk -J0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2DrOpm2RgbaIr1VxqYuvXtdj182d6UajtL -F8HVj71lODqV0D1VNk7feVcxKh7YWWVJWCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeL -YzcS19Dsw3sgQUSj7cugF+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWen -AScOospUxbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCCAk4w -PQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVvdmFkaXNvZmZzaG9y -ZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREwggENMIIBCQYJKwYBBAG+WAABMIH7 -MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNlIG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmlj -YXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJs -ZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh -Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYIKwYBBQUHAgEW -Fmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3TKbkGGew5Oanwl4Rqy+/fMIGu -BgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rqy+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkw -FwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0 -aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6 -tlCLMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSkfnIYj9lo -fFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf87C9TqnN7Az10buYWnuul -LsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1RcHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2x -gI4JVrmcGmD+XcHXetwReNDWXcG31a0ymQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi -5upZIof4l/UO/erMkqQWxFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi -5nrQNiOKSnQ2+Q== ------END CERTIFICATE----- - -QuoVadis Root CA 2 -================== ------BEGIN CERTIFICATE----- -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 ------END CERTIFICATE----- - -QuoVadis Root CA 3 -================== ------BEGIN CERTIFICATE----- -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 ------END CERTIFICATE----- - -Security Communication Root CA -============================== ------BEGIN CERTIFICATE----- -MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP -U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw -HhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP -U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw -8yl89f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJDKaVv0uM -DPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9Ms+k2Y7CI9eNqPPYJayX -5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/NQV3Is00qVUarH9oe4kA92819uZKAnDfd -DJZkndwi92SL32HeFZRSFaB9UslLqCHJxrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2 -JChzAgMBAAGjPzA9MB0GA1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYw -DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vGkl3g -0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfrUj94nK9NrvjVT8+a -mCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5Bw+SUEmK3TGXX8npN6o7WWWXlDLJ -s58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJUJRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ -6rBK+1YWc26sTfcioU+tHXotRSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAi -FL39vmwLAw== ------END CERTIFICATE----- - -Sonera Class 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----- - -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----- - -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----- - -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----- - -SwissSign Gold CA - G2 -====================== ------BEGIN CERTIFICATE----- -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 ------END CERTIFICATE----- - -SwissSign Silver CA - G2 -======================== ------BEGIN CERTIFICATE----- -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 ------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----- - -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----- - -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----- - -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----- - -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----- - -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----- - -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----- - -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----- - -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----- - -Autoridad de Certificacion Firmaprofesional CIF A62634068 -========================================================= ------BEGIN CERTIFICATE----- -MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UEBhMCRVMxQjBA -BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2 -MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEyMzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIw -QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB -NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD -Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P -B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY -7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH -ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI -plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX -MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX -LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK -bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU -vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1Ud -EwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNH -DhpkLzCBpgYDVR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp -cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBvACAAZABlACAA -bABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBlAGwAbwBuAGEAIAAwADgAMAAx -ADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx -51tkljYyGOylMnfX40S2wBEqgLk9am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qk -R71kMrv2JYSiJ0L1ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaP -T481PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS3a/DTg4f -Jl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5kSeTy36LssUzAKh3ntLFl -osS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF3dvd6qJ2gHN99ZwExEWN57kci57q13XR -crHedUTnQn3iV2t93Jm8PYMo6oCTjcVMZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoR -saS8I8nkvof/uZS2+F0gStRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTD -KCOM/iczQ0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQBjLMi -6Et8Vcad+qMUu2WFbm5PEn4KPJ2V ------END CERTIFICATE----- - -Izenpe.com -========== ------BEGIN CERTIFICATE----- -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 ------END CERTIFICATE----- - -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----- - -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----- - -Buypass Class 2 Root CA -======================= ------BEGIN CERTIFICATE----- -MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU -QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMiBSb290IENBMB4X -DTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1owTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1 -eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIw -DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1 -g1Lr6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPVL4O2fuPn -9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC911K2GScuVr1QGbNgGE41b -/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHxMlAQTn/0hpPshNOOvEu/XAFOBz3cFIqU -CqTqc/sLUegTBxj6DvEr0VQVfTzh97QZQmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeff -awrbD02TTqigzXsu8lkBarcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgI -zRFo1clrUs3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLiFRhn -Bkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRSP/TizPJhk9H9Z2vX -Uq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN9SG9dKpN6nIDSdvHXx1iY8f93ZHs -M+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxPAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD -VR0OBBYEFMmAd+BikoL1RpzzuvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF -AAOCAgEAU18h9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s -A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3tOluwlN5E40EI -osHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo+fsicdl9sz1Gv7SEr5AcD48S -aq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYd -DnkM/crqJIByw5c/8nerQyIKx+u2DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWD -LfJ6v9r9jv6ly0UsH8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0 -oyLQI+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK75t98biGC -wWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h3PFaTWwyI0PurKju7koS -CTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPzY11aWOIv4x3kqdbQCtCev9eBCfHJxyYN -rJgWVqA= ------END CERTIFICATE----- - -Buypass Class 3 Root CA -======================= ------BEGIN CERTIFICATE----- -MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU -QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMyBSb290IENBMB4X -DTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFowTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1 -eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIw -DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRH -sJ8YZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3EN3coTRiR -5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9tznDDgFHmV0ST9tD+leh -7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX0DJq1l1sDPGzbjniazEuOQAnFN44wOwZ -ZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH -2xc519woe2v1n/MuwU8XKhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV -/afmiSTYzIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvSO1UQ -RwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D34xFMFbG02SrZvPA -Xpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgPK9Dx2hzLabjKSWJtyNBjYt1gD1iq -j6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD -VR0OBBYEFEe4zf/lb+74suwvTg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF -AAOCAgEAACAjQTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV -cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXSIGrs/CIBKM+G -uIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2HJLw5QY33KbmkJs4j1xrG0aG -Q0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsaO5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8 -ZORK15FTAaggiG6cX0S5y2CBNOxv033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2 -KSb12tjE8nVhz36udmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz -6MkEkbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg413OEMXbug -UZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvDu79leNKGef9JOxqDDPDe -eOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq4/g7u9xN12TyUb7mqqta6THuBrxzvxNi -Cp/HuZc= ------END CERTIFICATE----- - -T-TeleSec GlobalRoot Class 3 -============================ ------BEGIN CERTIFICATE----- -MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM -IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU -cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgx -MDAxMTAyOTU2WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz -dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD -ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0GCSqGSIb3 -DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN8ELg63iIVl6bmlQdTQyK -9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/RLyTPWGrTs0NvvAgJ1gORH8EGoel15YU -NpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZF -iP0Zf3WHHx+xGwpzJFu5ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W -0eDrXltMEnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGjQjBA -MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1A/d2O2GCahKqGFPr -AyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOyWL6ukK2YJ5f+AbGwUgC4TeQbIXQb -fsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzT -ucpH9sry9uetuUg/vBa3wW306gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7h -P0HHRwA11fXT91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml -e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4pTpPDpFQUWw== ------END CERTIFICATE----- - -D-TRUST Root Class 3 CA 2 2009 -============================== ------BEGIN CERTIFICATE----- -MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQK -DAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTAe -Fw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NThaME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxE -LVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIw -DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOAD -ER03UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42tSHKXzlA -BF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9RySPocq60vFYJfxLLHLGv -KZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsMlFqVlNpQmvH/pStmMaTJOKDfHR+4CS7z -p+hnUquVH+BGPtikw8paxTGA6Eian5Rp/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUC -AwEAAaOCARowggEWMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ -4PGEMA4GA1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVjdG9y -eS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUyMENBJTIwMiUyMDIw -MDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRlcmV2b2NhdGlvbmxpc3QwQ6BBoD+G -PWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAw -OS5jcmwwDQYJKoZIhvcNAQELBQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm -2H6NMLVwMeniacfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0 -o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4KzCUqNQT4YJEV -dT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8PIWmawomDeCTmGCufsYkl4ph -X5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3YJohw1+qRzT65ysCQblrGXnRl11z+o+I= ------END CERTIFICATE----- - -D-TRUST Root Class 3 CA 2 EV 2009 -================================= ------BEGIN CERTIFICATE----- -MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK -DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw -OTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUwNDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK -DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw -OTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfS -egpnljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM03TP1YtHh -zRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6ZqQTMFexgaDbtCHu39b+T -7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lRp75mpoo6Kr3HGrHhFPC+Oh25z1uxav60 -sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure35 -11H3a6UCAwEAAaOCASQwggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyv -cop9NteaHNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFwOi8v -ZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xhc3MlMjAzJTIwQ0El -MjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1ERT9jZXJ0aWZpY2F0ZXJldm9jYXRp -b25saXN0MEagRKBChkBodHRwOi8vd3d3LmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xh -c3NfM19jYV8yX2V2XzIwMDkuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+ -PPoeUSbrh/Yp3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05 -nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNFCSuGdXzfX2lX -ANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7naxpeG0ILD5EJt/rDiZE4OJudA -NCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqXKVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVv -w9y4AyHqnxbxLFS1 ------END CERTIFICATE----- - -CA Disig Root R2 -================ ------BEGIN CERTIFICATE----- -MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNVBAYTAlNLMRMw -EQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNp -ZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQyMDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sx -EzARBgNVBAcTCkJyYXRpc2xhdmExEzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERp -c2lnIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbC -w3OeNcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNHPWSb6Wia -xswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3Ix2ymrdMxp7zo5eFm1tL7 -A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbeQTg06ov80egEFGEtQX6sx3dOy1FU+16S -GBsEWmjGycT6txOgmLcRK7fWV8x8nhfRyyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqV -g8NTEQxzHQuyRpDRQjrOQG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa -5Beny912H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJQfYE -koopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUDi/ZnWejBBhG93c+A -Ak9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORsnLMOPReisjQS1n6yqEm70XooQL6i -Fh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNV -HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5u -Qu0wDQYJKoZIhvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM -tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqfGopTpti72TVV -sRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkblvdhuDvEK7Z4bLQjb/D907Je -dR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka+elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W8 -1k/BfDxujRNt+3vrMNDcTa/F1balTFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjx -mHHEt38OFdAlab0inSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01 -utI3gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18DrG5gPcFw0 -sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3OszMOl6W8KjptlwlCFtaOg -UxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8xL4ysEr3vQCj8KWefshNPZiTEUxnpHikV -7+ZtsH8tZ/3zbBt1RqPlShfppNcL ------END CERTIFICATE----- - -ACCVRAIZ1 -========= ------BEGIN CERTIFICATE----- -MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UEAwwJQUNDVlJB -SVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQswCQYDVQQGEwJFUzAeFw0xMTA1 -MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQBgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwH -UEtJQUNDVjENMAsGA1UECgwEQUNDVjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4IC -DwAwggIKAoICAQCbqau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gM -jmoYHtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWoG2ioPej0 -RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpAlHPrzg5XPAOBOp0KoVdD -aaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhrIA8wKFSVf+DuzgpmndFALW4ir50awQUZ -0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDG -WuzndN9wrqODJerWx5eHk6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs7 -8yM2x/474KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMOm3WR -5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpacXpkatcnYGMN285J -9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPluUsXQA+xtrn13k/c4LOsOxFwYIRK -Q26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYIKwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRw -Oi8vd3d3LmFjY3YuZXMvZmlsZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEu -Y3J0MB8GCCsGAQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2 -VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeTVfZW6oHlNsyM -Hj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIGCCsGAQUFBwICMIIBFB6CARAA -QQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUAcgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBh -AO0AegAgAGQAZQAgAGwAYQAgAEEAQwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUA -YwBuAG8AbABvAGcA7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBj -AHQAcgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAAQwBQAFMA -IABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUAczAwBggrBgEFBQcCARYk -aHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2MuaHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0 -dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRtaW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2 -MV9kZXIuY3JsMA4GA1UdDwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZI -hvcNAQEFBQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdpD70E -R9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gUJyCpZET/LtZ1qmxN -YEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+mAM/EKXMRNt6GGT6d7hmKG9Ww7Y49 -nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepDvV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJ -TS+xJlsndQAJxGJ3KQhfnlmstn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3 -sCPdK6jT2iWH7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h -I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szAh1xA2syVP1Xg -Nce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xFd3+YJ5oyXSrjhO7FmGYvliAd -3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2HpPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3p -EfbRD0tVNEYqi4Y7 ------END CERTIFICATE----- - -TWCA Global Root CA -=================== ------BEGIN CERTIFICATE----- -MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcxEjAQBgNVBAoT -CVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMTVFdDQSBHbG9iYWwgUm9vdCBD -QTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQK -EwlUQUlXQU4tQ0ExEDAOBgNVBAsTB1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3Qg -Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2C -nJfF10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz0ALfUPZV -r2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfChMBwqoJimFb3u/Rk28OKR -Q4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbHzIh1HrtsBv+baz4X7GGqcXzGHaL3SekV -tTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1W -KKD+u4ZqyPpcC1jcxkt2yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99 -sy2sbZCilaLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYPoA/p -yJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQABDzfuBSO6N+pjWxn -kjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcEqYSjMq+u7msXi7Kx/mzhkIyIqJdI -zshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMC -AQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6g -cFGn90xHNcgL1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn -LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WFH6vPNOw/KP4M -8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNoRI2T9GRwoD2dKAXDOXC4Ynsg -/eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlg -lPx4mI88k1HtQJAH32RjJMtOcQWh15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryP -A9gK8kxkRr05YuWW6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3m -i4TWnsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5jwa19hAM8 -EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWzaGHQRiapIVJpLesux+t3 -zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmyKwbQBM0= ------END CERTIFICATE----- - -TeliaSonera Root CA v1 -====================== ------BEGIN CERTIFICATE----- -MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAwNzEUMBIGA1UE -CgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJvb3QgQ0EgdjEwHhcNMDcxMDE4 -MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYDVQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwW -VGVsaWFTb25lcmEgUm9vdCBDQSB2MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+ -6yfwIaPzaSZVfp3FVRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA -3GV17CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+XZ75Ljo1k -B1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+/jXh7VB7qTCNGdMJjmhn -Xb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxH -oLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkmdtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3 -F0fUTPHSiXk+TT2YqGHeOh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJ -oWjiUIMusDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4pgd7 -gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fsslESl1MpWtTwEhDc -TwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQarMCpgKIv7NHfirZ1fpoeDVNAgMB -AAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qW -DNXr+nuqF+gTEjANBgkqhkiG9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNm -zqjMDfz1mgbldxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx -0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1TjTQpgcmLNkQfW -pb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBedY2gea+zDTYa4EzAvXUYNR0PV -G6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpc -c41teyWRyu5FrgZLAMzTsVlQ2jqIOylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOT -JsjrDNYmiLbAJM+7vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2 -qReWt88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcnHL/EVlP6 -Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVxSK236thZiNSQvxaz2ems -WWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY= ------END CERTIFICATE----- - -E-Tugra Certification Authority -=============================== ------BEGIN CERTIFICATE----- -MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNVBAYTAlRSMQ8w -DQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamls -ZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN -ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMw -NTEyMDk0OFoXDTIzMDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmEx -QDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxl -cmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQD -DB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A -MIICCgKCAgEA4vU/kwVRHoViVF56C/UYB4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vd -hQd2h8y/L5VMzH2nPbxHD5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5K -CKpbknSFQ9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEoq1+g -ElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3Dk14opz8n8Y4e0ypQ -BaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcHfC425lAcP9tDJMW/hkd5s3kc91r0 -E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsutdEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gz -rt48Ue7LE3wBf4QOXVGUnhMMti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAq -jqFGOjGY5RH8zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn -rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUXU8u3Zg5mTPj5 -dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6Jyr+zE7S6E5UMA8GA1UdEwEB -/wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEG -MA0GCSqGSIb3DQEBCwUAA4ICAQAFNzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAK -kEh47U6YA5n+KGCRHTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jO -XKqYGwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c77NCR807 -VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3+GbHeJAAFS6LrVE1Uweo -a2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WKvJUawSg5TB9D0pH0clmKuVb8P7Sd2nCc -dlqMQ1DujjByTd//SffGqWfZbawCEeI6FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEV -KV0jq9BgoRJP3vQXzTLlyb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gT -Dx4JnW2PAJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpDy4Q0 -8ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8dNL/+I5c30jn6PQ0G -C7TbO6Orb1wdtn7os4I07QZcJA== ------END CERTIFICATE----- - -T-TeleSec GlobalRoot Class 2 -============================ ------BEGIN CERTIFICATE----- -MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM -IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU -cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgx -MDAxMTA0MDE0WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz -dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD -ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0GCSqGSIb3 -DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUdAqSzm1nzHoqvNK38DcLZ -SBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiCFoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/F -vudocP05l03Sx5iRUKrERLMjfTlH6VJi1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx970 -2cu+fjOlbpSD8DT6IavqjnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGV -WOHAD3bZwI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGjQjBA -MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/WSA2AHmgoCJrjNXy -YdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhyNsZt+U2e+iKo4YFWz827n+qrkRk4 -r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPACuvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNf -vNoBYimipidx5joifsFvHZVwIEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR -3p1m0IvVVGb6g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN -9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlPBSeOE6Fuwg== ------END CERTIFICATE----- - -Atos TrustedRoot 2011 -===================== ------BEGIN CERTIFICATE----- -MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UEAwwVQXRvcyBU -cnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0xMTA3MDcxNDU4 -MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMMFUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsG -A1UECgwEQXRvczELMAkGA1UEBhMCREUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCV -hTuXbyo7LjvPpvMpNb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr -54rMVD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+SZFhyBH+ -DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ4J7sVaE3IqKHBAUsR320 -HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0Lcp2AMBYHlT8oDv3FdU9T1nSatCQujgKR -z3bFmx5VdJx4IbHwLfELn8LVlhgf8FQieowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7R -l+lwrrw7GWzbITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZ -bNshMBgGA1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB -CwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8jvZfza1zv7v1Apt+h -k6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kPDpFrdRbhIfzYJsdHt6bPWHJxfrrh -TZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pcmaHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a9 -61qn8FYiqTxlVMYVqL2Gns2Dlmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G -3mB/ufNPRJLvKrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed ------END CERTIFICATE----- - -QuoVadis Root CA 1 G3 -===================== ------BEGIN CERTIFICATE----- -MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQELBQAwSDELMAkG -A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv -b3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJN -MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEg -RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakE -PBtVwedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWerNrwU8lm -PNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF34168Xfuw6cwI2H44g4hWf6 -Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh4Pw5qlPafX7PGglTvF0FBM+hSo+LdoIN -ofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXpUhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/l -g6AnhF4EwfWQvTA9xO+oabw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV -7qJZjqlc3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/GKubX -9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSthfbZxbGL0eUQMk1f -iyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KOTk0k+17kBL5yG6YnLUlamXrXXAkg -t3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOtzCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD -AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZI -hvcNAQELBQADggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC -MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2cDMT/uFPpiN3 -GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUNqXsCHKnQO18LwIE6PWThv6ct -Tr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP -+V04ikkwj+3x6xn0dxoxGE1nVGwvb2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh -3jRJjehZrJ3ydlo28hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fa -wx/kNSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNjZgKAvQU6 -O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhpq1467HxpvMc7hU6eFbm0 -FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFtnh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOV -hMJKzRwuJIczYOXD ------END CERTIFICATE----- - -QuoVadis Root CA 2 G3 -===================== ------BEGIN CERTIFICATE----- -MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQELBQAwSDELMAkG -A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv -b3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJN -MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIg -RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFh -ZiFfqq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMWn4rjyduY -NM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ymc5GQYaYDFCDy54ejiK2t -oIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+O7q414AB+6XrW7PFXmAqMaCvN+ggOp+o -MiwMzAkd056OXbxMmO7FGmh77FOm6RQ1o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+l -V0POKa2Mq1W/xPtbAd0jIaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZo -L1NesNKqIcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz8eQQ -sSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43ehvNURG3YBZwjgQQvD -6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l7ZizlWNof/k19N+IxWA1ksB8aRxh -lRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALGcC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTAD -AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZI -hvcNAQELBQADggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66 -AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RCroijQ1h5fq7K -pVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0GaW/ZZGYjeVYg3UQt4XAoeo0L9 -x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4nlv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgz -dWqTHBLmYF5vHX/JHyPLhGGfHoJE+V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6X -U/IyAgkwo1jwDQHVcsaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+Nw -mNtddbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNgKCLjsZWD -zYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeMHVOyToV7BjjHLPj4sHKN -JeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4WSr2Rz0ZiC3oheGe7IUIarFsNMkd7Egr -O3jtZsSOeWmD3n+M ------END CERTIFICATE----- - -QuoVadis Root CA 3 G3 -===================== ------BEGIN CERTIFICATE----- -MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQELBQAwSDELMAkG -A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv -b3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJN -MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMg -RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286 -IxSR/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNuFoM7pmRL -Mon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXRU7Ox7sWTaYI+FrUoRqHe -6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+cra1AdHkrAj80//ogaX3T7mH1urPnMNA3 -I4ZyYUUpSFlob3emLoG+B01vr87ERRORFHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3U -VDmrJqMz6nWB2i3ND0/kA9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f7 -5li59wzweyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634RylsSqi -Md5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBpVzgeAVuNVejH38DM -dyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0QA4XN8f+MFrXBsj6IbGB/kE+V9/Yt -rQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD -AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZI -hvcNAQELBQADggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px -KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnIFUBhynLWcKzS -t/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5WvvoxXqA/4Ti2Tk08HS6IT7SdEQ -TXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFgu/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9Du -DcpmvJRPpq3t/O5jrFc/ZSXPsoaP0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGib -Ih6BJpsQBJFxwAYf3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmD -hPbl8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+DhcI00iX -0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HNPlopNLk9hM6xZdRZkZFW -dSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ywaZWWDYWGWVjUTR939+J399roD1B0y2 -PpxxVJkES/1Y+Zj0 ------END CERTIFICATE----- - -DigiCert Assured ID Root G2 -=========================== ------BEGIN CERTIFICATE----- -MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQG -EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw -IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgw -MTE1MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL -ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIw -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSAn61UQbVH -35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4HteccbiJVMWWXvdMX0h5i89vq -bFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9HpEgjAALAcKxHad3A2m67OeYfcgnDmCXRw -VWmvo2ifv922ebPynXApVfSr/5Vh88lAbx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OP -YLfykqGxvYmJHzDNw6YuYjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+Rn -lTGNAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTO -w0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPIQW5pJ6d1Ee88hjZv -0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I0jJmwYrA8y8678Dj1JGG0VDjA9tz -d29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4GnilmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAW -hsI6yLETcDbYz+70CjTVW0z9B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0M -jomZmWzwPDCvON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo -IhNzbM8m9Yop5w== ------END CERTIFICATE----- - -DigiCert Assured ID Root G3 -=========================== ------BEGIN CERTIFICATE----- -MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQswCQYDVQQGEwJV -UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYD -VQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1 -MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQ -BgcqhkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJfZn4f5dwb -RXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17QRSAPWXYQ1qAk8C3eNvJs -KTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgF -UaFNN6KDec6NHSrkhDAKBggqhkjOPQQDAwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5Fy -YZ5eEJJZVrmDxxDnOOlYJjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy -1vUhZscv6pZjamVFkpUBtA== ------END CERTIFICATE----- - -DigiCert Global Root G2 -======================= ------BEGIN CERTIFICATE----- -MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQG -EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw -HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUx -MjAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 -dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkq -hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI2/Ou8jqJ -kTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx1x7e/dfgy5SDN67sH0NO -3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQq2EGnI/yuum06ZIya7XzV+hdG82MHauV -BJVJ8zUtluNJbd134/tJS7SsVQepj5WztCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyM -UNGPHgm+F6HmIcr9g+UQvIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQAB -o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV5uNu -5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY1Yl9PMWLSn/pvtsr -F9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4NeF22d+mQrvHRAiGfzZ0JFrabA0U -WTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NGFdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBH -QRFXGU7Aj64GxJUTFy8bJZ918rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/ -iyK5S9kJRaTepLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl -MrY= ------END CERTIFICATE----- - -DigiCert Global Root G3 -======================= ------BEGIN CERTIFICATE----- -MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQswCQYDVQQGEwJV -UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYD -VQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAw -MDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5k -aWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0C -AQYFK4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FGfp4tn+6O -YwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPOZ9wj/wMco+I+o0IwQDAP -BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNp -Yim8S8YwCgYIKoZIzj0EAwMDaAAwZQIxAK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y -3maTD/HMsQmP3Wyr+mt/oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34 -VOKa5Vt8sycX ------END CERTIFICATE----- - -DigiCert Trusted Root G4 -======================== ------BEGIN CERTIFICATE----- -MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBiMQswCQYDVQQG -EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEw -HwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1 -MTIwMDAwWjBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0G -CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3yithZwuEp -pz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9o -k3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7Fsa -vOvJz82sNEBfsXpm7nfISKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGY -QJB5w3jHtrHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6 -MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCiEhtm -mnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADMfRyVw4/3IbKyEbe7 -f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFH -dL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8 -oR7FwI+isX4KJpn15GkvmB0t9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud -DwEB/wQEAwIBhjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD -ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2SV1EY+CtnJYY -ZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd+SeuMIW59mdNOj6PWTkiU0Tr -yF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWcfFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy -7zBZLq7gcfJW5GqXb5JQbZaNaHqasjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iah -ixTXTBmyUEFxPT9NcCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN -5r5N0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie4u1Ki7wb -/UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mIr/OSmbaz5mEP0oUA51Aa -5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tK -G48BtieVU+i2iW1bvGjUI+iLUaJW+fCmgKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP -82Z+ ------END CERTIFICATE----- - -COMODO RSA Certification Authority -================================== ------BEGIN CERTIFICATE----- -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 -LaZRfyHBNVOFBkpdn627G190 ------END CERTIFICATE----- - -USERTrust RSA Certification Authority -===================================== ------BEGIN CERTIFICATE----- -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 -Q+6IHdfGjjxDah2nGN59PRbxYvnKkKj9 ------END CERTIFICATE----- - -USERTrust ECC Certification Authority -===================================== ------BEGIN CERTIFICATE----- -MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDELMAkGA1UEBhMC -VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU -aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv -biBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMC -VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU -aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv -biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqfloI+d61SRvU8Za2EurxtW2 -0eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinngo4N+LZfQYcTxmdwlkWOrfzCjtHDix6Ez -nPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0GA1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNV -HQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBB -HU6+4WMBzzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbWRNZu -9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg= ------END CERTIFICATE----- - -GlobalSign ECC Root CA - R4 -=========================== ------BEGIN CERTIFICATE----- -MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEkMCIGA1UECxMb -R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD -EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb -R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD -EwpHbG9iYWxTaWduMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprl -OQcJFspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAwDgYDVR0P -AQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61FuOJAf/sKbvu+M8k8o4TV -MAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGXkPoUVy0D7O48027KqGx2vKLeuwIgJ6iF -JzWbVsaj8kfSt24bAgAXqmemFZHe+pTsewv4n4Q= ------END CERTIFICATE----- - -GlobalSign ECC Root CA - R5 -=========================== ------BEGIN CERTIFICATE----- -MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEkMCIGA1UECxMb -R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD -EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb -R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD -EwpHbG9iYWxTaWduMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6 -SFkc8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8kehOvRnkmS -h5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd -BgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYIKoZIzj0EAwMDaAAwZQIxAOVpEslu28Yx -uglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7 -yFz9SO8NdCKoCOJuxUnOxwy8p2Fp8fc74SrL+SvzZpA3 ------END CERTIFICATE----- - -Staat der Nederlanden EV Root CA -================================ ------BEGIN CERTIFICATE----- -MIIFcDCCA1igAwIBAgIEAJiWjTANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJOTDEeMBwGA1UE -CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSkwJwYDVQQDDCBTdGFhdCBkZXIgTmVkZXJsYW5kZW4g -RVYgUm9vdCBDQTAeFw0xMDEyMDgxMTE5MjlaFw0yMjEyMDgxMTEwMjhaMFgxCzAJBgNVBAYTAk5M -MR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xKTAnBgNVBAMMIFN0YWF0IGRlciBOZWRl -cmxhbmRlbiBFViBSb290IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA48d+ifkk -SzrSM4M1LGns3Amk41GoJSt5uAg94JG6hIXGhaTK5skuU6TJJB79VWZxXSzFYGgEt9nCUiY4iKTW -O0Cmws0/zZiTs1QUWJZV1VD+hq2kY39ch/aO5ieSZxeSAgMs3NZmdO3dZ//BYY1jTw+bbRcwJu+r -0h8QoPnFfxZpgQNH7R5ojXKhTbImxrpsX23Wr9GxE46prfNeaXUmGD5BKyF/7otdBwadQ8QpCiv8 -Kj6GyzyDOvnJDdrFmeK8eEEzduG/L13lpJhQDBXd4Pqcfzho0LKmeqfRMb1+ilgnQ7O6M5HTp5gV -XJrm0w912fxBmJc+qiXbj5IusHsMX/FjqTf5m3VpTCgmJdrV8hJwRVXj33NeN/UhbJCONVrJ0yPr -08C+eKxCKFhmpUZtcALXEPlLVPxdhkqHz3/KRawRWrUgUY0viEeXOcDPusBCAUCZSCELa6fS/ZbV -0b5GnUngC6agIk440ME8MLxwjyx1zNDFjFE7PZQIZCZhfbnDZY8UnCHQqv0XcgOPvZuM5l5Tnrmd -74K74bzickFbIZTTRTeU0d8JOV3nI6qaHcptqAqGhYqCvkIH1vI4gnPah1vlPNOePqc7nvQDs/nx -fRN0Av+7oeX6AHkcpmZBiFxgV6YuCcS6/ZrPpx9Aw7vMWgpVSzs4dlG4Y4uElBbmVvMCAwEAAaNC -MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFP6rAJCYniT8qcwa -ivsnuL8wbqg7MA0GCSqGSIb3DQEBCwUAA4ICAQDPdyxuVr5Os7aEAJSrR8kN0nbHhp8dB9O2tLsI -eK9p0gtJ3jPFrK3CiAJ9Brc1AsFgyb/E6JTe1NOpEyVa/m6irn0F3H3zbPB+po3u2dfOWBfoqSmu -c0iH55vKbimhZF8ZE/euBhD/UcabTVUlT5OZEAFTdfETzsemQUHSv4ilf0X8rLiltTMMgsT7B/Zq -5SWEXwbKwYY5EdtYzXc7LMJMD16a4/CrPmEbUCTCwPTxGfARKbalGAKb12NMcIxHowNDXLldRqAN -b/9Zjr7dn3LDWyvfjFvO5QxGbJKyCqNMVEIYFRIYvdr8unRu/8G2oGTYqV9Vrp9canaW2HNnh/tN -f1zuacpzEPuKqf2evTY4SUmH9A4U8OmHuD+nT3pajnnUk+S7aFKErGzp85hwVXIy+TSrK0m1zSBi -5Dp6Z2Orltxtrpfs/J92VoguZs9btsmksNcFuuEnL5O7Jiqik7Ab846+HUCjuTaPPoIaGl6I6lD4 -WeKDRikL40Rc4ZW2aZCaFG+XroHPaO+Zmr615+F/+PoTRxZMzG0IQOeLeG9QgkRQP2YGiqtDhFZK -DyAthg710tvSeopLzaXoTvFeJiUBWSOgftL2fiFX1ye8FVdMpEbB4IMeDExNH08GGeL5qPQ6gqGy -eUN51q1veieQA6TqJIc/2b3Z6fJfUEkc7uzXLg== ------END CERTIFICATE----- - -IdenTrust Commercial Root CA 1 -============================== ------BEGIN CERTIFICATE----- -MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBKMQswCQYDVQQG -EwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBS -b290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQwMTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzES -MBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENB -IDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ld -hNlT3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU+ehcCuz/ -mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gpS0l4PJNgiCL8mdo2yMKi -1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1bVoE/c40yiTcdCMbXTMTEl3EASX2MN0C -XZ/g1Ue9tOsbobtJSdifWwLziuQkkORiT0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl -3ZBWzvurpWCdxJ35UrCLvYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzy -NeVJSQjKVsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZKdHzV -WYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHTc+XvvqDtMwt0viAg -xGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hvl7yTmvmcEpB4eoCHFddydJxVdHix -uuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5NiGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMC -AQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZI -hvcNAQELBQADggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH -6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwtLRvM7Kqas6pg -ghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93nAbowacYXVKV7cndJZ5t+qnt -ozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3+wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmV -YjzlVYA211QC//G5Xc7UI2/YRYRKW2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUX -feu+h1sXIFRRk0pTAwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/ro -kTLql1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG4iZZRHUe -2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZmUlO+KWA2yUPHGNiiskz -Z2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7R -cGzM7vRX+Bi6hG6H ------END CERTIFICATE----- - -IdenTrust Public Sector Root CA 1 -================================= ------BEGIN CERTIFICATE----- -MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQG -EwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3Rv -ciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcNMzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJV -UzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBS -b290IENBIDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTy -P4o7ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGyRBb06tD6 -Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlSbdsHyo+1W/CD80/HLaXI -rcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF/YTLNiCBWS2ab21ISGHKTN9T0a9SvESf -qy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoS -mJxZZoY+rfGwyj4GD3vwEUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFn -ol57plzy9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9VGxyh -LrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ2fjXctscvG29ZV/v -iDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsVWaFHVCkugyhfHMKiq3IXAAaOReyL -4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gDW/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8B -Af8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMw -DQYJKoZIhvcNAQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj -t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHVDRDtfULAj+7A -mgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9TaDKQGXSc3z1i9kKlT/YPyNt -GtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8GlwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFt -m6/n6J91eEyrRjuazr8FGF1NFTwWmhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMx -NRF4eKLg6TCMf4DfWN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4 -Mhn5+bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJtshquDDI -ajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhAGaQdp/lLQzfcaFpPz+vC -ZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ -3Wl9af0AVqW3rLatt8o+Ae+c ------END CERTIFICATE----- - -Entrust Root Certification Authority - G2 -========================================= ------BEGIN CERTIFICATE----- -MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMCVVMxFjAUBgNV -BAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVy -bXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ug -b25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIw -HhcNMDkwNzA3MTcyNTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoT -DUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMx -OTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25s -eTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwggEi -MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP -/vaCeb9zYQYKpSfYs1/TRU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXz -HHfV1IWNcCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hWwcKU -s/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1U1+cPvQXLOZprE4y -TGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0jaWvYkxN4FisZDQSA/i2jZRjJKRx -AgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ6 -0B7vfec7aVHUbI2fkBJmqzANBgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5Z -iXMRrEPR9RP/jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ -Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v1fN2D807iDgi -nWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4RnAuknZoh8/CbCzB428Hch0P+ -vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmHVHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xO -e4pIb4tF9g== ------END CERTIFICATE----- - -Entrust Root Certification Authority - EC1 -========================================== ------BEGIN CERTIFICATE----- -MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkGA1UEBhMCVVMx -FjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVn -YWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXpl -ZCB1c2Ugb25seTEzMDEGA1UEAxMqRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5 -IC0gRUMxMB4XDTEyMTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYw -FAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2Fs -LXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQg -dXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt -IEVDMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHy -AsWfoPZb1YsGGYZPUxBtByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef -9eNi1KlHBz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE -FLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVCR98crlOZF7ZvHH3h -vxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nXhTcGtXsI/esni0qU+eH6p44mCOh8 -kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G ------END CERTIFICATE----- - -CFCA EV ROOT -============ ------BEGIN CERTIFICATE----- -MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJDTjEwMC4GA1UE -CgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNB -IEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkxMjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEw -MC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQD -DAxDRkNBIEVWIFJPT1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnV -BU03sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpLTIpTUnrD -7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5/ZOkVIBMUtRSqy5J35DN -uF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp7hZZLDRJGqgG16iI0gNyejLi6mhNbiyW -ZXvKWfry4t3uMCz7zEasxGPrb382KzRzEpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7 -xzbh72fROdOXW3NiGUgthxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9f -py25IGvPa931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqotaK8K -gWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNgTnYGmE69g60dWIol -hdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfVPKPtl8MeNPo4+QgO48BdK4PRVmrJ -tqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hvcWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAf -BgNVHSMEGDAWgBTj/i39KNALtbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB -/wQEAwIBBjAdBgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB -ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObTej/tUxPQ4i9q -ecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdLjOztUmCypAbqTuv0axn96/Ua -4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBSESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sG -E5uPhnEFtC+NiWYzKXZUmhH4J/qyP5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfX -BDrDMlI1Dlb4pd19xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjn -aH9dCi77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN5mydLIhy -PDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe/v5WOaHIz16eGWRGENoX -kbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+ZAAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3C -ekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su ------END CERTIFICATE----- - -OISTE WISeKey Global Root GB CA -=============================== ------BEGIN CERTIFICATE----- -MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBtMQswCQYDVQQG -EwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl -ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAw -MzJaFw0zOTEyMDExNTEwMzFaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYD -VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEds -b2JhbCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3HEokKtaX -scriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGxWuR51jIjK+FTzJlFXHtP -rby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk -9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNku7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4o -Qnc/nSMbsrY9gBQHTC5P99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvg -GUpuuy9rM2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB -/zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZI -hvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrghcViXfa43FK8+5/ea4n32cZiZBKpD -dHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0 -VQreUGdNZtGn//3ZwLWoo4rOZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEui -HZeeevJuQHHfaPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic -Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM= ------END CERTIFICATE----- - -SZAFIR ROOT CA2 -=============== ------BEGIN CERTIFICATE----- -MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQELBQAwUTELMAkG -A1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6ZW5pb3dhIFMuQS4xGDAWBgNV -BAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkwNzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJ -BgNVBAYTAlBMMSgwJgYDVQQKDB9LcmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYD -VQQDDA9TWkFGSVIgUk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5Q -qEvNQLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT3PSQ1hNK -DJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw3gAeqDRHu5rr/gsUvTaE -2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr63fE9biCloBK0TXC5ztdyO4mTp4CEHCdJ -ckm1/zuVnsHMyAHs6A6KCpbns6aH5db5BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwi -ieDhZNRnvDF5YTy7ykHNXGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P -AQH/BAQDAgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsFAAOC -AQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw8PRBEew/R40/cof5 -O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOGnXkZ7/e7DDWQw4rtTw/1zBLZpD67 -oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCPoky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul -4+vJhaAlIDf7js4MNIThPIGyd05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6 -+/NNIxuZMzSgLvWpCz/UXeHPhJ/iGcJfitYgHuNztw== ------END CERTIFICATE----- - -Certum Trusted Network CA 2 -=========================== ------BEGIN CERTIFICATE----- -MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCBgDELMAkGA1UE -BhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAlBgNVBAsTHkNlcnR1 -bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29y -ayBDQSAyMCIYDzIwMTExMDA2MDgzOTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQ -TDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENl -cnRpZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENB -IDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWADGSdhhuWZGc/IjoedQF9 -7/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+o -CgCXhVqqndwpyeI1B+twTUrWwbNWuKFBOJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40b -Rr5HMNUuctHFY9rnY3lEfktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2p -uTRZCr+ESv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1mo130 -GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02isx7QBlrd9pPPV3WZ -9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOWOZV7bIBaTxNyxtd9KXpEulKkKtVB -Rgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgezTv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pye -hizKV/Ma5ciSixqClnrDvFASadgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vM -BhBgu4M1t15n3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD -AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZI -hvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQF/xlhMcQSZDe28cmk4gmb3DW -Al45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTfCVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuA -L55MYIR4PSFk1vtBHxgP58l1cb29XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMo -clm2q8KMZiYcdywmdjWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tM -pkT/WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jbAoJnwTnb -w3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksqP/ujmv5zMnHCnsZy4Ypo -J/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Kob7a6bINDd82Kkhehnlt4Fj1F4jNy3eFm -ypnTycUm/Q1oBEauttmbjL4ZvrHG8hnjXALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLX -is7VmFxWlgPF7ncGNf/P5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7 -zAYspsbiDrW5viSP ------END CERTIFICATE----- - -Hellenic Academic and Research Institutions RootCA 2015 -======================================================= ------BEGIN CERTIFICATE----- -MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcT -BkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0 -aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNl -YXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAx -MTIxWjCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMg -QWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNV -BAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIw -MTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDC+Kk/G4n8PDwEXT2QNrCROnk8Zlrv -bTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+eh -iGsxr/CL0BgzuNtFajT0AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+ -6PAQZe104S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06CojXd -FPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV9Cz82XBST3i4vTwr -i5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrDgfgXy5I2XdGj2HUb4Ysn6npIQf1F -GQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2 -fu/Z8VFRfS0myGlZYeCsargqNhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9mu -iNX6hME6wGkoLfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc -Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD -AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVdctA4GGqd83EkVAswDQYJKoZI -hvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0IXtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+ -D1hYc2Ryx+hFjtyp8iY/xnmMsVMIM4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrM -d/K4kPFox/la/vot9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+y -d+2VZ5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/eaj8GsGsVn -82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnhX9izjFk0WaSrT2y7Hxjb -davYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQl033DlZdwJVqwjbDG2jJ9SrcR5q+ss7F -Jej6A7na+RZukYT1HCjI/CbM1xyQVqdfbzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVt -J94Cj8rDtSvK6evIIVM4pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGa -JI7ZjnHKe7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0vm9q -p/UsQu0yrbYhnr68 ------END CERTIFICATE----- - -Hellenic Academic and Research Institutions ECC RootCA 2015 -=========================================================== ------BEGIN CERTIFICATE----- -MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0 -aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9u -cyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJj -aCBJbnN0aXR1dGlvbnMgRUNDIFJvb3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEw -MzcxMlowgaoxCzAJBgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmlj -IEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUQwQgYD -VQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIEVDQyBSb290 -Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKgQehLgoRc4vgxEZmGZE4JJS+dQS8KrjVP -dJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJajq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoK -Vlp8aQuqgAkkbH7BRqNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O -BBYEFLQiC4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaeplSTA -GiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7SofTUwJCA3sS61kFyjn -dc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR ------END CERTIFICATE----- - -ISRG Root X1 -============ ------BEGIN CERTIFICATE----- -MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAwTzELMAkGA1UE -BhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2VhcmNoIEdyb3VwMRUwEwYDVQQD -EwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQG -EwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMT -DElTUkcgUm9vdCBYMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54r -Vygch77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+0TM8ukj1 -3Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6UA5/TR5d8mUgjU+g4rk8K -b4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sWT8KOEUt+zwvo/7V3LvSye0rgTBIlDHCN -Aymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyHB5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ -4Q7e2RCOFvu396j3x+UCB5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf -1b0SHzUvKBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWnOlFu -hjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTnjh8BCNAw1FtxNrQH -usEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbwqHyGO0aoSCqI3Haadr8faqU9GY/r -OPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CIrU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4G -A1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY -9umbbjANBgkqhkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL -ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ3BebYhtF8GaV -0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KKNFtY2PwByVS5uCbMiogziUwt -hDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJw -TdwJx4nLCgdNbOhdjsnvzqvHu7UrTkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nx -e5AW0wdeRlN8NwdCjNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZA -JzVcoyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq4RgqsahD -YVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPAmRGunUHBcnWEvgJBQl9n -JEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57demyPxgcYxn/eR44/KJ4EBs+lVDR3veyJ -m+kXQ99b21/+jh5Xos1AnX5iItreGCc= ------END CERTIFICATE----- - -AC RAIZ FNMT-RCM -================ ------BEGIN CERTIFICATE----- -MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNVBAYT -AkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTAeFw0wODEw -MjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJD -TTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC -ggIBALpxgHpMhm5/yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcf -qQgfBBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAzWHFctPVr -btQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxFtBDXaEAUwED653cXeuYL -j2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z374jNUUeAlz+taibmSXaXvMiwzn15Cou -08YfxGyqxRxqAQVKL9LFwag0Jl1mpdICIfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mw -WsXmo8RZZUc1g16p6DULmbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnT -tOmlcYF7wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peSMKGJ -47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2ZSysV4999AeU14EC -ll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMetUqIJ5G+GR4of6ygnXYMgrwTJbFaa -i0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE -FPd9xf3E6Jobd2Sn9R2gzL+HYJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1o -dHRwOi8vd3d3LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD -nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1RXxlDPiyN8+s -D8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYMLVN0V2Ue1bLdI4E7pWYjJ2cJ -j+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrT -Qfv6MooqtyuGC2mDOL7Nii4LcK2NJpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW -+YJF1DngoABd15jmfZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7 -Ixjp6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp1txyM/1d -8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B9kiABdcPUXmsEKvU7ANm -5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wokRqEIr9baRRmW1FMdW4R58MD3R++Lj8UG -rp1MYp3/RgT408m2ECVAdf4WqslKYIYvuu8wd+RU4riEmViAqhOLUTpPSPaLtrM= ------END CERTIFICATE----- - -Amazon Root CA 1 -================ ------BEGIN CERTIFICATE----- -MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsFADA5MQswCQYD -VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAxMB4XDTE1 -MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv -bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBALJ4gHHKeNXjca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgH -FzZM9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qwIFAGbHrQ -gLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6VOujw5H5SNz/0egwLX0t -dHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L93FcXmn/6pUCyziKrlA4b9v7LWIbxcce -VOF34GfID5yHI9Y/QCB/IIDEgEw+OyQmjgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB -/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3 -DQEBCwUAA4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDIU5PM -CCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUsN+gDS63pYaACbvXy -8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vvo/ufQJVtMVT8QtPHRh8jrdkPSHCa -2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2 -xJNDd2ZhwLnoQdeXeGADbkpyrqXRfboQnoZsG4q5WTP468SQvvG5 ------END CERTIFICATE----- - -Amazon Root CA 2 -================ ------BEGIN CERTIFICATE----- -MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwFADA5MQswCQYD -VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAyMB4XDTE1 -MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv -bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC -ggIBAK2Wny2cSkxKgXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4 -kHbZW0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg1dKmSYXp -N+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K8nu+NQWpEjTj82R0Yiw9 -AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvd -fLC6HM783k81ds8P+HgfajZRRidhW+mez/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAEx -kv8LV/SasrlX6avvDXbR8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSS -btqDT6ZjmUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz7Mt0 -Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6+XUyo05f7O0oYtlN -c/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI0u1ufm8/0i2BWSlmy5A5lREedCf+ -3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSw -DPBMMPQFWAJI/TPlUq9LhONmUjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oA -A7CXDpO8Wqj2LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY -+gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kSk5Nrp+gvU5LE -YFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl7uxMMne0nxrpS10gxdr9HIcW -xkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygmbtmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQ -gj9sAq+uEjonljYE1x2igGOpm/HlurR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbW -aQbLU8uz/mtBzUF+fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoV -Yh63n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE76KlXIx3 -KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H9jVlpNMKVv/1F2Rs76gi -JUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT4PsJYGw= ------END CERTIFICATE----- - -Amazon Root CA 3 -================ ------BEGIN CERTIFICATE----- -MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5MQswCQYDVQQG -EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAzMB4XDTE1MDUy -NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ -MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZB -f8ANm+gBG1bG8lKlui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjr -Zt6jQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSrttvXBp43 -rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkrBqWTrBqYaGFy+uGh0Psc -eGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteMYyRIHN8wfdVoOw== ------END CERTIFICATE----- - -Amazon Root CA 4 -================ ------BEGIN CERTIFICATE----- -MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5MQswCQYDVQQG -EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSA0MB4XDTE1MDUy -NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ -MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN -/sGKe0uoe0ZLY7Bi9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri -83BkM6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV -HQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WBMAoGCCqGSM49BAMDA2gA -MGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlwCkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1 -AE47xDqUEpHJWEadIRNyp4iciuRMStuW1KyLa2tJElMzrdfkviT8tQp21KW8EA== ------END CERTIFICATE----- - -TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1 -============================================= ------BEGIN CERTIFICATE----- -MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIxGDAWBgNVBAcT -D0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxpbXNlbCB2ZSBUZWtub2xvamlr -IEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0wKwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24g -TWVya2V6aSAtIEthbXUgU00xNjA0BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRp -ZmlrYXNpIC0gU3VydW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYD -VQQGEwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXllIEJpbGlt -c2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklUQUsxLTArBgNVBAsTJEth -bXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBTTTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11 -IFNNIFNTTCBLb2sgU2VydGlmaWthc2kgLSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A -MIIBCgKCAQEAr3UwM6q7a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y8 -6Ij5iySrLqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INrN3wc -wv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2XYacQuFWQfw4tJzh0 -3+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/iSIzL+aFCr2lqBs23tPcLG07xxO9 -WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4fAJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQU -ZT/HiobGPN08VFw1+DrtUgxHV8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJ -KoZIhvcNAQELBQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh -AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPfIPP54+M638yc -lNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4lzwDGrpDxpa5RXI4s6ehlj2R -e37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0j -q5Rm+K37DwhuJi1/FwcJsoz7UMCflo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM= ------END CERTIFICATE----- - -GDCA TrustAUTH R5 ROOT -====================== ------BEGIN CERTIFICATE----- -MIIFiDCCA3CgAwIBAgIIfQmX/vBH6nowDQYJKoZIhvcNAQELBQAwYjELMAkGA1UEBhMCQ04xMjAw -BgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZIENPLixMVEQuMR8wHQYDVQQD -DBZHRENBIFRydXN0QVVUSCBSNSBST09UMB4XDTE0MTEyNjA1MTMxNVoXDTQwMTIzMTE1NTk1OVow -YjELMAkGA1UEBhMCQ04xMjAwBgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZ -IENPLixMVEQuMR8wHQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMIICIjANBgkqhkiG9w0B -AQEFAAOCAg8AMIICCgKCAgEA2aMW8Mh0dHeb7zMNOwZ+Vfy1YI92hhJCfVZmPoiC7XJjDp6L3TQs -AlFRwxn9WVSEyfFrs0yw6ehGXTjGoqcuEVe6ghWinI9tsJlKCvLriXBjTnnEt1u9ol2x8kECK62p -OqPseQrsXzrj/e+APK00mxqriCZ7VqKChh/rNYmDf1+uKU49tm7srsHwJ5uu4/Ts765/94Y9cnrr -pftZTqfrlYwiOXnhLQiPzLyRuEH3FMEjqcOtmkVEs7LXLM3GKeJQEK5cy4KOFxg2fZfmiJqwTTQJ -9Cy5WmYqsBebnh52nUpmMUHfP/vFBu8btn4aRjb3ZGM74zkYI+dndRTVdVeSN72+ahsmUPI2JgaQ -xXABZG12ZuGR224HwGGALrIuL4xwp9E7PLOR5G62xDtw8mySlwnNR30YwPO7ng/Wi64HtloPzgsM -R6flPri9fcebNaBhlzpBdRfMK5Z3KpIhHtmVdiBnaM8Nvd/WHwlqmuLMc3GkL30SgLdTMEZeS1SZ -D2fJpcjyIMGC7J0R38IC+xo70e0gmu9lZJIQDSri3nDxGGeCjGHeuLzRL5z7D9Ar7Rt2ueQ5Vfj4 -oR24qoAATILnsn8JuLwwoC8N9VKejveSswoAHQBUlwbgsQfZxw9cZX08bVlX5O2ljelAU58VS6Bx -9hoh49pwBiFYFIeFd3mqgnkCAwEAAaNCMEAwHQYDVR0OBBYEFOLJQJ9NzuiaoXzPDj9lxSmIahlR -MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQDRSVfg -p8xoWLoBDysZzY2wYUWsEe1jUGn4H3++Fo/9nesLqjJHdtJnJO29fDMylyrHBYZmDRd9FBUb1Ov9 -H5r2XpdptxolpAqzkT9fNqyL7FeoPueBihhXOYV0GkLH6VsTX4/5COmSdI31R9KrO9b7eGZONn35 -6ZLpBN79SWP8bfsUcZNnL0dKt7n/HipzcEYwv1ryL3ml4Y0M2fmyYzeMN2WFcGpcWwlyua1jPLHd -+PwyvzeG5LuOmCd+uh8W4XAR8gPfJWIyJyYYMoSf/wA6E7qaTfRPuBRwIrHKK5DOKcFw9C+df/KQ -HtZa37dG/OaG+svgIHZ6uqbL9XzeYqWxi+7egmaKTjowHz+Ay60nugxe19CxVsp3cbK1daFQqUBD -F8Io2c9Si1vIY9RCPqAzekYu9wogRlR+ak8x8YF+QnQ4ZXMn7sZ8uI7XpTrXmKGcjBBV09tL7ECQ -8s1uV9JiDnxXk7Gnbc2dg7sq5+W2O3FYrf3RRbxake5TFW/TRQl1brqQXR4EzzffHqhmsYzmIGrv -/EhOdJhCrylvLmrH+33RZjEizIYAfmaDDEL0vTSSwxrqT8p+ck0LcIymSLumoRT2+1hEmRSuqguT -aaApJUqlyyvdimYHFngVV3Eb7PVHhPOeMTd61X8kreS8/f3MboPoDKi3QWwH3b08hpcv0g== ------END CERTIFICATE----- - -TrustCor RootCert CA-1 -====================== ------BEGIN CERTIFICATE----- -MIIEMDCCAxigAwIBAgIJANqb7HHzA7AZMA0GCSqGSIb3DQEBCwUAMIGkMQswCQYDVQQGEwJQQTEP -MA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3Ig -U3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3Jp -dHkxHzAdBgNVBAMMFlRydXN0Q29yIFJvb3RDZXJ0IENBLTEwHhcNMTYwMjA0MTIzMjE2WhcNMjkx -MjMxMTcyMzE2WjCBpDELMAkGA1UEBhMCUEExDzANBgNVBAgMBlBhbmFtYTEUMBIGA1UEBwwLUGFu -YW1hIENpdHkxJDAiBgNVBAoMG1RydXN0Q29yIFN5c3RlbXMgUy4gZGUgUi5MLjEnMCUGA1UECwwe -VHJ1c3RDb3IgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MR8wHQYDVQQDDBZUcnVzdENvciBSb290Q2Vy -dCBDQS0xMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv463leLCJhJrMxnHQFgKq1mq -jQCj/IDHUHuO1CAmujIS2CNUSSUQIpidRtLByZ5OGy4sDjjzGiVoHKZaBeYei0i/mJZ0PmnK6bV4 -pQa81QBeCQryJ3pS/C3Vseq0iWEk8xoT26nPUu0MJLq5nux+AHT6k61sKZKuUbS701e/s/OojZz0 -JEsq1pme9J7+wH5COucLlVPat2gOkEz7cD+PSiyU8ybdY2mplNgQTsVHCJCZGxdNuWxu72CVEY4h -gLW9oHPY0LJ3xEXqWib7ZnZ2+AYfYW0PVcWDtxBWcgYHpfOxGgMFZA6dWorWhnAbJN7+KIor0Gqw -/Hqi3LJ5DotlDwIDAQABo2MwYTAdBgNVHQ4EFgQU7mtJPHo/DeOxCbeKyKsZn3MzUOcwHwYDVR0j -BBgwFoAU7mtJPHo/DeOxCbeKyKsZn3MzUOcwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC -AYYwDQYJKoZIhvcNAQELBQADggEBACUY1JGPE+6PHh0RU9otRCkZoB5rMZ5NDp6tPVxBb5UrJKF5 -mDo4Nvu7Zp5I/5CQ7z3UuJu0h3U/IJvOcs+hVcFNZKIZBqEHMwwLKeXx6quj7LUKdJDHfXLy11yf -ke+Ri7fc7Waiz45mO7yfOgLgJ90WmMCV1Aqk5IGadZQ1nJBfiDcGrVmVCrDRZ9MZyonnMlo2HD6C -qFqTvsbQZJG2z9m2GM/bftJlo6bEjhcxwft+dtvTheNYsnd6djtsL1Ac59v2Z3kf9YKVmgenFK+P -3CghZwnS1k1aHBkcjndcw5QkPTJrS37UeJSDvjdNzl/HHk484IkzlQsPpTLWPFp5LBk= ------END CERTIFICATE----- - -TrustCor RootCert CA-2 -====================== ------BEGIN CERTIFICATE----- -MIIGLzCCBBegAwIBAgIIJaHfyjPLWQIwDQYJKoZIhvcNAQELBQAwgaQxCzAJBgNVBAYTAlBBMQ8w -DQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5MSQwIgYDVQQKDBtUcnVzdENvciBT -eXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRydXN0Q29yIENlcnRpZmljYXRlIEF1dGhvcml0 -eTEfMB0GA1UEAwwWVHJ1c3RDb3IgUm9vdENlcnQgQ0EtMjAeFw0xNjAyMDQxMjMyMjNaFw0zNDEy -MzExNzI2MzlaMIGkMQswCQYDVQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5h -bWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5U -cnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRydXN0Q29yIFJvb3RDZXJ0 -IENBLTIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCnIG7CKqJiJJWQdsg4foDSq8Gb -ZQWU9MEKENUCrO2fk8eHyLAnK0IMPQo+QVqedd2NyuCb7GgypGmSaIwLgQ5WoD4a3SwlFIIvl9Nk -RvRUqdw6VC0xK5mC8tkq1+9xALgxpL56JAfDQiDyitSSBBtlVkxs1Pu2YVpHI7TYabS3OtB0PAx1 -oYxOdqHp2yqlO/rOsP9+aij9JxzIsekp8VduZLTQwRVtDr4uDkbIXvRR/u8OYzo7cbrPb1nKDOOb -XUm4TOJXsZiKQlecdu/vvdFoqNL0Cbt3Nb4lggjEFixEIFapRBF37120Hapeaz6LMvYHL1cEksr1 -/p3C6eizjkxLAjHZ5DxIgif3GIJ2SDpxsROhOdUuxTTCHWKF3wP+TfSvPd9cW436cOGlfifHhi5q -jxLGhF5DUVCcGZt45vz27Ud+ez1m7xMTiF88oWP7+ayHNZ/zgp6kPwqcMWmLmaSISo5uZk3vFsQP -eSghYA2FFn3XVDjxklb9tTNMg9zXEJ9L/cb4Qr26fHMC4P99zVvh1Kxhe1fVSntb1IVYJ12/+Ctg -rKAmrhQhJ8Z3mjOAPF5GP/fDsaOGM8boXg25NSyqRsGFAnWAoOsk+xWq5Gd/bnc/9ASKL3x74xdh -8N0JqSDIvgmk0H5Ew7IwSjiqqewYmgeCK9u4nBit2uBGF6zPXQIDAQABo2MwYTAdBgNVHQ4EFgQU -2f4hQG6UnrybPZx9mCAZ5YwwYrIwHwYDVR0jBBgwFoAU2f4hQG6UnrybPZx9mCAZ5YwwYrIwDwYD -VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggIBAJ5Fngw7tu/h -Osh80QA9z+LqBrWyOrsGS2h60COXdKcs8AjYeVrXWoSK2BKaG9l9XE1wxaX5q+WjiYndAfrs3fnp -kpfbsEZC89NiqpX+MWcUaViQCqoL7jcjx1BRtPV+nuN79+TMQjItSQzL/0kMmx40/W5ulop5A7Zv -2wnL/V9lFDfhOPXzYRZY5LVtDQsEGz9QLX+zx3oaFoBg+Iof6Rsqxvm6ARppv9JYx1RXCI/hOWB3 -S6xZhBqI8d3LT3jX5+EzLfzuQfogsL7L9ziUwOHQhQ+77Sxzq+3+knYaZH9bDTMJBzN7Bj8RpFxw -PIXAz+OQqIN3+tvmxYxoZxBnpVIt8MSZj3+/0WvitUfW2dCFmU2Umw9Lje4AWkcdEQOsQRivh7dv -DDqPys/cA8GiCcjl/YBeyGBCARsaU1q7N6a3vLqE6R5sGtRk2tRD/pOLS/IseRYQ1JMLiI+h2IYU -RpFHmygk71dSTlxCnKr3Sewn6EAes6aJInKc9Q0ztFijMDvd1GpUk74aTfOTlPf8hAs/hCBcNANE -xdqtvArBAs8e5ZTZ845b2EzwnexhF7sUMlQMAimTHpKG9n/v55IFDlndmQguLvqcAFLTxWYp5KeX -RKQOKIETNcX2b2TmQcTVL8w0RSXPQQCWPUouwpaYT05KnJe32x+SMsj/D1Fu1uwJ ------END CERTIFICATE----- - -TrustCor ECA-1 -============== ------BEGIN CERTIFICATE----- -MIIEIDCCAwigAwIBAgIJAISCLF8cYtBAMA0GCSqGSIb3DQEBCwUAMIGcMQswCQYDVQQGEwJQQTEP -MA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3Ig -U3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3Jp -dHkxFzAVBgNVBAMMDlRydXN0Q29yIEVDQS0xMB4XDTE2MDIwNDEyMzIzM1oXDTI5MTIzMTE3Mjgw -N1owgZwxCzAJBgNVBAYTAlBBMQ8wDQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5 -MSQwIgYDVQQKDBtUcnVzdENvciBTeXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRydXN0Q29y -IENlcnRpZmljYXRlIEF1dGhvcml0eTEXMBUGA1UEAwwOVHJ1c3RDb3IgRUNBLTEwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPj+ARtZ+odnbb3w9U73NjKYKtR8aja+3+XzP4Q1HpGjOR -MRegdMTUpwHmspI+ap3tDvl0mEDTPwOABoJA6LHip1GnHYMma6ve+heRK9jGrB6xnhkB1Zem6g23 -xFUfJ3zSCNV2HykVh0A53ThFEXXQmqc04L/NyFIduUd+Dbi7xgz2c1cWWn5DkR9VOsZtRASqnKmc -p0yJF4OuowReUoCLHhIlERnXDH19MURB6tuvsBzvgdAsxZohmz3tQjtQJvLsznFhBmIhVE5/wZ0+ -fyCMgMsq2JdiyIMzkX2woloPV+g7zPIlstR8L+xNxqE6FXrntl019fZISjZFZtS6mFjBAgMBAAGj -YzBhMB0GA1UdDgQWBBREnkj1zG1I1KBLf/5ZJC+Dl5mahjAfBgNVHSMEGDAWgBREnkj1zG1I1KBL -f/5ZJC+Dl5mahjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsF -AAOCAQEABT41XBVwm8nHc2FvcivUwo/yQ10CzsSUuZQRg2dd4mdsdXa/uwyqNsatR5Nj3B5+1t4u -/ukZMjgDfxT2AHMsWbEhBuH7rBiVDKP/mZb3Kyeb1STMHd3BOuCYRLDE5D53sXOpZCz2HAF8P11F -hcCF5yWPldwX8zyfGm6wyuMdKulMY/okYWLW2n62HGz1Ah3UKt1VkOsqEUc8Ll50soIipX1TH0Xs -J5F95yIW6MBoNtjG8U+ARDL54dHRHareqKucBK+tIA5kmE2la8BIWJZpTdwHjFGTot+fDz2LYLSC -jaoITmJF4PkL0uDgPFveXHEnJcLmA4GLEFPjx1WitJ/X5g== ------END CERTIFICATE----- - -SSL.com Root Certification Authority RSA -======================================== ------BEGIN CERTIFICATE----- -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 -WuuA8ShYIc2wBlX7Jz9TkHCpBB5XJ7k= ------END CERTIFICATE----- - -SSL.com Root Certification Authority ECC -======================================== ------BEGIN CERTIFICATE----- -MIICjTCCAhSgAwIBAgIIdebfy8FoW6gwCgYIKoZIzj0EAwIwfDELMAkGA1UEBhMCVVMxDjAMBgNV -BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24xMTAv -BgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEy -MTgxNDAzWhcNNDEwMjEyMTgxNDAzWjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAO -BgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNv -bSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuBBAAiA2IA -BEVuqVDEpiM2nl8ojRfLliJkP9x6jh3MCLOicSS6jkm5BBtHllirLZXI7Z4INcgn64mMU1jrYor+ -8FsPazFSY0E7ic3s7LaNGdM0B9y7xgZ/wkWV7Mt/qCPgCemB+vNH06NjMGEwHQYDVR0OBBYEFILR -hXMw5zUE044CkvvlpNHEIejNMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUgtGFczDnNQTT -jgKS++Wk0cQh6M0wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2cAMGQCMG/n61kRpGDPYbCW -e+0F+S8Tkdzt5fxQaxFGRrMcIQBiu77D5+jNB5n5DQtdcj7EqgIwH7y6C+IwJPt8bYBVCpk+gA0z -5Wajs6O7pdWLjwkspl1+4vAHCGht0nxpbl/f5Wpl ------END CERTIFICATE----- - -SSL.com EV Root Certification Authority RSA R2 -============================================== ------BEGIN CERTIFICATE----- -MIIF6zCCA9OgAwIBAgIIVrYpzTS8ePYwDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNVBAYTAlVTMQ4w -DAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9u -MTcwNQYDVQQDDC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIy -MB4XDTE3MDUzMTE4MTQzN1oXDTQyMDUzMDE4MTQzN1owgYIxCzAJBgNVBAYTAlVTMQ4wDAYDVQQI -DAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTcwNQYD -VQQDDC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIyMIICIjAN -BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjzZlQOHWTcDXtOlG2mvqM0fNTPl9fb69LT3w23jh -hqXZuglXaO1XPqDQCEGD5yhBJB/jchXQARr7XnAjssufOePPxU7Gkm0mxnu7s9onnQqG6YE3Bf7w -cXHswxzpY6IXFJ3vG2fThVUCAtZJycxa4bH3bzKfydQ7iEGonL3Lq9ttewkfokxykNorCPzPPFTO -Zw+oz12WGQvE43LrrdF9HSfvkusQv1vrO6/PgN3B0pYEW3p+pKk8OHakYo6gOV7qd89dAFmPZiw+ -B6KjBSYRaZfqhbcPlgtLyEDhULouisv3D5oi53+aNxPN8k0TayHRwMwi8qFG9kRpnMphNQcAb9Zh -CBHqurj26bNg5U257J8UZslXWNvNh2n4ioYSA0e/ZhN2rHd9NCSFg83XqpyQGp8hLH94t2S42Oim -9HizVcuE0jLEeK6jj2HdzghTreyI/BXkmg3mnxp3zkyPuBQVPWKchjgGAGYS5Fl2WlPAApiiECto -RHuOec4zSnaqW4EWG7WK2NAAe15itAnWhmMOpgWVSbooi4iTsjQc2KRVbrcc0N6ZVTsj9CLg+Slm -JuwgUHfbSguPvuUCYHBBXtSuUDkiFCbLsjtzdFVHB3mBOagwE0TlBIqulhMlQg+5U8Sb/M3kHN48 -+qvWBkofZ6aYMBzdLNvcGJVXZsb/XItW9XcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNV -HSMEGDAWgBT5YLvU49U09rj1BoAlp3PbRmmonjAdBgNVHQ4EFgQU+WC71OPVNPa49QaAJadz20Zp -qJ4wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBWs47LCp1Jjr+kxJG7ZhcFUZh1 -++VQLHqe8RT6q9OKPv+RKY9ji9i0qVQBDb6Thi/5Sm3HXvVX+cpVHBK+Rw82xd9qt9t1wkclf7nx -Y/hoLVUE0fKNsKTPvDxeH3jnpaAgcLAExbf3cqfeIg29MyVGjGSSJuM+LmOW2puMPfgYCdcDzH2G -guDKBAdRUNf/ktUM79qGn5nX67evaOI5JpS6aLe/g9Pqemc9YmeuJeVy6OLk7K4S9ksrPJ/psEDz -OFSz/bdoyNrGj1E8svuR3Bznm53htw1yj+KkxKl4+esUrMZDBcJlOSgYAsOCsp0FvmXtll9ldDz7 -CTUue5wT/RsPXcdtgTpWD8w74a8CLyKsRspGPKAcTNZEtF4uXBVmCeEmKf7GUmG6sXP/wwyc5Wxq -lD8UykAWlYTzWamsX0xhk23RO8yilQwipmdnRC652dKKQbNmC1r7fSOl8hqw/96bg5Qu0T/fkreR -rwU7ZcegbLHNYhLDkBvjJc40vG93drEQw/cFGsDWr3RiSBd3kmmQYRzelYB0VI8YHMPzA9C/pEN1 -hlMYegouCRw2n5H9gooiS9EOUCXdywMMF8mDAAhONU2Ki+3wApRmLER/y5UnlhetCTCstnEXbosX -9hwJ1C07mKVx01QT2WDz9UtmT/rx7iASjbSsV7FFY6GsdqnC+w== ------END CERTIFICATE----- - -SSL.com EV Root Certification Authority ECC -=========================================== ------BEGIN CERTIFICATE----- -MIIClDCCAhqgAwIBAgIILCmcWxbtBZUwCgYIKoZIzj0EAwIwfzELMAkGA1UEBhMCVVMxDjAMBgNV -BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24xNDAy -BgNVBAMMK1NTTC5jb20gRVYgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYw -MjEyMTgxNTIzWhcNNDEwMjEyMTgxNTIzWjB/MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMx -EDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrU1NM -LmNvbSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuB -BAAiA2IABKoSR5CYG/vvw0AHgyBO8TCCogbR8pKGYfL2IWjKAMTH6kMAVIbc/R/fALhBYlzccBYy -3h+Z1MzFB8gIH2EWB1E9fVwHU+M1OIzfzZ/ZLg1KthkuWnBaBu2+8KGwytAJKaNjMGEwHQYDVR0O -BBYEFFvKXuXe0oGqzagtZFG22XKbl+ZPMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUW8pe -5d7SgarNqC1kUbbZcpuX5k8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2gAMGUCMQCK5kCJ -N+vp1RPZytRrJPOwPYdGWBrssd9v+1a6cGvHOMzosYxPD/fxZ3YOg9AeUY8CMD32IygmTMZgh5Mm -m7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg== ------END CERTIFICATE----- - -GlobalSign Root CA - R6 -======================= ------BEGIN CERTIFICATE----- -MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEgMB4GA1UECxMX -R2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkds -b2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQxMjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9i -YWxTaWduIFJvb3QgQ0EgLSBSNjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFs -U2lnbjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQss -grRIxutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1kZguSgMpE -3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxDaNc9PIrFsmbVkJq3MQbF -vuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJwLnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqM -PKq0pPbzlUoSB239jLKJz9CgYXfIWHSw1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+ -azayOeSsJDa38O+2HBNXk7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05O -WgtH8wY2SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/hbguy -CLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4nWUx2OVvq+aWh2IMP -0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpYrZxCRXluDocZXFSxZba/jJvcE+kN -b7gu3GduyYsRtYQUigAZcIN5kZeR1BonvzceMgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQE -AwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNV -HSMEGDAWgBSubAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN -nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGtIxg93eFyRJa0 -lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr6155wsTLxDKZmOMNOsIeDjHfrY -BzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLjvUYAGm0CuiVdjaExUd1URhxN25mW7xocBFym -Fe944Hn+Xds+qkxV/ZoVqW/hpvvfcDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr -3TsTjxKM4kEaSHpzoHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB1 -0jZpnOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfspA9MRf/T -uTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+vJJUEeKgDu+6B5dpffItK -oZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+t -JDfLRVpOoERIyNiwmcUVhAn21klJwGW45hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA= ------END CERTIFICATE----- - -OISTE WISeKey Global Root GC CA -=============================== ------BEGIN CERTIFICATE----- -MIICaTCCAe+gAwIBAgIQISpWDK7aDKtARb8roi066jAKBggqhkjOPQQDAzBtMQswCQYDVQQGEwJD -SDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEo -MCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQyBDQTAeFw0xNzA1MDkwOTQ4MzRa -Fw00MjA1MDkwOTU4MzNaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQL -ExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2Jh -bCBSb290IEdDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAETOlQwMYPchi82PG6s4nieUqjFqdr -VCTbUf/q9Akkwwsin8tqJ4KBDdLArzHkdIJuyiXZjHWd8dvQmqJLIX4Wp2OQ0jnUsYd4XxiWD1Ab -NTcPasbc2RNNpI6QN+a9WzGRo1QwUjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd -BgNVHQ4EFgQUSIcUrOPDnpBgOtfKie7TrYy0UGYwEAYJKwYBBAGCNxUBBAMCAQAwCgYIKoZIzj0E -AwMDaAAwZQIwJsdpW9zV57LnyAyMjMPdeYwbY9XJUpROTYJKcx6ygISpJcBMWm1JKWB4E+J+SOtk -AjEA2zQgMgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9 ------END CERTIFICATE----- - -GTS Root R1 -=========== ------BEGIN CERTIFICATE----- -MIIFWjCCA0KgAwIBAgIQbkepxUtHDA3sM9CJuRz04TANBgkqhkiG9w0BAQwFADBHMQswCQYDVQQG -EwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJv -b3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAG -A1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIi -MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx -9vaMf/vo27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7wCl7r -aKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjwTcLCeoiKu7rPWRnW -r4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0PfyblqAj+lug8aJRT7oM6iCsVlgmy4HqM -LnXWnOunVmSPlk9orj2XwoSPwLxAwAtcvfaHszVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly -4cpk9+aCEI3oncKKiPo4Zor8Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr -06zqkUspzBmkMiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92 -wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70paDPvOmbsB4om -3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrNVjzRlwW5y0vtOUucxD/SVRNu -JLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD -VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEM -BQADggIBADiWCu49tJYeX++dnAsznyvgyv3SjgofQXSlfKqE1OXyHuY3UjKcC9FhHb8owbZEKTV1 -d5iyfNm9dKyKaOOpMQkpAWBz40d8U6iQSifvS9efk+eCNs6aaAyC58/UEBZvXw6ZXPYfcX3v73sv -fuo21pdwCxXu11xWajOl40k4DLh9+42FpLFZXvRq4d2h9mREruZRgyFmxhE+885H7pwoHyXa/6xm -ld01D1zvICxi/ZG6qcz8WpyTgYMpl0p8WnK0OdC3d8t5/Wk6kjftbjhlRn7pYL15iJdfOBL07q9b -gsiG1eGZbYwE8na6SfZu6W0eX6DvJ4J2QPim01hcDyxC2kLGe4g0x8HYRZvBPsVhHdljUEn2NIVq -4BjFbkerQUIpm/ZgDdIx02OYI5NaAIFItO/Nis3Jz5nu2Z6qNuFoS3FJFDYoOj0dzpqPJeaAcWEr -tXvM+SUWgeExX6GjfhaknBZqlxi9dnKlC54dNuYvoS++cJEPqOba+MSSQGwlfnuzCdyyF62ARPBo -pY+Udf90WuioAnwMCeKpSwughQtiue+hMZL77/ZRBIls6Kl0obsXs7X9SQ98POyDGCBDTtWTurQ0 -sR8WNh8M5mQ5Fkzc4P4dyKliPUDqysU0ArSuiYgzNdwsE3PYJ/HQcu51OyLemGhmW/HGY0dVHLql -CFF1pkgl ------END CERTIFICATE----- - -GTS Root R2 -=========== ------BEGIN CERTIFICATE----- -MIIFWjCCA0KgAwIBAgIQbkepxlqz5yDFMJo/aFLybzANBgkqhkiG9w0BAQwFADBHMQswCQYDVQQG -EwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJv -b3QgUjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAG -A1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIi -MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTuk -k3LvCvptnfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3KgGjSY6Dlo -7JUle3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9BuXvAuMC6C/Pq8tBcKSOWI -m8Wba96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOdre7kRXuJVfeKH2JShBKzwkCX44ofR5Gm -dFrS+LFjKBC4swm4VndAoiaYecb+3yXuPuWgf9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbu -ak7MkogwTZq9TwtImoS1mKPV+3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscsz -cTJGr61K8YzodDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqjx5RW -Ir9qS34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsRnTKaG73Vululycsl -aVNVJ1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0kzCqgc7dGtxRcw1PcOnlthYhGXmy -5okLdWTK1au8CcEYof/UVKGFPP0UJAOyh9OktwIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD -VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEM -BQADggIBALZp8KZ3/p7uC4Gt4cCpx/k1HUCCq+YEtN/L9x0Pg/B+E02NjO7jMyLDOfxA325BS0JT -vhaI8dI4XsRomRyYUpOM52jtG2pzegVATX9lO9ZY8c6DR2Dj/5epnGB3GFW1fgiTz9D2PGcDFWEJ -+YF59exTpJ/JjwGLc8R3dtyDovUMSRqodt6Sm2T4syzFJ9MHwAiApJiS4wGWAqoC7o87xdFtCjMw -c3i5T1QWvwsHoaRc5svJXISPD+AVdyx+Jn7axEvbpxZ3B7DNdehyQtaVhJ2Gg/LkkM0JR9SLA3Da -WsYDQvTtN6LwG1BUSw7YhN4ZKJmBR64JGz9I0cNv4rBgF/XuIwKl2gBbbZCr7qLpGzvpx0QnRY5r -n/WkhLx3+WuXrD5RRaIRpsyF7gpo8j5QOHokYh4XIDdtak23CZvJ/KRY9bb7nE4Yu5UC56Gtmwfu -Nmsk0jmGwZODUNKBRqhfYlcsu2xkiAhu7xNUX90txGdj08+JN7+dIPT7eoOboB6BAFDC5AwiWVIQ -7UNWhwD4FFKnHYuTjKJNRn8nxnGbJN7k2oaLDX5rIMHAnuFl2GqjpuiFizoHCBy69Y9Vmhh1fuXs -gWbRIXOhNUQLgD1bnF5vKheW0YMjiGZt5obicDIvUiLnyOd/xCxgXS/Dr55FBcOEArf9LAhST4Ld -o/DUhgkC ------END CERTIFICATE----- - -GTS Root R3 -=========== ------BEGIN CERTIFICATE----- -MIICDDCCAZGgAwIBAgIQbkepx2ypcyRAiQ8DVd2NHTAKBggqhkjOPQQDAzBHMQswCQYDVQQGEwJV -UzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3Qg -UjMwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UE -ChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcq -hkjOPQIBBgUrgQQAIgNiAAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUU -Rout736GjOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2ADDL24Cej -QjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTB8Sa6oC2uhYHP -0/EqEr24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEAgFukfCPAlaUs3L6JbyO5o91lAFJekazInXJ0 -glMLfalAvWhgxeG4VDvBNhcl2MG9AjEAnjWSdIUlUfUk7GRSJFClH9voy8l27OyCbvWFGFPouOOa -KaqW04MjyaR7YbPMAuhd ------END CERTIFICATE----- - -GTS Root R4 -=========== ------BEGIN CERTIFICATE----- -MIICCjCCAZGgAwIBAgIQbkepyIuUtui7OyrYorLBmTAKBggqhkjOPQQDAzBHMQswCQYDVQQGEwJV -UzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3Qg -UjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UE -ChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcq -hkjOPQIBBgUrgQQAIgNiAATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa -6zzuhXyiQHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/lxKvRHYqj -QjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSATNbrdP9JNqPV -2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNnADBkAjBqUFJ0CMRw3J5QdCHojXohw0+WbhXRIjVhLfoI -N+4Zba3bssx9BzT1YBkstTTZbyACMANxsbqjYAuG7ZoIapVon+Kz4ZNkfF6Tpt95LY2F45TPI11x -zPKwTdb+mciUqXWi4w== ------END CERTIFICATE----- - -UCA Global G2 Root -================== ------BEGIN CERTIFICATE----- -MIIFRjCCAy6gAwIBAgIQXd+x2lqj7V2+WmUgZQOQ7zANBgkqhkiG9w0BAQsFADA9MQswCQYDVQQG -EwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxGzAZBgNVBAMMElVDQSBHbG9iYWwgRzIgUm9vdDAeFw0x -NjAzMTEwMDAwMDBaFw00MDEyMzEwMDAwMDBaMD0xCzAJBgNVBAYTAkNOMREwDwYDVQQKDAhVbmlU -cnVzdDEbMBkGA1UEAwwSVUNBIEdsb2JhbCBHMiBSb290MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A -MIICCgKCAgEAxeYrb3zvJgUno4Ek2m/LAfmZmqkywiKHYUGRO8vDaBsGxUypK8FnFyIdK+35KYmT -oni9kmugow2ifsqTs6bRjDXVdfkX9s9FxeV67HeToI8jrg4aA3++1NDtLnurRiNb/yzmVHqUwCoV -8MmNsHo7JOHXaOIxPAYzRrZUEaalLyJUKlgNAQLx+hVRZ2zA+te2G3/RVogvGjqNO7uCEeBHANBS -h6v7hn4PJGtAnTRnvI3HLYZveT6OqTwXS3+wmeOwcWDcC/Vkw85DvG1xudLeJ1uK6NjGruFZfc8o -LTW4lVYa8bJYS7cSN8h8s+1LgOGN+jIjtm+3SJUIsUROhYw6AlQgL9+/V087OpAh18EmNVQg7Mc/ -R+zvWr9LesGtOxdQXGLYD0tK3Cv6brxzks3sx1DoQZbXqX5t2Okdj4q1uViSukqSKwxW/YDrCPBe -KW4bHAyvj5OJrdu9o54hyokZ7N+1wxrrFv54NkzWbtA+FxyQF2smuvt6L78RHBgOLXMDj6DlNaBa -4kx1HXHhOThTeEDMg5PXCp6dW4+K5OXgSORIskfNTip1KnvyIvbJvgmRlld6iIis7nCs+dwp4wwc -OxJORNanTrAmyPPZGpeRaOrvjUYG0lZFWJo8DA+DuAUlwznPO6Q0ibd5Ei9Hxeepl2n8pndntd97 -8XplFeRhVmUCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O -BBYEFIHEjMz15DD/pQwIX4wVZyF0Ad/fMA0GCSqGSIb3DQEBCwUAA4ICAQATZSL1jiutROTL/7lo -5sOASD0Ee/ojL3rtNtqyzm325p7lX1iPyzcyochltq44PTUbPrw7tgTQvPlJ9Zv3hcU2tsu8+Mg5 -1eRfB70VVJd0ysrtT7q6ZHafgbiERUlMjW+i67HM0cOU2kTC5uLqGOiiHycFutfl1qnN3e92mI0A -Ds0b+gO3joBYDic/UvuUospeZcnWhNq5NXHzJsBPd+aBJ9J3O5oUb3n09tDh05S60FdRvScFDcH9 -yBIw7m+NESsIndTUv4BFFJqIRNow6rSn4+7vW4LVPtateJLbXDzz2K36uGt/xDYotgIVilQsnLAX -c47QN6MUPJiVAAwpBVueSUmxX8fjy88nZY41F7dXyDDZQVu5FLbowg+UMaeUmMxq67XhJ/UQqAHo -jhJi6IjMtX9Gl8CbEGY4GjZGXyJoPd/JxhMnq1MGrKI8hgZlb7F+sSlEmqO6SWkoaY/X5V+tBIZk -bxqgDMUIYs6Ao9Dz7GjevjPHF1t/gMRMTLGmhIrDO7gJzRSBuhjjVFc2/tsvfEehOjPI+Vg7RE+x -ygKJBJYoaMVLuCaJu9YzL1DV/pqJuhgyklTGW+Cd+V7lDSKb9triyCGyYiGqhkCyLmTTX8jjfhFn -RR8F/uOi77Oos/N9j/gMHyIfLXC0uAE0djAA5SN4p1bXUB+K+wb1whnw0A== ------END CERTIFICATE----- - -UCA Extended Validation Root -============================ ------BEGIN CERTIFICATE----- -MIIFWjCCA0KgAwIBAgIQT9Irj/VkyDOeTzRYZiNwYDANBgkqhkiG9w0BAQsFADBHMQswCQYDVQQG -EwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9u -IFJvb3QwHhcNMTUwMzEzMDAwMDAwWhcNMzgxMjMxMDAwMDAwWjBHMQswCQYDVQQGEwJDTjERMA8G -A1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwggIi -MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCpCQcoEwKwmeBkqh5DFnpzsZGgdT6o+uM4AHrs -iWogD4vFsJszA1qGxliG1cGFu0/GnEBNyr7uaZa4rYEwmnySBesFK5pI0Lh2PpbIILvSsPGP2KxF -Rv+qZ2C0d35qHzwaUnoEPQc8hQ2E0B92CvdqFN9y4zR8V05WAT558aopO2z6+I9tTcg1367r3CTu -eUWnhbYFiN6IXSV8l2RnCdm/WhUFhvMJHuxYMjMR83dksHYf5BA1FxvyDrFspCqjc/wJHx4yGVMR -59mzLC52LqGj3n5qiAno8geK+LLNEOfic0CTuwjRP+H8C5SzJe98ptfRr5//lpr1kXuYC3fUfugH -0mK1lTnj8/FtDw5lhIpjVMWAtuCeS31HJqcBCF3RiJ7XwzJE+oJKCmhUfzhTA8ykADNkUVkLo4KR -el7sFsLzKuZi2irbWWIQJUoqgQtHB0MGcIfS+pMRKXpITeuUx3BNr2fVUbGAIAEBtHoIppB/TuDv -B0GHr2qlXov7z1CymlSvw4m6WC31MJixNnI5fkkE/SmnTHnkBVfblLkWU41Gsx2VYVdWf6/wFlth -WG82UBEL2KwrlRYaDh8IzTY0ZRBiZtWAXxQgXy0MoHgKaNYs1+lvK9JKBZP8nm9rZ/+I8U6laUpS -NwXqxhaN0sSZ0YIrO7o1dfdRUVjzyAfd5LQDfwIDAQABo0IwQDAdBgNVHQ4EFgQU2XQ65DA9DfcS -3H5aBZ8eNJr34RQwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQEL -BQADggIBADaNl8xCFWQpN5smLNb7rhVpLGsaGvdftvkHTFnq88nIua7Mui563MD1sC3AO6+fcAUR -ap8lTwEpcOPlDOHqWnzcSbvBHiqB9RZLcpHIojG5qtr8nR/zXUACE/xOHAbKsxSQVBcZEhrxH9cM -aVr2cXj0lH2RC47skFSOvG+hTKv8dGT9cZr4QQehzZHkPJrgmzI5c6sq1WnIeJEmMX3ixzDx/BR4 -dxIOE/TdFpS/S2d7cFOFyrC78zhNLJA5wA3CXWvp4uXViI3WLL+rG761KIcSF3Ru/H38j9CHJrAb -+7lsq+KePRXBOy5nAliRn+/4Qh8st2j1da3Ptfb/EX3C8CSlrdP6oDyp+l3cpaDvRKS+1ujl5BOW -F3sGPjLtx7dCvHaj2GU4Kzg1USEODm8uNBNA4StnDG1KQTAYI1oyVZnJF+A83vbsea0rWBmirSwi -GpWOvpaQXUJXxPkUAzUrHC1RVwinOt4/5Mi0A3PCwSaAuwtCH60NryZy2sy+s6ODWA2CxR9GUeOc -GMyNm43sSet1UNWMKFnKdDTajAshqx7qG+XH/RU+wBeq+yNuJkbL+vmxcmtpzyKEC2IPrNkZAJSi -djzULZrtBJ4tBmIQN1IchXIbJ+XMxjHsN+xjWZsLHXbMfjKaiJUINlK73nZfdklJrX+9ZSCyycEr -dhh2n1ax ------END CERTIFICATE----- - -Certigna Root CA -================ ------BEGIN CERTIFICATE----- -MIIGWzCCBEOgAwIBAgIRAMrpG4nxVQMNo+ZBbcTjpuEwDQYJKoZIhvcNAQELBQAwWjELMAkGA1UE -BhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczEcMBoGA1UECwwTMDAwMiA0ODE0NjMwODEwMDAzNjEZ -MBcGA1UEAwwQQ2VydGlnbmEgUm9vdCBDQTAeFw0xMzEwMDEwODMyMjdaFw0zMzEwMDEwODMyMjda -MFoxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxHDAaBgNVBAsMEzAwMDIgNDgxNDYz -MDgxMDAwMzYxGTAXBgNVBAMMEENlcnRpZ25hIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4IC -DwAwggIKAoICAQDNGDllGlmx6mQWDoyUJJV8g9PFOSbcDO8WV43X2KyjQn+Cyu3NW9sOty3tRQgX -stmzy9YXUnIo245Onoq2C/mehJpNdt4iKVzSs9IGPjA5qXSjklYcoW9MCiBtnyN6tMbaLOQdLNyz -KNAT8kxOAkmhVECe5uUFoC2EyP+YbNDrihqECB63aCPuI9Vwzm1RaRDuoXrC0SIxwoKF0vJVdlB8 -JXrJhFwLrN1CTivngqIkicuQstDuI7pmTLtipPlTWmR7fJj6o0ieD5Wupxj0auwuA0Wv8HT4Ks16 -XdG+RCYyKfHx9WzMfgIhC59vpD++nVPiz32pLHxYGpfhPTc3GGYo0kDFUYqMwy3OU4gkWGQwFsWq -4NYKpkDfePb1BHxpE4S80dGnBs8B92jAqFe7OmGtBIyT46388NtEbVncSVmurJqZNjBBe3YzIoej -wpKGbvlw7q6Hh5UbxHq9MfPU0uWZ/75I7HX1eBYdpnDBfzwboZL7z8g81sWTCo/1VTp2lc5ZmIoJ -lXcymoO6LAQ6l73UL77XbJuiyn1tJslV1c/DeVIICZkHJC1kJWumIWmbat10TWuXekG9qxf5kBdI -jzb5LdXF2+6qhUVB+s06RbFo5jZMm5BX7CO5hwjCxAnxl4YqKE3idMDaxIzb3+KhF1nOJFl0Mdp/ -/TBt2dzhauH8XwIDAQABo4IBGjCCARYwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw -HQYDVR0OBBYEFBiHVuBud+4kNTxOc5of1uHieX4rMB8GA1UdIwQYMBaAFBiHVuBud+4kNTxOc5of -1uHieX4rMEQGA1UdIAQ9MDswOQYEVR0gADAxMC8GCCsGAQUFBwIBFiNodHRwczovL3d3d3cuY2Vy -dGlnbmEuZnIvYXV0b3JpdGVzLzBtBgNVHR8EZjBkMC+gLaArhilodHRwOi8vY3JsLmNlcnRpZ25h -LmZyL2NlcnRpZ25hcm9vdGNhLmNybDAxoC+gLYYraHR0cDovL2NybC5kaGlteW90aXMuY29tL2Nl -cnRpZ25hcm9vdGNhLmNybDANBgkqhkiG9w0BAQsFAAOCAgEAlLieT/DjlQgi581oQfccVdV8AOIt -OoldaDgvUSILSo3L6btdPrtcPbEo/uRTVRPPoZAbAh1fZkYJMyjhDSSXcNMQH+pkV5a7XdrnxIxP -TGRGHVyH41neQtGbqH6mid2PHMkwgu07nM3A6RngatgCdTer9zQoKJHyBApPNeNgJgH60BGM+RFq -7q89w1DTj18zeTyGqHNFkIwgtnJzFyO+B2XleJINugHA64wcZr+shncBlA2c5uk5jR+mUYyZDDl3 -4bSb+hxnV29qao6pK0xXeXpXIs/NX2NGjVxZOob4Mkdio2cNGJHc+6Zr9UhhcyNZjgKnvETq9Emd -8VRY+WCv2hikLyhF3HqgiIZd8zvn/yk1gPxkQ5Tm4xxvvq0OKmOZK8l+hfZx6AYDlf7ej0gcWtSS -6Cvu5zHbugRqh5jnxV/vfaci9wHYTfmJ0A6aBVmknpjZbyvKcL5kwlWj9Omvw5Ip3IgWJJk8jSaY -tlu3zM63Nwf9JtmYhST/WSMDmu2dnajkXjjO11INb9I/bbEFa0nOipFGc/T2L/Coc3cOZayhjWZS -aX5LaAzHHjcng6WMxwLkFM1JAbBzs/3GkDpv0mztO+7skb6iQ12LAEpmJURw3kAP+HwV96LOPNde -E4yBFxgX0b3xdxA61GU5wSesVywlVP+i2k+KYTlerj1KjL0= ------END CERTIFICATE----- - -emSign Root CA - G1 -=================== ------BEGIN CERTIFICATE----- -MIIDlDCCAnygAwIBAgIKMfXkYgxsWO3W2DANBgkqhkiG9w0BAQsFADBnMQswCQYDVQQGEwJJTjET -MBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRl -ZDEcMBoGA1UEAxMTZW1TaWduIFJvb3QgQ0EgLSBHMTAeFw0xODAyMTgxODMwMDBaFw00MzAyMTgx -ODMwMDBaMGcxCzAJBgNVBAYTAklOMRMwEQYDVQQLEwplbVNpZ24gUEtJMSUwIwYDVQQKExxlTXVk -aHJhIFRlY2hub2xvZ2llcyBMaW1pdGVkMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEcxMIIB -IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk0u76WaK7p1b1TST0Bsew+eeuGQzf2N4aLTN -LnF115sgxk0pvLZoYIr3IZpWNVrzdr3YzZr/k1ZLpVkGoZM0Kd0WNHVO8oG0x5ZOrRkVUkr+PHB1 -cM2vK6sVmjM8qrOLqs1D/fXqcP/tzxE7lM5OMhbTI0Aqd7OvPAEsbO2ZLIvZTmmYsvePQbAyeGHW -DV/D+qJAkh1cF+ZwPjXnorfCYuKrpDhMtTk1b+oDafo6VGiFbdbyL0NVHpENDtjVaqSW0RM8LHhQ -6DqS0hdW5TUaQBw+jSztOd9C4INBdN+jzcKGYEho42kLVACL5HZpIQ15TjQIXhTCzLG3rdd8cIrH -hQIDAQABo0IwQDAdBgNVHQ4EFgQU++8Nhp6w492pufEhF38+/PB3KxowDgYDVR0PAQH/BAQDAgEG -MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFn/8oz1h31xPaOfG1vR2vjTnGs2 -vZupYeveFix0PZ7mddrXuqe8QhfnPZHr5X3dPpzxz5KsbEjMwiI/aTvFthUvozXGaCocV685743Q -NcMYDHsAVhzNixl03r4PEuDQqqE/AjSxcM6dGNYIAwlG7mDgfrbESQRRfXBgvKqy/3lyeqYdPV8q -+Mri/Tm3R7nrft8EI6/6nAYH6ftjk4BAtcZsCjEozgyfz7MjNYBBjWzEN3uBL4ChQEKF6dk4jeih -U80Bv2noWgbyRQuQ+q7hv53yrlc8pa6yVvSLZUDp/TGBLPQ5Cdjua6e0ph0VpZj3AYHYhX3zUVxx -iN66zB+Afko= ------END CERTIFICATE----- - -emSign ECC Root CA - G3 -======================= ------BEGIN CERTIFICATE----- -MIICTjCCAdOgAwIBAgIKPPYHqWhwDtqLhDAKBggqhkjOPQQDAzBrMQswCQYDVQQGEwJJTjETMBEG -A1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRlZDEg -MB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0gRzMwHhcNMTgwMjE4MTgzMDAwWhcNNDMwMjE4 -MTgzMDAwWjBrMQswCQYDVQQGEwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11 -ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0g -RzMwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQjpQy4LRL1KPOxst3iAhKAnjlfSU2fySU0WXTsuwYc -58Byr+iuL+FBVIcUqEqy6HyC5ltqtdyzdc6LBtCGI79G1Y4PPwT01xySfvalY8L1X44uT6EYGQIr -MgqCZH0Wk9GjQjBAMB0GA1UdDgQWBBR8XQKEE9TMipuBzhccLikenEhjQjAOBgNVHQ8BAf8EBAMC -AQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNpADBmAjEAvvNhzwIQHWSVB7gYboiFBS+D -CBeQyh+KTOgNG3qxrdWBCUfvO6wIBHxcmbHtRwfSAjEAnbpV/KlK6O3t5nYBQnvI+GDZjVGLVTv7 -jHvrZQnD+JbNR6iC8hZVdyR+EhCVBCyj ------END CERTIFICATE----- - -emSign Root CA - C1 -=================== ------BEGIN CERTIFICATE----- -MIIDczCCAlugAwIBAgILAK7PALrEzzL4Q7IwDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCVVMx -EzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQDExNlbVNp -Z24gUm9vdCBDQSAtIEMxMB4XDTE4MDIxODE4MzAwMFoXDTQzMDIxODE4MzAwMFowVjELMAkGA1UE -BhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQD -ExNlbVNpZ24gUm9vdCBDQSAtIEMxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz+up -ufGZBczYKCFK83M0UYRWEPWgTywS4/oTmifQz/l5GnRfHXk5/Fv4cI7gklL35CX5VIPZHdPIWoU/ -Xse2B+4+wM6ar6xWQio5JXDWv7V7Nq2s9nPczdcdioOl+yuQFTdrHCZH3DspVpNqs8FqOp099cGX -OFgFixwR4+S0uF2FHYP+eF8LRWgYSKVGczQ7/g/IdrvHGPMF0Ybzhe3nudkyrVWIzqa2kbBPrH4V -I5b2P/AgNBbeCsbEBEV5f6f9vtKppa+cxSMq9zwhbL2vj07FOrLzNBL834AaSaTUqZX3noleooms -lMuoaJuvimUnzYnu3Yy1aylwQ6BpC+S5DwIDAQABo0IwQDAdBgNVHQ4EFgQU/qHgcB4qAzlSWkK+ -XJGFehiqTbUwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQAD -ggEBAMJKVvoVIXsoounlHfv4LcQ5lkFMOycsxGwYFYDGrK9HWS8mC+M2sO87/kOXSTKZEhVb3xEp -/6tT+LvBeA+snFOvV71ojD1pM/CjoCNjO2RnIkSt1XHLVip4kqNPEjE2NuLe/gDEo2APJ62gsIq1 -NnpSob0n9CAnYuhNlCQT5AoE6TyrLshDCUrGYQTlSTR+08TI9Q/Aqum6VF7zYytPT1DU/rl7mYw9 -wC68AivTxEDkigcxHpvOJpkT+xHqmiIMERnHXhuBUDDIlhJu58tBf5E7oke3VIAb3ADMmpDqw8NQ -BmIMMMAVSKeoWXzhriKi4gp6D/piq1JM4fHfyr6DDUI= ------END CERTIFICATE----- - -emSign ECC Root CA - C3 -======================= ------BEGIN CERTIFICATE----- -MIICKzCCAbGgAwIBAgIKe3G2gla4EnycqDAKBggqhkjOPQQDAzBaMQswCQYDVQQGEwJVUzETMBEG -A1UECxMKZW1TaWduIFBLSTEUMBIGA1UEChMLZU11ZGhyYSBJbmMxIDAeBgNVBAMTF2VtU2lnbiBF -Q0MgUm9vdCBDQSAtIEMzMB4XDTE4MDIxODE4MzAwMFoXDTQzMDIxODE4MzAwMFowWjELMAkGA1UE -BhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMSAwHgYDVQQD -ExdlbVNpZ24gRUNDIFJvb3QgQ0EgLSBDMzB2MBAGByqGSM49AgEGBSuBBAAiA2IABP2lYa57JhAd -6bciMK4G9IGzsUJxlTm801Ljr6/58pc1kjZGDoeVjbk5Wum739D+yAdBPLtVb4OjavtisIGJAnB9 -SMVK4+kiVCJNk7tCDK93nCOmfddhEc5lx/h//vXyqaNCMEAwHQYDVR0OBBYEFPtaSNCAIEDyqOkA -B2kZd6fmw/TPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMDA2gA -MGUCMQC02C8Cif22TGK6Q04ThHK1rt0c3ta13FaPWEBaLd4gTCKDypOofu4SQMfWh0/434UCMBwU -ZOR8loMRnLDRWmFLpg9J0wD8ofzkpf9/rdcw0Md3f76BB1UwUCAU9Vc4CqgxUQ== ------END CERTIFICATE----- - -Hongkong Post Root CA 3 -======================= ------BEGIN CERTIFICATE----- -MIIFzzCCA7egAwIBAgIUCBZfikyl7ADJk0DfxMauI7gcWqQwDQYJKoZIhvcNAQELBQAwbzELMAkG -A1UEBhMCSEsxEjAQBgNVBAgTCUhvbmcgS29uZzESMBAGA1UEBxMJSG9uZyBLb25nMRYwFAYDVQQK -Ew1Ib25na29uZyBQb3N0MSAwHgYDVQQDExdIb25na29uZyBQb3N0IFJvb3QgQ0EgMzAeFw0xNzA2 -MDMwMjI5NDZaFw00MjA2MDMwMjI5NDZaMG8xCzAJBgNVBAYTAkhLMRIwEAYDVQQIEwlIb25nIEtv -bmcxEjAQBgNVBAcTCUhvbmcgS29uZzEWMBQGA1UEChMNSG9uZ2tvbmcgUG9zdDEgMB4GA1UEAxMX -SG9uZ2tvbmcgUG9zdCBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCz -iNfqzg8gTr7m1gNt7ln8wlffKWihgw4+aMdoWJwcYEuJQwy51BWy7sFOdem1p+/l6TWZ5Mwc50tf -jTMwIDNT2aa71T4Tjukfh0mtUC1Qyhi+AViiE3CWu4mIVoBc+L0sPOFMV4i707mV78vH9toxdCim -5lSJ9UExyuUmGs2C4HDaOym71QP1mbpV9WTRYA6ziUm4ii8F0oRFKHyPaFASePwLtVPLwpgchKOe -sL4jpNrcyCse2m5FHomY2vkALgbpDDtw1VAliJnLzXNg99X/NWfFobxeq81KuEXryGgeDQ0URhLj -0mRiikKYvLTGCAj4/ahMZJx2Ab0vqWwzD9g/KLg8aQFChn5pwckGyuV6RmXpwtZQQS4/t+TtbNe/ -JgERohYpSms0BpDsE9K2+2p20jzt8NYt3eEV7KObLyzJPivkaTv/ciWxNoZbx39ri1UbSsUgYT2u -y1DhCDq+sI9jQVMwCFk8mB13umOResoQUGC/8Ne8lYePl8X+l2oBlKN8W4UdKjk60FSh0Tlxnf0h -+bV78OLgAo9uliQlLKAeLKjEiafv7ZkGL7YKTE/bosw3Gq9HhS2KX8Q0NEwA/RiTZxPRN+ZItIsG -xVd7GYYKecsAyVKvQv83j+GjHno9UKtjBucVtT+2RTeUN7F+8kjDf8V1/peNRY8apxpyKBpADwID -AQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBQXnc0e -i9Y5K3DTXNSguB+wAPzFYTAdBgNVHQ4EFgQUF53NHovWOStw01zUoLgfsAD8xWEwDQYJKoZIhvcN -AQELBQADggIBAFbVe27mIgHSQpsY1Q7XZiNc4/6gx5LS6ZStS6LG7BJ8dNVI0lkUmcDrudHr9Egw -W62nV3OZqdPlt9EuWSRY3GguLmLYauRwCy0gUCCkMpXRAJi70/33MvJJrsZ64Ee+bs7Lo3I6LWld -y8joRTnU+kLBEUx3XZL7av9YROXrgZ6voJmtvqkBZss4HTzfQx/0TW60uhdG/H39h4F5ag0zD/ov -+BS5gLNdTaqX4fnkGMX41TiMJjz98iji7lpJiCzfeT2OnpA8vUFKOt1b9pq0zj8lMH8yfaIDlNDc -eqFS3m6TjRgm/VWsvY+b0s+v54Ysyx8Jb6NvqYTUc79NoXQbTiNg8swOqn+knEwlqLJmOzj/2ZQw -9nKEvmhVEA/GcywWaZMH/rFF7buiVWqw2rVKAiUnhde3t4ZEFolsgCs+l6mc1X5VTMbeRRAc6uk7 -nwNT7u56AQIWeNTowr5GdogTPyK7SBIdUgC0An4hGh6cJfTzPV4e0hz5sy229zdcxsshTrD3mUcY -hcErulWuBurQB7Lcq9CClnXO0lD+mefPL5/ndtFhKvshuzHQqp9HpLIiyhY6UFfEW0NnxWViA0kB -60PZ2Pierc+xYw5F9KBaLJstxabArahH9CdMOA0uG0k7UvToiIMrVCjU8jVStDKDYmlkDJGcn5fq -dBb9HxEGmpv0 ------END CERTIFICATE----- - -Entrust Root Certification Authority - G4 -========================================= ------BEGIN CERTIFICATE----- -MIIGSzCCBDOgAwIBAgIRANm1Q3+vqTkPAAAAAFVlrVgwDQYJKoZIhvcNAQELBQAwgb4xCzAJBgNV -BAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3Qu -bmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNSBFbnRydXN0LCBJbmMuIC0gZm9yIGF1 -dGhvcml6ZWQgdXNlIG9ubHkxMjAwBgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1 -dGhvcml0eSAtIEc0MB4XDTE1MDUyNzExMTExNloXDTM3MTIyNzExNDExNlowgb4xCzAJBgNVBAYT -AlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0 -L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNSBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhv -cml6ZWQgdXNlIG9ubHkxMjAwBgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhv -cml0eSAtIEc0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsewsQu7i0TD/pZJH4i3D -umSXbcr3DbVZwbPLqGgZ2K+EbTBwXX7zLtJTmeH+H17ZSK9dE43b/2MzTdMAArzE+NEGCJR5WIoV -3imz/f3ET+iq4qA7ec2/a0My3dl0ELn39GjUu9CH1apLiipvKgS1sqbHoHrmSKvS0VnM1n4j5pds -8ELl3FFLFUHtSUrJ3hCX1nbB76W1NhSXNdh4IjVS70O92yfbYVaCNNzLiGAMC1rlLAHGVK/XqsEQ -e9IFWrhAnoanw5CGAlZSCXqc0ieCU0plUmr1POeo8pyvi73TDtTUXm6Hnmo9RR3RXRv06QqsYJn7 -ibT/mCzPfB3pAqoEmh643IhuJbNsZvc8kPNXwbMv9W3y+8qh+CmdRouzavbmZwe+LGcKKh9asj5X -xNMhIWNlUpEbsZmOeX7m640A2Vqq6nPopIICR5b+W45UYaPrL0swsIsjdXJ8ITzI9vF01Bx7owVV -7rtNOzK+mndmnqxpkCIHH2E6lr7lmk/MBTwoWdPBDFSoWWG9yHJM6Nyfh3+9nEg2XpWjDrk4JFX8 -dWbrAuMINClKxuMrLzOg2qOGpRKX/YAr2hRC45K9PvJdXmd0LhyIRyk0X+IyqJwlN4y6mACXi0mW -Hv0liqzc2thddG5msP9E36EYxr5ILzeUePiVSj9/E15dWf10hkNjc0kCAwEAAaNCMEAwDwYDVR0T -AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJ84xFYjwznooHFs6FRM5Og6sb9n -MA0GCSqGSIb3DQEBCwUAA4ICAQAS5UKme4sPDORGpbZgQIeMJX6tuGguW8ZAdjwD+MlZ9POrYs4Q -jbRaZIxowLByQzTSGwv2LFPSypBLhmb8qoMi9IsabyZIrHZ3CL/FmFz0Jomee8O5ZDIBf9PD3Vht -7LGrhFV0d4QEJ1JrhkzO3bll/9bGXp+aEJlLdWr+aumXIOTkdnrG0CSqkM0gkLpHZPt/B7NTeLUK -YvJzQ85BK4FqLoUWlFPUa19yIqtRLULVAJyZv967lDtX/Zr1hstWO1uIAeV8KEsD+UmDfLJ/fOPt -jqF/YFOOVZ1QNBIPt5d7bIdKROf1beyAN/BYGW5KaHbwH5Lk6rWS02FREAutp9lfx1/cH6NcjKF+ -m7ee01ZvZl4HliDtC3T7Zk6LERXpgUl+b7DUUH8i119lAg2m9IUe2K4GS0qn0jFmwvjO5QimpAKW -RGhXxNUzzxkvFMSUHHuk2fCfDrGA4tGeEWSpiBE6doLlYsKA2KSD7ZPvfC+QsDJMlhVoSFLUmQjA -JOgc47OlIQ6SwJAfzyBfyjs4x7dtOvPmRLgOMWuIjnDrnBdSqEGULoe256YSxXXfW8AKbnuk5F6G -+TaU33fD6Q3AOfF5u0aOq0NZJ7cguyPpVkAh7DE9ZapD8j3fcEThuk0mEDuYn/PIjhs4ViFqUZPT -kcpG2om3PVODLAgfi49T3f+sHw== ------END CERTIFICATE----- - -Microsoft ECC Root Certificate Authority 2017 -============================================= ------BEGIN CERTIFICATE----- -MIICWTCCAd+gAwIBAgIQZvI9r4fei7FK6gxXMQHC7DAKBggqhkjOPQQDAzBlMQswCQYDVQQGEwJV -UzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1NaWNyb3NvZnQgRUND -IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwHhcNMTkxMjE4MjMwNjQ1WhcNNDIwNzE4 -MjMxNjA0WjBlMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYw -NAYDVQQDEy1NaWNyb3NvZnQgRUNDIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwdjAQ -BgcqhkjOPQIBBgUrgQQAIgNiAATUvD0CQnVBEyPNgASGAlEvaqiBYgtlzPbKnR5vSmZRogPZnZH6 -thaxjG7efM3beaYvzrvOcS/lpaso7GMEZpn4+vKTEAXhgShC48Zo9OYbhGBKia/teQ87zvH2RPUB -eMCjVDBSMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTIy5lycFIM -+Oa+sgRXKSrPQhDtNTAQBgkrBgEEAYI3FQEEAwIBADAKBggqhkjOPQQDAwNoADBlAjBY8k3qDPlf -Xu5gKcs68tvWMoQZP3zVL8KxzJOuULsJMsbG7X7JNpQS5GiFBqIb0C8CMQCZ6Ra0DvpWSNSkMBaR -eNtUjGUBiudQZsIxtzm6uBoiB078a1QWIP8rtedMDE2mT3M= ------END CERTIFICATE----- - -Microsoft RSA Root Certificate Authority 2017 -============================================= ------BEGIN CERTIFICATE----- -MIIFqDCCA5CgAwIBAgIQHtOXCV/YtLNHcB6qvn9FszANBgkqhkiG9w0BAQwFADBlMQswCQYDVQQG -EwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1NaWNyb3NvZnQg -UlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwHhcNMTkxMjE4MjI1MTIyWhcNNDIw -NzE4MjMwMDIzWjBlMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9u -MTYwNAYDVQQDEy1NaWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcw -ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKW76UM4wplZEWCpW9R2LBifOZNt9GkMml -7Xhqb0eRaPgnZ1AzHaGm++DlQ6OEAlcBXZxIQIJTELy/xztokLaCLeX0ZdDMbRnMlfl7rEqUrQ7e -S0MdhweSE5CAg2Q1OQT85elss7YfUJQ4ZVBcF0a5toW1HLUX6NZFndiyJrDKxHBKrmCk3bPZ7Pw7 -1VdyvD/IybLeS2v4I2wDwAW9lcfNcztmgGTjGqwu+UcF8ga2m3P1eDNbx6H7JyqhtJqRjJHTOoI+ -dkC0zVJhUXAoP8XFWvLJjEm7FFtNyP9nTUwSlq31/niol4fX/V4ggNyhSyL71Imtus5Hl0dVe49F -yGcohJUcaDDv70ngNXtk55iwlNpNhTs+VcQor1fznhPbRiefHqJeRIOkpcrVE7NLP8TjwuaGYaRS -MLl6IE9vDzhTyzMMEyuP1pq9KsgtsRx9S1HKR9FIJ3Jdh+vVReZIZZ2vUpC6W6IYZVcSn2i51BVr -lMRpIpj0M+Dt+VGOQVDJNE92kKz8OMHY4Xu54+OU4UZpyw4KUGsTuqwPN1q3ErWQgR5WrlcihtnJ -0tHXUeOrO8ZV/R4O03QK0dqq6mm4lyiPSMQH+FJDOvTKVTUssKZqwJz58oHhEmrARdlns87/I6KJ -ClTUFLkqqNfs+avNJVgyeY+QW5g5xAgGwax/Dj0ApQIDAQABo1QwUjAOBgNVHQ8BAf8EBAMCAYYw -DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUCctZf4aycI8awznjwNnpv7tNsiMwEAYJKwYBBAGC -NxUBBAMCAQAwDQYJKoZIhvcNAQEMBQADggIBAKyvPl3CEZaJjqPnktaXFbgToqZCLgLNFgVZJ8og -6Lq46BrsTaiXVq5lQ7GPAJtSzVXNUzltYkyLDVt8LkS/gxCP81OCgMNPOsduET/m4xaRhPtthH80 -dK2Jp86519efhGSSvpWhrQlTM93uCupKUY5vVau6tZRGrox/2KJQJWVggEbbMwSubLWYdFQl3JPk -+ONVFT24bcMKpBLBaYVu32TxU5nhSnUgnZUP5NbcA/FZGOhHibJXWpS2qdgXKxdJ5XbLwVaZOjex -/2kskZGT4d9Mozd2TaGf+G0eHdP67Pv0RR0Tbc/3WeUiJ3IrhvNXuzDtJE3cfVa7o7P4NHmJweDy -AmH3pvwPuxwXC65B2Xy9J6P9LjrRk5Sxcx0ki69bIImtt2dmefU6xqaWM/5TkshGsRGRxpl/j8nW -ZjEgQRCHLQzWwa80mMpkg/sTV9HB8Dx6jKXB/ZUhoHHBk2dxEuqPiAppGWSZI1b7rCoucL5mxAyE -7+WL85MB+GqQk2dLsmijtWKP6T+MejteD+eMuMZ87zf9dOLITzNy4ZQ5bb0Sr74MTnB8G2+NszKT -c0QWbej09+CVgI+WXTik9KveCjCHk9hNAHFiRSdLOkKEW39lt2c0Ui2cFmuqqNh7o0JMcccMyj6D -5KbvtwEwXlGjefVwaaZBRA+GsCyRxj3qrg+E ------END CERTIFICATE----- - -e-Szigno Root CA 2017 -===================== ------BEGIN CERTIFICATE----- -MIICQDCCAeWgAwIBAgIMAVRI7yH9l1kN9QQKMAoGCCqGSM49BAMCMHExCzAJBgNVBAYTAkhVMREw -DwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UECgwNTWljcm9zZWMgTHRkLjEXMBUGA1UEYQwOVkFUSFUt -MjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3ppZ25vIFJvb3QgQ0EgMjAxNzAeFw0xNzA4MjIxMjA3MDZa -Fw00MjA4MjIxMjA3MDZaMHExCzAJBgNVBAYTAkhVMREwDwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UE -CgwNTWljcm9zZWMgTHRkLjEXMBUGA1UEYQwOVkFUSFUtMjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3pp -Z25vIFJvb3QgQ0EgMjAxNzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJbcPYrYsHtvxie+RJCx -s1YVe45DJH0ahFnuY2iyxl6H0BVIHqiQrb1TotreOpCmYF9oMrWGQd+HWyx7xf58etqjYzBhMA8G -A1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSHERUI0arBeAyxr87GyZDv -vzAEwDAfBgNVHSMEGDAWgBSHERUI0arBeAyxr87GyZDvvzAEwDAKBggqhkjOPQQDAgNJADBGAiEA -tVfd14pVCzbhhkT61NlojbjcI4qKDdQvfepz7L9NbKgCIQDLpbQS+ue16M9+k/zzNY9vTlp8tLxO -svxyqltZ+efcMQ== ------END CERTIFICATE----- - -certSIGN Root CA G2 -=================== ------BEGIN CERTIFICATE----- -MIIFRzCCAy+gAwIBAgIJEQA0tk7GNi02MA0GCSqGSIb3DQEBCwUAMEExCzAJBgNVBAYTAlJPMRQw -EgYDVQQKEwtDRVJUU0lHTiBTQTEcMBoGA1UECxMTY2VydFNJR04gUk9PVCBDQSBHMjAeFw0xNzAy -MDYwOTI3MzVaFw00MjAyMDYwOTI3MzVaMEExCzAJBgNVBAYTAlJPMRQwEgYDVQQKEwtDRVJUU0lH -TiBTQTEcMBoGA1UECxMTY2VydFNJR04gUk9PVCBDQSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIP -ADCCAgoCggIBAMDFdRmRfUR0dIf+DjuW3NgBFszuY5HnC2/OOwppGnzC46+CjobXXo9X69MhWf05 -N0IwvlDqtg+piNguLWkh59E3GE59kdUWX2tbAMI5Qw02hVK5U2UPHULlj88F0+7cDBrZuIt4Imfk -abBoxTzkbFpG583H+u/E7Eu9aqSs/cwoUe+StCmrqzWaTOTECMYmzPhpn+Sc8CnTXPnGFiWeI8Mg -wT0PPzhAsP6CRDiqWhqKa2NYOLQV07YRaXseVO6MGiKscpc/I1mbySKEwQdPzH/iV8oScLumZfNp -dWO9lfsbl83kqK/20U6o2YpxJM02PbyWxPFsqa7lzw1uKA2wDrXKUXt4FMMgL3/7FFXhEZn91Qqh -ngLjYl/rNUssuHLoPj1PrCy7Lobio3aP5ZMqz6WryFyNSwb/EkaseMsUBzXgqd+L6a8VTxaJW732 -jcZZroiFDsGJ6x9nxUWO/203Nit4ZoORUSs9/1F3dmKh7Gc+PoGD4FapUB8fepmrY7+EF3fxDTvf -95xhszWYijqy7DwaNz9+j5LP2RIUZNoQAhVB/0/E6xyjyfqZ90bp4RjZsbgyLcsUDFDYg2WD7rlc -z8sFWkz6GZdr1l0T08JcVLwyc6B49fFtHsufpaafItzRUZ6CeWRgKRM+o/1Pcmqr4tTluCRVLERL -iohEnMqE0yo7AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1Ud -DgQWBBSCIS1mxteg4BXrzkwJd8RgnlRuAzANBgkqhkiG9w0BAQsFAAOCAgEAYN4auOfyYILVAzOB -ywaK8SJJ6ejqkX/GM15oGQOGO0MBzwdw5AgeZYWR5hEit/UCI46uuR59H35s5r0l1ZUa8gWmr4UC -b6741jH/JclKyMeKqdmfS0mbEVeZkkMR3rYzpMzXjWR91M08KCy0mpbqTfXERMQlqiCA2ClV9+BB -/AYm/7k29UMUA2Z44RGx2iBfRgB4ACGlHgAoYXhvqAEBj500mv/0OJD7uNGzcgbJceaBxXntC6Z5 -8hMLnPddDnskk7RI24Zf3lCGeOdA5jGokHZwYa+cNywRtYK3qq4kNFtyDGkNzVmf9nGvnAvRCjj5 -BiKDUyUM/FHE5r7iOZULJK2v0ZXkltd0ZGtxTgI8qoXzIKNDOXZbbFD+mpwUHmUUihW9o4JFWklW -atKcsWMy5WHgUyIOpwpJ6st+H6jiYoD2EEVSmAYY3qXNL3+q1Ok+CHLsIwMCPKaq2LxndD0UF/tU -Sxfj03k9bWtJySgOLnRQvwzZRjoQhsmnP+mg7H/rpXdYaXHmgwo38oZJar55CJD2AhZkPuXaTH4M -NMn5X7azKFGnpyuqSfqNZSlO42sTp5SjLVFteAxEy9/eCG/Oo2Sr05WE1LlSVHJ7liXMvGnjSG4N -0MedJ5qq+BOS3R7fY581qRY27Iy4g/Q9iY/NtBde17MXQRBdJ3NghVdJIgc= ------END CERTIFICATE----- - -Trustwave Global Certification Authority -======================================== ------BEGIN CERTIFICATE----- -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 -29FpHOTKyeC2nOnOcXHebD8WpHk= ------END CERTIFICATE----- - -Trustwave Global ECC P256 Certification Authority -================================================= ------BEGIN CERTIFICATE----- -MIICYDCCAgegAwIBAgIMDWpfCD8oXD5Rld9dMAoGCCqGSM49BAMCMIGRMQswCQYDVQQGEwJVUzER -MA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0d2F2ZSBI -b2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDI1NiBDZXJ0aWZp -Y2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MjMxOTM1MTBaFw00MjA4MjMxOTM1MTBaMIGRMQswCQYD -VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRy -dXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDI1 -NiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABH77bOYj -43MyCMpg5lOcunSNGLB4kFKA3TjASh3RqMyTpJcGOMoNFWLGjgEqZZ2q3zSRLoHB5DOSMcT9CTqm -P62jQzBBMA8GA1UdEwEB/wQFMAMBAf8wDwYDVR0PAQH/BAUDAwcGADAdBgNVHQ4EFgQUo0EGrJBt -0UrrdaVKEJmzsaGLSvcwCgYIKoZIzj0EAwIDRwAwRAIgB+ZU2g6gWrKuEZ+Hxbb/ad4lvvigtwjz -RM4q3wghDDcCIC0mA6AFvWvR9lz4ZcyGbbOcNEhjhAnFjXca4syc4XR7 ------END CERTIFICATE----- - -Trustwave Global ECC P384 Certification Authority -================================================= ------BEGIN CERTIFICATE----- -MIICnTCCAiSgAwIBAgIMCL2Fl2yZJ6SAaEc7MAoGCCqGSM49BAMDMIGRMQswCQYDVQQGEwJVUzER -MA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0d2F2ZSBI -b2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDM4NCBDZXJ0aWZp -Y2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MjMxOTM2NDNaFw00MjA4MjMxOTM2NDNaMIGRMQswCQYD -VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRy -dXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDM4 -NCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTB2MBAGByqGSM49AgEGBSuBBAAiA2IABGvaDXU1CDFH -Ba5FmVXxERMuSvgQMSOjfoPTfygIOiYaOs+Xgh+AtycJj9GOMMQKmw6sWASr9zZ9lCOkmwqKi6vr -/TklZvFe/oyujUF5nQlgziip04pt89ZF1PKYhDhloKNDMEEwDwYDVR0TAQH/BAUwAwEB/zAPBgNV -HQ8BAf8EBQMDBwYAMB0GA1UdDgQWBBRVqYSJ0sEyvRjLbKYHTsjnnb6CkDAKBggqhkjOPQQDAwNn -ADBkAjA3AZKXRRJ+oPM+rRk6ct30UJMDEr5E0k9BpIycnR+j9sKS50gU/k6bpZFXrsY3crsCMGcl -CrEMXu6pY5Jv5ZAL/mYiykf9ijH3g/56vxC+GCsej/YpHpRZ744hN8tRmKVuSw== ------END CERTIFICATE----- - -NAVER Global Root Certification Authority -========================================= ------BEGIN CERTIFICATE----- -MIIFojCCA4qgAwIBAgIUAZQwHqIL3fXFMyqxQ0Rx+NZQTQ0wDQYJKoZIhvcNAQEMBQAwaTELMAkG -A1UEBhMCS1IxJjAkBgNVBAoMHU5BVkVSIEJVU0lORVNTIFBMQVRGT1JNIENvcnAuMTIwMAYDVQQD -DClOQVZFUiBHbG9iYWwgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MTgwODU4 -NDJaFw0zNzA4MTgyMzU5NTlaMGkxCzAJBgNVBAYTAktSMSYwJAYDVQQKDB1OQVZFUiBCVVNJTkVT -UyBQTEFURk9STSBDb3JwLjEyMDAGA1UEAwwpTkFWRVIgR2xvYmFsIFJvb3QgQ2VydGlmaWNhdGlv -biBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC21PGTXLVAiQqrDZBb -UGOukJR0F0Vy1ntlWilLp1agS7gvQnXp2XskWjFlqxcX0TM62RHcQDaH38dq6SZeWYp34+hInDEW -+j6RscrJo+KfziFTowI2MMtSAuXaMl3Dxeb57hHHi8lEHoSTGEq0n+USZGnQJoViAbbJAh2+g1G7 -XNr4rRVqmfeSVPc0W+m/6imBEtRTkZazkVrd/pBzKPswRrXKCAfHcXLJZtM0l/aM9BhK4dA9WkW2 -aacp+yPOiNgSnABIqKYPszuSjXEOdMWLyEz59JuOuDxp7W87UC9Y7cSw0BwbagzivESq2M0UXZR4 -Yb8ObtoqvC8MC3GmsxY/nOb5zJ9TNeIDoKAYv7vxvvTWjIcNQvcGufFt7QSUqP620wbGQGHfnZ3z -VHbOUzoBppJB7ASjjw2i1QnK1sua8e9DXcCrpUHPXFNwcMmIpi3Ua2FzUCaGYQ5fG8Ir4ozVu53B -A0K6lNpfqbDKzE0K70dpAy8i+/Eozr9dUGWokG2zdLAIx6yo0es+nPxdGoMuK8u180SdOqcXYZai -cdNwlhVNt0xz7hlcxVs+Qf6sdWA7G2POAN3aCJBitOUt7kinaxeZVL6HSuOpXgRM6xBtVNbv8ejy -YhbLgGvtPe31HzClrkvJE+2KAQHJuFFYwGY6sWZLxNUxAmLpdIQM201GLQIDAQABo0IwQDAdBgNV -HQ4EFgQU0p+I36HNLL3s9TsBAZMzJ7LrYEswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMB -Af8wDQYJKoZIhvcNAQEMBQADggIBADLKgLOdPVQG3dLSLvCkASELZ0jKbY7gyKoNqo0hV4/GPnrK -21HUUrPUloSlWGB/5QuOH/XcChWB5Tu2tyIvCZwTFrFsDDUIbatjcu3cvuzHV+YwIHHW1xDBE1UB -jCpD5EHxzzp6U5LOogMFDTjfArsQLtk70pt6wKGm+LUx5vR1yblTmXVHIloUFcd4G7ad6Qz4G3bx -hYTeodoS76TiEJd6eN4MUZeoIUCLhr0N8F5OSza7OyAfikJW4Qsav3vQIkMsRIz75Sq0bBwcupTg -E34h5prCy8VCZLQelHsIJchxzIdFV4XTnyliIoNRlwAYl3dqmJLJfGBs32x9SuRwTMKeuB330DTH -D8z7p/8Dvq1wkNoL3chtl1+afwkyQf3NosxabUzyqkn+Zvjp2DXrDige7kgvOtB5CTh8piKCk5XQ -A76+AqAF3SAi428diDRgxuYKuQl1C/AH6GmWNcf7I4GOODm4RStDeKLRLBT/DShycpWbXgnbiUSY -qqFJu3FS8r/2/yehNq+4tneI3TqkbZs0kNwUXTC/t+sX5Ie3cdCh13cV1ELX8vMxmV2b3RZtP+oG -I/hGoiLtk/bdmuYqh7GYVPEi92tF4+KOdh2ajcQGjTa3FPOdVGm3jjzVpG2Tgbet9r1ke8LJaDmg -kpzNNIaRkPpkUZ3+/uul9XXeifdy ------END CERTIFICATE----- - -AC RAIZ FNMT-RCM SERVIDORES SEGUROS -=================================== ------BEGIN CERTIFICATE----- -MIICbjCCAfOgAwIBAgIQYvYybOXE42hcG2LdnC6dlTAKBggqhkjOPQQDAzB4MQswCQYDVQQGEwJF -UzERMA8GA1UECgwIRk5NVC1SQ00xDjAMBgNVBAsMBUNlcmVzMRgwFgYDVQRhDA9WQVRFUy1RMjgy -NjAwNEoxLDAqBgNVBAMMI0FDIFJBSVogRk5NVC1SQ00gU0VSVklET1JFUyBTRUdVUk9TMB4XDTE4 -MTIyMDA5MzczM1oXDTQzMTIyMDA5MzczM1oweDELMAkGA1UEBhMCRVMxETAPBgNVBAoMCEZOTVQt -UkNNMQ4wDAYDVQQLDAVDZXJlczEYMBYGA1UEYQwPVkFURVMtUTI4MjYwMDRKMSwwKgYDVQQDDCNB -QyBSQUlaIEZOTVQtUkNNIFNFUlZJRE9SRVMgU0VHVVJPUzB2MBAGByqGSM49AgEGBSuBBAAiA2IA -BPa6V1PIyqvfNkpSIeSX0oNnnvBlUdBeh8dHsVnyV0ebAAKTRBdp20LHsbI6GA60XYyzZl2hNPk2 -LEnb80b8s0RpRBNm/dfF/a82Tc4DTQdxz69qBdKiQ1oKUm8BA06Oi6NCMEAwDwYDVR0TAQH/BAUw -AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFAG5L++/EYZg8k/QQW6rcx/n0m5JMAoGCCqG -SM49BAMDA2kAMGYCMQCuSuMrQMN0EfKVrRYj3k4MGuZdpSRea0R7/DjiT8ucRRcRTBQnJlU5dUoD -zBOQn5ICMQD6SmxgiHPz7riYYqnOK8LZiqZwMR2vsJRM60/G49HzYqc8/5MuB1xJAWdpEgJyv+c= ------END CERTIFICATE----- - -GlobalSign Root R46 -=================== ------BEGIN CERTIFICATE----- -MIIFWjCCA0KgAwIBAgISEdK7udcjGJ5AXwqdLdDfJWfRMA0GCSqGSIb3DQEBDAUAMEYxCzAJBgNV -BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYDVQQDExNHbG9iYWxTaWduIFJv -b3QgUjQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMyMDAwMDAwMFowRjELMAkGA1UEBhMCQkUxGTAX -BgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExHDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBSNDYwggIi -MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCsrHQy6LNl5brtQyYdpokNRbopiLKkHWPd08Es -CVeJOaFV6Wc0dwxu5FUdUiXSE2te4R2pt32JMl8Nnp8semNgQB+msLZ4j5lUlghYruQGvGIFAha/ -r6gjA7aUD7xubMLL1aa7DOn2wQL7Id5m3RerdELv8HQvJfTqa1VbkNud316HCkD7rRlr+/fKYIje -2sGP1q7Vf9Q8g+7XFkyDRTNrJ9CG0Bwta/OrffGFqfUo0q3v84RLHIf8E6M6cqJaESvWJ3En7YEt -bWaBkoe0G1h6zD8K+kZPTXhc+CtI4wSEy132tGqzZfxCnlEmIyDLPRT5ge1lFgBPGmSXZgjPjHvj -K8Cd+RTyG/FWaha/LIWFzXg4mutCagI0GIMXTpRW+LaCtfOW3T3zvn8gdz57GSNrLNRyc0NXfeD4 -12lPFzYE+cCQYDdF3uYM2HSNrpyibXRdQr4G9dlkbgIQrImwTDsHTUB+JMWKmIJ5jqSngiCNI/on -ccnfxkF0oE32kRbcRoxfKWMxWXEM2G/CtjJ9++ZdU6Z+Ffy7dXxd7Pj2Fxzsx2sZy/N78CsHpdls -eVR2bJ0cpm4O6XkMqCNqo98bMDGfsVR7/mrLZqrcZdCinkqaByFrgY/bxFn63iLABJzjqls2k+g9 -vXqhnQt2sQvHnf3PmKgGwvgqo6GDoLclcqUC4wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYD -VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA1yrc4GHqMywptWU4jaWSf8FmSwwDQYJKoZIhvcNAQEM -BQADggIBAHx47PYCLLtbfpIrXTncvtgdokIzTfnvpCo7RGkerNlFo048p9gkUbJUHJNOxO97k4Vg -JuoJSOD1u8fpaNK7ajFxzHmuEajwmf3lH7wvqMxX63bEIaZHU1VNaL8FpO7XJqti2kM3S+LGteWy -gxk6x9PbTZ4IevPuzz5i+6zoYMzRx6Fcg0XERczzF2sUyQQCPtIkpnnpHs6i58FZFZ8d4kuaPp92 -CC1r2LpXFNqD6v6MVenQTqnMdzGxRBF6XLE+0xRFFRhiJBPSy03OXIPBNvIQtQ6IbbjhVp+J3pZm -OUdkLG5NrmJ7v2B0GbhWrJKsFjLtrWhV/pi60zTe9Mlhww6G9kuEYO4Ne7UyWHmRVSyBQ7N0H3qq -JZ4d16GLuc1CLgSkZoNNiTW2bKg2SnkheCLQQrzRQDGQob4Ez8pn7fXwgNNgyYMqIgXQBztSvwye -qiv5u+YfjyW6hY0XHgL+XVAEV8/+LbzvXMAaq7afJMbfc2hIkCwU9D9SGuTSyxTDYWnP4vkYxboz -nxSjBF25cfe1lNj2M8FawTSLfJvdkzrnE6JwYZ+vj+vYxXX4M2bUdGc6N3ec592kD3ZDZopD8p/7 -DEJ4Y9HiD2971KE9dJeFt0g5QdYg/NA6s/rob8SKunE3vouXsXgxT7PntgMTzlSdriVZzH81Xwj3 -QEUxeCp6 ------END CERTIFICATE----- - -GlobalSign Root E46 -=================== ------BEGIN CERTIFICATE----- -MIICCzCCAZGgAwIBAgISEdK7ujNu1LzmJGjFDYQdmOhDMAoGCCqGSM49BAMDMEYxCzAJBgNVBAYT -AkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYDVQQDExNHbG9iYWxTaWduIFJvb3Qg -RTQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMyMDAwMDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNV -BAoTEEdsb2JhbFNpZ24gbnYtc2ExHDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBFNDYwdjAQBgcq -hkjOPQIBBgUrgQQAIgNiAAScDrHPt+ieUnd1NPqlRqetMhkytAepJ8qUuwzSChDH2omwlwxwEwkB -jtjqR+q+soArzfwoDdusvKSGN+1wCAB16pMLey5SnCNoIwZD7JIvU4Tb+0cUB+hflGddyXqBPCCj -QjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQxCpCPtsad0kRL -gLWi5h+xEk8blTAKBggqhkjOPQQDAwNoADBlAjEA31SQ7Zvvi5QCkxeCmb6zniz2C5GMn0oUsfZk -vLtoURMMA/cVi4RguYv/Uo7njLwcAjA8+RHUjE7AwWHCFUyqqx0LMV87HOIAl0Qx5v5zli/altP+ -CAezNIm8BZ/3Hobui3A= ------END CERTIFICATE----- diff --git a/twitter/vendor/composer/ca-bundle/src/CaBundle.php b/twitter/vendor/composer/ca-bundle/src/CaBundle.php deleted file mode 100644 index 0109ba037..000000000 --- a/twitter/vendor/composer/ca-bundle/src/CaBundle.php +++ /dev/null @@ -1,353 +0,0 @@ - - * - * For the full copyright and license information, please view - * the LICENSE file that was distributed with this source code. - */ - -namespace Composer\CaBundle; - -use Psr\Log\LoggerInterface; -use Symfony\Component\Process\PhpProcess; - -/** - * @author Chris Smith - * @author Jordi Boggiano - */ -class CaBundle -{ - /** @var string|null */ - private static $caPath; - /** @var array */ - private static $caFileValidity = array(); - /** @var bool|null */ - private static $useOpensslParse; - - /** - * Returns the system CA bundle path, or a path to the bundled one - * - * This method was adapted from Sslurp. - * https://github.com/EvanDotPro/Sslurp - * - * (c) Evan Coury - * - * For the full copyright and license information, please see below: - * - * Copyright (c) 2013, Evan Coury - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * @param LoggerInterface $logger optional logger for information about which CA files were loaded - * @return string path to a CA bundle file or directory - */ - public static function getSystemCaRootBundlePath(LoggerInterface $logger = null) - { - if (self::$caPath !== null) { - return self::$caPath; - } - $caBundlePaths = array(); - - // If SSL_CERT_FILE env variable points to a valid certificate/bundle, use that. - // This mimics how OpenSSL uses the SSL_CERT_FILE env variable. - $caBundlePaths[] = self::getEnvVariable('SSL_CERT_FILE'); - - // If SSL_CERT_DIR env variable points to a valid certificate/bundle, use that. - // This mimics how OpenSSL uses the SSL_CERT_FILE env variable. - $caBundlePaths[] = self::getEnvVariable('SSL_CERT_DIR'); - - $caBundlePaths[] = ini_get('openssl.cafile'); - $caBundlePaths[] = ini_get('openssl.capath'); - - $otherLocations = array( - '/etc/pki/tls/certs/ca-bundle.crt', // Fedora, RHEL, CentOS (ca-certificates package) - '/etc/ssl/certs/ca-certificates.crt', // Debian, Ubuntu, Gentoo, Arch Linux (ca-certificates package) - '/etc/ssl/ca-bundle.pem', // SUSE, openSUSE (ca-certificates package) - '/usr/local/share/certs/ca-root-nss.crt', // FreeBSD (ca_root_nss_package) - '/usr/ssl/certs/ca-bundle.crt', // Cygwin - '/opt/local/share/curl/curl-ca-bundle.crt', // OS X macports, curl-ca-bundle package - '/usr/local/share/curl/curl-ca-bundle.crt', // Default cURL CA bunde path (without --with-ca-bundle option) - '/usr/share/ssl/certs/ca-bundle.crt', // Really old RedHat? - '/etc/ssl/cert.pem', // OpenBSD - '/usr/local/etc/ssl/cert.pem', // FreeBSD 10.x - '/usr/local/etc/openssl/cert.pem', // OS X homebrew, openssl package - '/usr/local/etc/openssl@1.1/cert.pem', // OS X homebrew, openssl@1.1 package - ); - - foreach($otherLocations as $location) { - $otherLocations[] = dirname($location); - } - - $caBundlePaths = array_merge($caBundlePaths, $otherLocations); - - foreach ($caBundlePaths as $caBundle) { - if ($caBundle && self::caFileUsable($caBundle, $logger)) { - return self::$caPath = $caBundle; - } - - if ($caBundle && self::caDirUsable($caBundle)) { - return self::$caPath = $caBundle; - } - } - - return self::$caPath = static::getBundledCaBundlePath(); // Bundled CA file, last resort - } - - /** - * Returns the path to the bundled CA file - * - * In case you don't want to trust the user or the system, you can use this directly - * - * @return string path to a CA bundle file - */ - public static function getBundledCaBundlePath() - { - $caBundleFile = __DIR__.'/../res/cacert.pem'; - - // cURL does not understand 'phar://' paths - // see https://github.com/composer/ca-bundle/issues/10 - if (0 === strpos($caBundleFile, 'phar://')) { - $tempCaBundleFile = tempnam(sys_get_temp_dir(), 'openssl-ca-bundle-'); - if (false === $tempCaBundleFile) { - throw new \RuntimeException('Could not create a temporary file to store the bundled CA file'); - } - - file_put_contents( - $tempCaBundleFile, - file_get_contents($caBundleFile) - ); - - register_shutdown_function(function() use ($tempCaBundleFile) { - @unlink($tempCaBundleFile); - }); - - $caBundleFile = $tempCaBundleFile; - } - - return $caBundleFile; - } - - /** - * Validates a CA file using opensl_x509_parse only if it is safe to use - * - * @param string $filename - * @param LoggerInterface $logger optional logger for information about which CA files were loaded - * - * @return bool - */ - public static function validateCaFile($filename, LoggerInterface $logger = null) - { - static $warned = false; - - if (isset(self::$caFileValidity[$filename])) { - return self::$caFileValidity[$filename]; - } - - $contents = file_get_contents($filename); - - // assume the CA is valid if php is vulnerable to - // https://www.sektioneins.de/advisories/advisory-012013-php-openssl_x509_parse-memory-corruption-vulnerability.html - if (!static::isOpensslParseSafe()) { - if (!$warned && $logger) { - $logger->warning(sprintf( - 'Your version of PHP, %s, is affected by CVE-2013-6420 and cannot safely perform certificate validation, we strongly suggest you upgrade.', - PHP_VERSION - )); - $warned = true; - } - - $isValid = !empty($contents); - } elseif (is_string($contents) && strlen($contents) > 0) { - $contents = preg_replace("/^(\\-+(?:BEGIN|END))\\s+TRUSTED\\s+(CERTIFICATE\\-+)\$/m", '$1 $2', $contents); - if (null === $contents) { - // regex extraction failed - $isValid = false; - } else { - $isValid = (bool) openssl_x509_parse($contents); - } - } else { - $isValid = false; - } - - if ($logger) { - $logger->debug('Checked CA file '.realpath($filename).': '.($isValid ? 'valid' : 'invalid')); - } - - return self::$caFileValidity[$filename] = $isValid; - } - - /** - * Test if it is safe to use the PHP function openssl_x509_parse(). - * - * This checks if OpenSSL extensions is vulnerable to remote code execution - * via the exploit documented as CVE-2013-6420. - * - * @return bool - */ - public static function isOpensslParseSafe() - { - if (null !== self::$useOpensslParse) { - return self::$useOpensslParse; - } - - if (PHP_VERSION_ID >= 50600) { - return self::$useOpensslParse = true; - } - - // Vulnerable: - // PHP 5.3.0 - PHP 5.3.27 - // PHP 5.4.0 - PHP 5.4.22 - // PHP 5.5.0 - PHP 5.5.6 - if ( - (PHP_VERSION_ID < 50400 && PHP_VERSION_ID >= 50328) - || (PHP_VERSION_ID < 50500 && PHP_VERSION_ID >= 50423) - || PHP_VERSION_ID >= 50507 - ) { - // This version of PHP has the fix for CVE-2013-6420 applied. - return self::$useOpensslParse = true; - } - - if (defined('PHP_WINDOWS_VERSION_BUILD')) { - // Windows is probably insecure in this case. - return self::$useOpensslParse = false; - } - - $compareDistroVersionPrefix = function ($prefix, $fixedVersion) { - $regex = '{^'.preg_quote($prefix).'([0-9]+)$}'; - - if (preg_match($regex, PHP_VERSION, $m)) { - return ((int) $m[1]) >= $fixedVersion; - } - - return false; - }; - - // Hard coded list of PHP distributions with the fix backported. - if ( - $compareDistroVersionPrefix('5.3.3-7+squeeze', 18) // Debian 6 (Squeeze) - || $compareDistroVersionPrefix('5.4.4-14+deb7u', 7) // Debian 7 (Wheezy) - || $compareDistroVersionPrefix('5.3.10-1ubuntu3.', 9) // Ubuntu 12.04 (Precise) - ) { - return self::$useOpensslParse = true; - } - - // Symfony Process component is missing so we assume it is unsafe at this point - if (!class_exists('Symfony\Component\Process\PhpProcess')) { - return self::$useOpensslParse = false; - } - - // This is where things get crazy, because distros backport security - // fixes the chances are on NIX systems the fix has been applied but - // it's not possible to verify that from the PHP version. - // - // To verify exec a new PHP process and run the issue testcase with - // known safe input that replicates the bug. - - // Based on testcase in https://github.com/php/php-src/commit/c1224573c773b6845e83505f717fbf820fc18415 - // changes in https://github.com/php/php-src/commit/76a7fd893b7d6101300cc656058704a73254d593 - $cert = 'LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVwRENDQTR5Z0F3SUJBZ0lKQUp6dThyNnU2ZUJjTUEwR0NTcUdTSWIzRFFFQkJRVUFNSUhETVFzd0NRWUQKVlFRR0V3SkVSVEVjTUJvR0ExVUVDQXdUVG05eVpISm9aV2x1TFZkbGMzUm1ZV3hsYmpFUU1BNEdBMVVFQnd3SApTOE9Ed3Jac2JqRVVNQklHQTFVRUNnd0xVMlZyZEdsdmJrVnBibk14SHpBZEJnTlZCQXNNRmsxaGJHbGphVzkxCmN5QkRaWEowSUZObFkzUnBiMjR4SVRBZkJnTlZCQU1NR0cxaGJHbGphVzkxY3k1elpXdDBhVzl1WldsdWN5NWsKWlRFcU1DZ0dDU3FHU0liM0RRRUpBUlliYzNSbFptRnVMbVZ6YzJWeVFITmxhM1JwYjI1bGFXNXpMbVJsTUhVWQpaREU1TnpBd01UQXhNREF3TURBd1dnQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBCkFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUEKQUFBQUFBQVhEVEUwTVRFeU9ERXhNemt6TlZvd2djTXhDekFKQmdOVkJBWVRBa1JGTVJ3d0dnWURWUVFJREJOTwpiM0prY21obGFXNHRWMlZ6ZEdaaGJHVnVNUkF3RGdZRFZRUUhEQWRMdzRQQ3RteHVNUlF3RWdZRFZRUUtEQXRUClpXdDBhVzl1UldsdWN6RWZNQjBHQTFVRUN3d1dUV0ZzYVdOcGIzVnpJRU5sY25RZ1UyVmpkR2x2YmpFaE1COEcKQTFVRUF3d1liV0ZzYVdOcGIzVnpMbk5sYTNScGIyNWxhVzV6TG1SbE1Tb3dLQVlKS29aSWh2Y05BUWtCRmh0egpkR1ZtWVc0dVpYTnpaWEpBYzJWcmRHbHZibVZwYm5NdVpHVXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRRERBZjNobDdKWTBYY0ZuaXlFSnBTU0RxbjBPcUJyNlFQNjV1c0pQUnQvOFBhRG9xQnUKd0VZVC9OYSs2ZnNnUGpDMHVLOURaZ1dnMnRIV1dvYW5TYmxBTW96NVBINlorUzRTSFJaN2UyZERJalBqZGhqaAowbUxnMlVNTzV5cDBWNzk3R2dzOWxOdDZKUmZIODFNTjJvYlhXczROdHp0TE11RDZlZ3FwcjhkRGJyMzRhT3M4CnBrZHVpNVVhd1Raa3N5NXBMUEhxNWNNaEZHbTA2djY1Q0xvMFYyUGQ5K0tBb2tQclBjTjVLTEtlYno3bUxwazYKU01lRVhPS1A0aWRFcXh5UTdPN2ZCdUhNZWRzUWh1K3ByWTNzaTNCVXlLZlF0UDVDWm5YMmJwMHdLSHhYMTJEWAoxbmZGSXQ5RGJHdkhUY3lPdU4rblpMUEJtM3ZXeG50eUlJdlZBZ01CQUFHalFqQkFNQWtHQTFVZEV3UUNNQUF3CkVRWUpZSVpJQVliNFFnRUJCQVFEQWdlQU1Bc0dBMVVkRHdRRUF3SUZvREFUQmdOVkhTVUVEREFLQmdnckJnRUYKQlFjREFqQU5CZ2txaGtpRzl3MEJBUVVGQUFPQ0FRRUFHMGZaWVlDVGJkajFYWWMrMVNub2FQUit2SThDOENhRAo4KzBVWWhkbnlVNGdnYTBCQWNEclk5ZTk0ZUVBdTZacXljRjZGakxxWFhkQWJvcHBXb2NyNlQ2R0QxeDMzQ2tsClZBcnpHL0t4UW9oR0QySmVxa2hJTWxEb214SE83a2EzOStPYThpMnZXTFZ5alU4QVp2V01BcnVIYTRFRU55RzcKbFcyQWFnYUZLRkNyOVRuWFRmcmR4R1ZFYnY3S1ZRNmJkaGc1cDVTanBXSDErTXEwM3VSM1pYUEJZZHlWODMxOQpvMGxWajFLRkkyRENML2xpV2lzSlJvb2YrMWNSMzVDdGQwd1lCY3BCNlRac2xNY09QbDc2ZHdLd0pnZUpvMlFnClpzZm1jMnZDMS9xT2xOdU5xLzBUenprVkd2OEVUVDNDZ2FVK1VYZTRYT1Z2a2NjZWJKbjJkZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K'; - $script = <<<'EOT' - -error_reporting(-1); -$info = openssl_x509_parse(base64_decode('%s')); -var_dump(PHP_VERSION, $info['issuer']['emailAddress'], $info['validFrom_time_t']); - -EOT; - $script = '<'."?php\n".sprintf($script, $cert); - - try { - $process = new PhpProcess($script); - $process->mustRun(); - } catch (\Exception $e) { - // In the case of any exceptions just accept it is not possible to - // determine the safety of openssl_x509_parse and bail out. - return self::$useOpensslParse = false; - } - - $output = preg_split('{\r?\n}', trim($process->getOutput())); - $errorOutput = trim($process->getErrorOutput()); - - if ( - is_array($output) - && count($output) === 3 - && $output[0] === sprintf('string(%d) "%s"', strlen(PHP_VERSION), PHP_VERSION) - && $output[1] === 'string(27) "stefan.esser@sektioneins.de"' - && $output[2] === 'int(-1)' - && preg_match('{openssl_x509_parse\(\): illegal (?:ASN1 data type for|length in) timestamp in - on line \d+}', $errorOutput) - ) { - // This PHP has the fix backported probably by a distro security team. - return self::$useOpensslParse = true; - } - - return self::$useOpensslParse = false; - } - - /** - * Resets the static caches - * @return void - */ - public static function reset() - { - self::$caFileValidity = array(); - self::$caPath = null; - self::$useOpensslParse = null; - } - - /** - * @param string $name - * @return string|false - */ - private static function getEnvVariable($name) - { - if (isset($_SERVER[$name])) { - return (string) $_SERVER[$name]; - } - - if (PHP_SAPI === 'cli' && ($value = getenv($name)) !== false && $value !== null) { - return (string) $value; - } - - return false; - } - - /** - * @param string|false $certFile - * @return bool - */ - private static function caFileUsable($certFile, LoggerInterface $logger = null) - { - return $certFile && @is_file($certFile) && @is_readable($certFile) && static::validateCaFile($certFile, $logger); - } - - /** - * @param string|false $certDir - * @return bool - */ - private static function caDirUsable($certDir) - { - return $certDir && @is_dir($certDir) && @is_readable($certDir) && glob($certDir . '/*'); - } -} diff --git a/twitter/vendor/composer/installed.json b/twitter/vendor/composer/installed.json deleted file mode 100644 index 2649372c7..000000000 --- a/twitter/vendor/composer/installed.json +++ /dev/null @@ -1,317 +0,0 @@ -[ - { - "name": "abraham/twitteroauth", - "version": "2.0.0", - "version_normalized": "2.0.0.0", - "source": { - "type": "git", - "url": "https://github.com/abraham/twitteroauth.git", - "reference": "96f49e67baec10f5e5cb703d87be16ba01a798a5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/abraham/twitteroauth/zipball/96f49e67baec10f5e5cb703d87be16ba01a798a5", - "reference": "96f49e67baec10f5e5cb703d87be16ba01a798a5", - "shasum": "" - }, - "require": { - "composer/ca-bundle": "^1.2", - "ext-curl": "*", - "php": "^7.2 || ^7.3 || ^7.4 || ^8.0" - }, - "require-dev": { - "php-vcr/php-vcr": "^1", - "php-vcr/phpunit-testlistener-vcr": "dev-php-8", - "phpmd/phpmd": "^2", - "phpunit/phpunit": "^8", - "squizlabs/php_codesniffer": "^3" - }, - "time": "2020-12-02T01:27:06+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Abraham\\TwitterOAuth\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Abraham Williams", - "email": "abraham@abrah.am", - "homepage": "https://abrah.am", - "role": "Developer" - } - ], - "description": "The most popular PHP library for use with the Twitter OAuth REST API.", - "homepage": "https://twitteroauth.com", - "keywords": [ - "Twitter API", - "Twitter oAuth", - "api", - "oauth", - "rest", - "social", - "twitter" - ] - }, - { - "name": "composer/ca-bundle", - "version": "1.2.10", - "version_normalized": "1.2.10.0", - "source": { - "type": "git", - "url": "https://github.com/composer/ca-bundle.git", - "reference": "9fdb22c2e97a614657716178093cd1da90a64aa8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/ca-bundle/zipball/9fdb22c2e97a614657716178093cd1da90a64aa8", - "reference": "9fdb22c2e97a614657716178093cd1da90a64aa8", - "shasum": "" - }, - "require": { - "ext-openssl": "*", - "ext-pcre": "*", - "php": "^5.3.2 || ^7.0 || ^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^0.12.55", - "psr/log": "^1.0", - "symfony/phpunit-bridge": "^4.2 || ^5", - "symfony/process": "^2.5 || ^3.0 || ^4.0 || ^5.0" - }, - "time": "2021-06-07T13:58:28+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Composer\\CaBundle\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - } - ], - "description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.", - "keywords": [ - "cabundle", - "cacert", - "certificate", - "ssl", - "tls" - ], - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ] - }, - { - "name": "composer/installers", - "version": "v1.6.0", - "version_normalized": "1.6.0.0", - "source": { - "type": "git", - "url": "https://github.com/composer/installers.git", - "reference": "cfcca6b1b60bc4974324efb5783c13dca6932b5b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/installers/zipball/cfcca6b1b60bc4974324efb5783c13dca6932b5b", - "reference": "cfcca6b1b60bc4974324efb5783c13dca6932b5b", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^1.0" - }, - "replace": { - "roundcube/plugin-installer": "*", - "shama/baton": "*" - }, - "require-dev": { - "composer/composer": "1.0.*@dev", - "phpunit/phpunit": "^4.8.36" - }, - "time": "2018-08-27T06:10:37+00:00", - "type": "composer-plugin", - "extra": { - "class": "Composer\\Installers\\Plugin", - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Composer\\Installers\\": "src/Composer/Installers" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Kyle Robinson Young", - "email": "kyle@dontkry.com", - "homepage": "https://github.com/shama" - } - ], - "description": "A multi-framework Composer library installer", - "homepage": "https://composer.github.io/installers/", - "keywords": [ - "Craft", - "Dolibarr", - "Eliasis", - "Hurad", - "ImageCMS", - "Kanboard", - "Lan Management System", - "MODX Evo", - "Mautic", - "Maya", - "OXID", - "Plentymarkets", - "Porto", - "RadPHP", - "SMF", - "Thelia", - "WolfCMS", - "agl", - "aimeos", - "annotatecms", - "attogram", - "bitrix", - "cakephp", - "chef", - "cockpit", - "codeigniter", - "concrete5", - "croogo", - "dokuwiki", - "drupal", - "eZ Platform", - "elgg", - "expressionengine", - "fuelphp", - "grav", - "installer", - "itop", - "joomla", - "kohana", - "laravel", - "lavalite", - "lithium", - "magento", - "majima", - "mako", - "mediawiki", - "modulework", - "modx", - "moodle", - "osclass", - "phpbb", - "piwik", - "ppi", - "puppet", - "pxcms", - "reindex", - "roundcube", - "shopware", - "silverstripe", - "sydes", - "symfony", - "typo3", - "wordpress", - "yawik", - "zend", - "zikula" - ] - }, - { - "name": "jublonet/codebird-php", - "version": "dev-master", - "version_normalized": "9999999-dev", - "source": { - "type": "git", - "url": "https://github.com/jublo/codebird-php.git", - "reference": "df362d8ad629aad6c4c7dbf36a440e569ec41368" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/jublo/codebird-php/zipball/df362d8ad629aad6c4c7dbf36a440e569ec41368", - "reference": "df362d8ad629aad6c4c7dbf36a440e569ec41368", - "shasum": "" - }, - "require": { - "composer/installers": "~1.0", - "ext-hash": "*", - "ext-json": "*", - "lib-openssl": "*", - "php": ">=5.5.0" - }, - "require-dev": { - "php-coveralls/php-coveralls": ">=0.6", - "phpunit/phpunit": ">=7.3", - "squizlabs/php_codesniffer": "2.*" - }, - "time": "2018-08-16T00:07:08+00:00", - "type": "library", - "installation-source": "source", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "GPL-3.0+" - ], - "authors": [ - { - "name": "Joshua Atkins", - "role": "Developer", - "email": "joshua.atkins@jublo.net", - "homepage": "http://atkins.im/" - }, - { - "name": "J.M.", - "role": "Developer", - "email": "jm@jublo.net", - "homepage": "http://mynetx.net/" - } - ], - "description": "Easy access to the Twitter REST API, Direct Messages API, Account Activity API, TON (Object Nest) API and Twitter Ads API — all from one PHP library.", - "homepage": "https://www.jublo.net/projects/codebird/php", - "keywords": [ - "api", - "networking", - "twitter" - ] - } -] diff --git a/twitter/vendor/composer/installers/LICENSE b/twitter/vendor/composer/installers/LICENSE deleted file mode 100644 index 85f97fc79..000000000 --- a/twitter/vendor/composer/installers/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2012 Kyle Robinson Young - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. \ No newline at end of file diff --git a/twitter/vendor/composer/installers/composer.json b/twitter/vendor/composer/installers/composer.json deleted file mode 100644 index 6de40853c..000000000 --- a/twitter/vendor/composer/installers/composer.json +++ /dev/null @@ -1,105 +0,0 @@ -{ - "name": "composer/installers", - "type": "composer-plugin", - "license": "MIT", - "description": "A multi-framework Composer library installer", - "keywords": [ - "installer", - "Aimeos", - "AGL", - "AnnotateCms", - "Attogram", - "Bitrix", - "CakePHP", - "Chef", - "Cockpit", - "CodeIgniter", - "concrete5", - "Craft", - "Croogo", - "DokuWiki", - "Dolibarr", - "Drupal", - "Elgg", - "Eliasis", - "ExpressionEngine", - "eZ Platform", - "FuelPHP", - "Grav", - "Hurad", - "ImageCMS", - "iTop", - "Joomla", - "Kanboard", - "Kohana", - "Lan Management System", - "Laravel", - "Lavalite", - "Lithium", - "Magento", - "majima", - "Mako", - "Mautic", - "Maya", - "MODX", - "MODX Evo", - "MediaWiki", - "OXID", - "osclass", - "MODULEWork", - "Moodle", - "Piwik", - "pxcms", - "phpBB", - "Plentymarkets", - "PPI", - "Puppet", - "Porto", - "RadPHP", - "ReIndex", - "Roundcube", - "shopware", - "SilverStripe", - "SMF", - "SyDES", - "symfony", - "Thelia", - "TYPO3", - "WolfCMS", - "WordPress", - "YAWIK", - "Zend", - "Zikula" - ], - "homepage": "https://composer.github.io/installers/", - "authors": [ - { - "name": "Kyle Robinson Young", - "email": "kyle@dontkry.com", - "homepage": "https://github.com/shama" - } - ], - "autoload": { - "psr-4": { "Composer\\Installers\\": "src/Composer/Installers" } - }, - "extra": { - "class": "Composer\\Installers\\Plugin", - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "replace": { - "shama/baton": "*", - "roundcube/plugin-installer": "*" - }, - "require": { - "composer-plugin-api": "^1.0" - }, - "require-dev": { - "composer/composer": "1.0.*@dev", - "phpunit/phpunit": "^4.8.36" - }, - "scripts": { - "test": "phpunit" - } -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/AglInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/AglInstaller.php deleted file mode 100644 index 01b8a4165..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/AglInstaller.php +++ /dev/null @@ -1,21 +0,0 @@ - 'More/{$name}/', - ); - - /** - * Format package name to CamelCase - */ - public function inflectPackageVars($vars) - { - $vars['name'] = preg_replace_callback('/(?:^|_|-)(.?)/', function ($matches) { - return strtoupper($matches[1]); - }, $vars['name']); - - return $vars; - } -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/AimeosInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/AimeosInstaller.php deleted file mode 100644 index 79a0e958f..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/AimeosInstaller.php +++ /dev/null @@ -1,9 +0,0 @@ - 'ext/{$name}/', - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/AnnotateCmsInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/AnnotateCmsInstaller.php deleted file mode 100644 index 89d7ad905..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/AnnotateCmsInstaller.php +++ /dev/null @@ -1,11 +0,0 @@ - 'addons/modules/{$name}/', - 'component' => 'addons/components/{$name}/', - 'service' => 'addons/services/{$name}/', - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/AsgardInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/AsgardInstaller.php deleted file mode 100644 index 22dad1b9a..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/AsgardInstaller.php +++ /dev/null @@ -1,49 +0,0 @@ - 'Modules/{$name}/', - 'theme' => 'Themes/{$name}/' - ); - - /** - * Format package name. - * - * For package type asgard-module, cut off a trailing '-plugin' if present. - * - * For package type asgard-theme, cut off a trailing '-theme' if present. - * - */ - public function inflectPackageVars($vars) - { - if ($vars['type'] === 'asgard-module') { - return $this->inflectPluginVars($vars); - } - - if ($vars['type'] === 'asgard-theme') { - return $this->inflectThemeVars($vars); - } - - return $vars; - } - - protected function inflectPluginVars($vars) - { - $vars['name'] = preg_replace('/-module$/', '', $vars['name']); - $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']); - $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); - - return $vars; - } - - protected function inflectThemeVars($vars) - { - $vars['name'] = preg_replace('/-theme$/', '', $vars['name']); - $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']); - $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); - - return $vars; - } -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/AttogramInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/AttogramInstaller.php deleted file mode 100644 index d62fd8fd1..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/AttogramInstaller.php +++ /dev/null @@ -1,9 +0,0 @@ - 'modules/{$name}/', - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/BaseInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/BaseInstaller.php deleted file mode 100644 index 7082bf2cb..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/BaseInstaller.php +++ /dev/null @@ -1,136 +0,0 @@ -composer = $composer; - $this->package = $package; - $this->io = $io; - } - - /** - * Return the install path based on package type. - * - * @param PackageInterface $package - * @param string $frameworkType - * @return string - */ - public function getInstallPath(PackageInterface $package, $frameworkType = '') - { - $type = $this->package->getType(); - - $prettyName = $this->package->getPrettyName(); - if (strpos($prettyName, '/') !== false) { - list($vendor, $name) = explode('/', $prettyName); - } else { - $vendor = ''; - $name = $prettyName; - } - - $availableVars = $this->inflectPackageVars(compact('name', 'vendor', 'type')); - - $extra = $package->getExtra(); - if (!empty($extra['installer-name'])) { - $availableVars['name'] = $extra['installer-name']; - } - - if ($this->composer->getPackage()) { - $extra = $this->composer->getPackage()->getExtra(); - if (!empty($extra['installer-paths'])) { - $customPath = $this->mapCustomInstallPaths($extra['installer-paths'], $prettyName, $type, $vendor); - if ($customPath !== false) { - return $this->templatePath($customPath, $availableVars); - } - } - } - - $packageType = substr($type, strlen($frameworkType) + 1); - $locations = $this->getLocations(); - if (!isset($locations[$packageType])) { - throw new \InvalidArgumentException(sprintf('Package type "%s" is not supported', $type)); - } - - return $this->templatePath($locations[$packageType], $availableVars); - } - - /** - * For an installer to override to modify the vars per installer. - * - * @param array $vars - * @return array - */ - public function inflectPackageVars($vars) - { - return $vars; - } - - /** - * Gets the installer's locations - * - * @return array - */ - public function getLocations() - { - return $this->locations; - } - - /** - * Replace vars in a path - * - * @param string $path - * @param array $vars - * @return string - */ - protected function templatePath($path, array $vars = array()) - { - if (strpos($path, '{') !== false) { - extract($vars); - preg_match_all('@\{\$([A-Za-z0-9_]*)\}@i', $path, $matches); - if (!empty($matches[1])) { - foreach ($matches[1] as $var) { - $path = str_replace('{$' . $var . '}', $$var, $path); - } - } - } - - return $path; - } - - /** - * Search through a passed paths array for a custom install path. - * - * @param array $paths - * @param string $name - * @param string $type - * @param string $vendor = NULL - * @return string - */ - protected function mapCustomInstallPaths(array $paths, $name, $type, $vendor = NULL) - { - foreach ($paths as $path => $names) { - if (in_array($name, $names) || in_array('type:' . $type, $names) || in_array('vendor:' . $vendor, $names)) { - return $path; - } - } - - return false; - } -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/BitrixInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/BitrixInstaller.php deleted file mode 100644 index e80cd1e10..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/BitrixInstaller.php +++ /dev/null @@ -1,126 +0,0 @@ -.`. - * - `bitrix-d7-component` — copy the component to directory `bitrix/components//`. - * - `bitrix-d7-template` — copy the template to directory `bitrix/templates/_`. - * - * You can set custom path to directory with Bitrix kernel in `composer.json`: - * - * ```json - * { - * "extra": { - * "bitrix-dir": "s1/bitrix" - * } - * } - * ``` - * - * @author Nik Samokhvalov - * @author Denis Kulichkin - */ -class BitrixInstaller extends BaseInstaller -{ - protected $locations = array( - 'module' => '{$bitrix_dir}/modules/{$name}/', // deprecated, remove on the major release (Backward compatibility will be broken) - 'component' => '{$bitrix_dir}/components/{$name}/', // deprecated, remove on the major release (Backward compatibility will be broken) - 'theme' => '{$bitrix_dir}/templates/{$name}/', // deprecated, remove on the major release (Backward compatibility will be broken) - 'd7-module' => '{$bitrix_dir}/modules/{$vendor}.{$name}/', - 'd7-component' => '{$bitrix_dir}/components/{$vendor}/{$name}/', - 'd7-template' => '{$bitrix_dir}/templates/{$vendor}_{$name}/', - ); - - /** - * @var array Storage for informations about duplicates at all the time of installation packages. - */ - private static $checkedDuplicates = array(); - - /** - * {@inheritdoc} - */ - public function inflectPackageVars($vars) - { - if ($this->composer->getPackage()) { - $extra = $this->composer->getPackage()->getExtra(); - - if (isset($extra['bitrix-dir'])) { - $vars['bitrix_dir'] = $extra['bitrix-dir']; - } - } - - if (!isset($vars['bitrix_dir'])) { - $vars['bitrix_dir'] = 'bitrix'; - } - - return parent::inflectPackageVars($vars); - } - - /** - * {@inheritdoc} - */ - protected function templatePath($path, array $vars = array()) - { - $templatePath = parent::templatePath($path, $vars); - $this->checkDuplicates($templatePath, $vars); - - return $templatePath; - } - - /** - * Duplicates search packages. - * - * @param string $path - * @param array $vars - */ - protected function checkDuplicates($path, array $vars = array()) - { - $packageType = substr($vars['type'], strlen('bitrix') + 1); - $localDir = explode('/', $vars['bitrix_dir']); - array_pop($localDir); - $localDir[] = 'local'; - $localDir = implode('/', $localDir); - - $oldPath = str_replace( - array('{$bitrix_dir}', '{$name}'), - array($localDir, $vars['name']), - $this->locations[$packageType] - ); - - if (in_array($oldPath, static::$checkedDuplicates)) { - return; - } - - if ($oldPath !== $path && file_exists($oldPath) && $this->io && $this->io->isInteractive()) { - - $this->io->writeError(' Duplication of packages:'); - $this->io->writeError(' Package ' . $oldPath . ' will be called instead package ' . $path . ''); - - while (true) { - switch ($this->io->ask(' Delete ' . $oldPath . ' [y,n,?]? ', '?')) { - case 'y': - $fs = new Filesystem(); - $fs->removeDirectory($oldPath); - break 2; - - case 'n': - break 2; - - case '?': - default: - $this->io->writeError(array( - ' y - delete package ' . $oldPath . ' and to continue with the installation', - ' n - don\'t delete and to continue with the installation', - )); - $this->io->writeError(' ? - print help'); - break; - } - } - } - - static::$checkedDuplicates[] = $oldPath; - } -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/BonefishInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/BonefishInstaller.php deleted file mode 100644 index da3aad2a3..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/BonefishInstaller.php +++ /dev/null @@ -1,9 +0,0 @@ - 'Packages/{$vendor}/{$name}/' - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/CakePHPInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/CakePHPInstaller.php deleted file mode 100644 index 6352beb11..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/CakePHPInstaller.php +++ /dev/null @@ -1,82 +0,0 @@ - 'Plugin/{$name}/', - ); - - /** - * Format package name to CamelCase - */ - public function inflectPackageVars($vars) - { - if ($this->matchesCakeVersion('>=', '3.0.0')) { - return $vars; - } - - $nameParts = explode('/', $vars['name']); - foreach ($nameParts as &$value) { - $value = strtolower(preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $value)); - $value = str_replace(array('-', '_'), ' ', $value); - $value = str_replace(' ', '', ucwords($value)); - } - $vars['name'] = implode('/', $nameParts); - - return $vars; - } - - /** - * Change the default plugin location when cakephp >= 3.0 - */ - public function getLocations() - { - if ($this->matchesCakeVersion('>=', '3.0.0')) { - $this->locations['plugin'] = $this->composer->getConfig()->get('vendor-dir') . '/{$vendor}/{$name}/'; - } - return $this->locations; - } - - /** - * Check if CakePHP version matches against a version - * - * @param string $matcher - * @param string $version - * @return bool - */ - protected function matchesCakeVersion($matcher, $version) - { - if (class_exists('Composer\Semver\Constraint\MultiConstraint')) { - $multiClass = 'Composer\Semver\Constraint\MultiConstraint'; - $constraintClass = 'Composer\Semver\Constraint\Constraint'; - } else { - $multiClass = 'Composer\Package\LinkConstraint\MultiConstraint'; - $constraintClass = 'Composer\Package\LinkConstraint\VersionConstraint'; - } - - $repositoryManager = $this->composer->getRepositoryManager(); - if ($repositoryManager) { - $repos = $repositoryManager->getLocalRepository(); - if (!$repos) { - return false; - } - $cake3 = new $multiClass(array( - new $constraintClass($matcher, $version), - new $constraintClass('!=', '9999999-dev'), - )); - $pool = new Pool('dev'); - $pool->addRepository($repos); - $packages = $pool->whatProvides('cakephp/cakephp'); - foreach ($packages as $package) { - $installed = new $constraintClass('=', $package->getVersion()); - if ($cake3->matches($installed)) { - return true; - } - } - } - return false; - } -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/ChefInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/ChefInstaller.php deleted file mode 100644 index ab2f9aad8..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/ChefInstaller.php +++ /dev/null @@ -1,11 +0,0 @@ - 'Chef/{$vendor}/{$name}/', - 'role' => 'Chef/roles/{$name}/', - ); -} - diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/CiviCrmInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/CiviCrmInstaller.php deleted file mode 100644 index 6673aea94..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/CiviCrmInstaller.php +++ /dev/null @@ -1,9 +0,0 @@ - 'ext/{$name}/' - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/ClanCatsFrameworkInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/ClanCatsFrameworkInstaller.php deleted file mode 100644 index c887815c9..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/ClanCatsFrameworkInstaller.php +++ /dev/null @@ -1,10 +0,0 @@ - 'CCF/orbit/{$name}/', - 'theme' => 'CCF/app/themes/{$name}/', - ); -} \ No newline at end of file diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/CockpitInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/CockpitInstaller.php deleted file mode 100644 index c7816dfce..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/CockpitInstaller.php +++ /dev/null @@ -1,34 +0,0 @@ - 'cockpit/modules/addons/{$name}/', - ); - - /** - * Format module name. - * - * Strip `module-` prefix from package name. - * - * @param array @vars - * - * @return array - */ - public function inflectPackageVars($vars) - { - if ($vars['type'] == 'cockpit-module') { - return $this->inflectModuleVars($vars); - } - - return $vars; - } - - public function inflectModuleVars($vars) - { - $vars['name'] = ucfirst(preg_replace('/cockpit-/i', '', $vars['name'])); - - return $vars; - } -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/CodeIgniterInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/CodeIgniterInstaller.php deleted file mode 100644 index 3b4a4ece1..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/CodeIgniterInstaller.php +++ /dev/null @@ -1,11 +0,0 @@ - 'application/libraries/{$name}/', - 'third-party' => 'application/third_party/{$name}/', - 'module' => 'application/modules/{$name}/', - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/Concrete5Installer.php b/twitter/vendor/composer/installers/src/Composer/Installers/Concrete5Installer.php deleted file mode 100644 index 5c01bafd7..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/Concrete5Installer.php +++ /dev/null @@ -1,13 +0,0 @@ - 'concrete/', - 'block' => 'application/blocks/{$name}/', - 'package' => 'packages/{$name}/', - 'theme' => 'application/themes/{$name}/', - 'update' => 'updates/{$name}/', - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/CraftInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/CraftInstaller.php deleted file mode 100644 index d37a77ae2..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/CraftInstaller.php +++ /dev/null @@ -1,35 +0,0 @@ - 'craft/plugins/{$name}/', - ); - - /** - * Strip `craft-` prefix and/or `-plugin` suffix from package names - * - * @param array $vars - * - * @return array - */ - final public function inflectPackageVars($vars) - { - return $this->inflectPluginVars($vars); - } - - private function inflectPluginVars($vars) - { - $vars['name'] = preg_replace('/-' . self::NAME_SUFFIX . '$/i', '', $vars['name']); - $vars['name'] = preg_replace('/^' . self::NAME_PREFIX . '-/i', '', $vars['name']); - - return $vars; - } -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/CroogoInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/CroogoInstaller.php deleted file mode 100644 index d94219d3a..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/CroogoInstaller.php +++ /dev/null @@ -1,21 +0,0 @@ - 'Plugin/{$name}/', - 'theme' => 'View/Themed/{$name}/', - ); - - /** - * Format package name to CamelCase - */ - public function inflectPackageVars($vars) - { - $vars['name'] = strtolower(str_replace(array('-', '_'), ' ', $vars['name'])); - $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); - - return $vars; - } -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/DecibelInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/DecibelInstaller.php deleted file mode 100644 index f4837a6c1..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/DecibelInstaller.php +++ /dev/null @@ -1,10 +0,0 @@ - 'app/{$name}/', - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/DokuWikiInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/DokuWikiInstaller.php deleted file mode 100644 index cfd638d5f..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/DokuWikiInstaller.php +++ /dev/null @@ -1,50 +0,0 @@ - 'lib/plugins/{$name}/', - 'template' => 'lib/tpl/{$name}/', - ); - - /** - * Format package name. - * - * For package type dokuwiki-plugin, cut off a trailing '-plugin', - * or leading dokuwiki_ if present. - * - * For package type dokuwiki-template, cut off a trailing '-template' if present. - * - */ - public function inflectPackageVars($vars) - { - - if ($vars['type'] === 'dokuwiki-plugin') { - return $this->inflectPluginVars($vars); - } - - if ($vars['type'] === 'dokuwiki-template') { - return $this->inflectTemplateVars($vars); - } - - return $vars; - } - - protected function inflectPluginVars($vars) - { - $vars['name'] = preg_replace('/-plugin$/', '', $vars['name']); - $vars['name'] = preg_replace('/^dokuwiki_?-?/', '', $vars['name']); - - return $vars; - } - - protected function inflectTemplateVars($vars) - { - $vars['name'] = preg_replace('/-template$/', '', $vars['name']); - $vars['name'] = preg_replace('/^dokuwiki_?-?/', '', $vars['name']); - - return $vars; - } - -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/DolibarrInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/DolibarrInstaller.php deleted file mode 100644 index 21f7e8e80..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/DolibarrInstaller.php +++ /dev/null @@ -1,16 +0,0 @@ - - */ -class DolibarrInstaller extends BaseInstaller -{ - //TODO: Add support for scripts and themes - protected $locations = array( - 'module' => 'htdocs/custom/{$name}/', - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/DrupalInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/DrupalInstaller.php deleted file mode 100644 index fef7c525d..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/DrupalInstaller.php +++ /dev/null @@ -1,16 +0,0 @@ - 'core/', - 'module' => 'modules/{$name}/', - 'theme' => 'themes/{$name}/', - 'library' => 'libraries/{$name}/', - 'profile' => 'profiles/{$name}/', - 'drush' => 'drush/{$name}/', - 'custom-theme' => 'themes/custom/{$name}/', - 'custom-module' => 'modules/custom/{$name}/', - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/ElggInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/ElggInstaller.php deleted file mode 100644 index c0bb609f4..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/ElggInstaller.php +++ /dev/null @@ -1,9 +0,0 @@ - 'mod/{$name}/', - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/EliasisInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/EliasisInstaller.php deleted file mode 100644 index 6f3dc97b1..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/EliasisInstaller.php +++ /dev/null @@ -1,12 +0,0 @@ - 'components/{$name}/', - 'module' => 'modules/{$name}/', - 'plugin' => 'plugins/{$name}/', - 'template' => 'templates/{$name}/', - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/ExpressionEngineInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/ExpressionEngineInstaller.php deleted file mode 100644 index d5321a8ca..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/ExpressionEngineInstaller.php +++ /dev/null @@ -1,29 +0,0 @@ - 'system/expressionengine/third_party/{$name}/', - 'theme' => 'themes/third_party/{$name}/', - ); - - private $ee3Locations = array( - 'addon' => 'system/user/addons/{$name}/', - 'theme' => 'themes/user/{$name}/', - ); - - public function getInstallPath(PackageInterface $package, $frameworkType = '') - { - - $version = "{$frameworkType}Locations"; - $this->locations = $this->$version; - - return parent::getInstallPath($package, $frameworkType); - } -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/EzPlatformInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/EzPlatformInstaller.php deleted file mode 100644 index f30ebcc77..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/EzPlatformInstaller.php +++ /dev/null @@ -1,10 +0,0 @@ - 'web/assets/ezplatform/', - 'assets' => 'web/assets/ezplatform/{$name}/', - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/FuelInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/FuelInstaller.php deleted file mode 100644 index 6eba2e34f..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/FuelInstaller.php +++ /dev/null @@ -1,11 +0,0 @@ - 'fuel/app/modules/{$name}/', - 'package' => 'fuel/packages/{$name}/', - 'theme' => 'fuel/app/themes/{$name}/', - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/FuelphpInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/FuelphpInstaller.php deleted file mode 100644 index 29d980b30..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/FuelphpInstaller.php +++ /dev/null @@ -1,9 +0,0 @@ - 'components/{$name}/', - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/GravInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/GravInstaller.php deleted file mode 100644 index dbe63e07e..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/GravInstaller.php +++ /dev/null @@ -1,30 +0,0 @@ - 'user/plugins/{$name}/', - 'theme' => 'user/themes/{$name}/', - ); - - /** - * Format package name - * - * @param array $vars - * - * @return array - */ - public function inflectPackageVars($vars) - { - $restrictedWords = implode('|', array_keys($this->locations)); - - $vars['name'] = strtolower($vars['name']); - $vars['name'] = preg_replace('/^(?:grav-)?(?:(?:'.$restrictedWords.')-)?(.*?)(?:-(?:'.$restrictedWords.'))?$/ui', - '$1', - $vars['name'] - ); - - return $vars; - } -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/HuradInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/HuradInstaller.php deleted file mode 100644 index 8fe017f0f..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/HuradInstaller.php +++ /dev/null @@ -1,25 +0,0 @@ - 'plugins/{$name}/', - 'theme' => 'plugins/{$name}/', - ); - - /** - * Format package name to CamelCase - */ - public function inflectPackageVars($vars) - { - $nameParts = explode('/', $vars['name']); - foreach ($nameParts as &$value) { - $value = strtolower(preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $value)); - $value = str_replace(array('-', '_'), ' ', $value); - $value = str_replace(' ', '', ucwords($value)); - } - $vars['name'] = implode('/', $nameParts); - return $vars; - } -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/ImageCMSInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/ImageCMSInstaller.php deleted file mode 100644 index 5e2142ea5..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/ImageCMSInstaller.php +++ /dev/null @@ -1,11 +0,0 @@ - 'templates/{$name}/', - 'module' => 'application/modules/{$name}/', - 'library' => 'application/libraries/{$name}/', - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/Installer.php b/twitter/vendor/composer/installers/src/Composer/Installers/Installer.php deleted file mode 100644 index 352cb7fae..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/Installer.php +++ /dev/null @@ -1,274 +0,0 @@ - 'AimeosInstaller', - 'asgard' => 'AsgardInstaller', - 'attogram' => 'AttogramInstaller', - 'agl' => 'AglInstaller', - 'annotatecms' => 'AnnotateCmsInstaller', - 'bitrix' => 'BitrixInstaller', - 'bonefish' => 'BonefishInstaller', - 'cakephp' => 'CakePHPInstaller', - 'chef' => 'ChefInstaller', - 'civicrm' => 'CiviCrmInstaller', - 'ccframework' => 'ClanCatsFrameworkInstaller', - 'cockpit' => 'CockpitInstaller', - 'codeigniter' => 'CodeIgniterInstaller', - 'concrete5' => 'Concrete5Installer', - 'craft' => 'CraftInstaller', - 'croogo' => 'CroogoInstaller', - 'dokuwiki' => 'DokuWikiInstaller', - 'dolibarr' => 'DolibarrInstaller', - 'decibel' => 'DecibelInstaller', - 'drupal' => 'DrupalInstaller', - 'elgg' => 'ElggInstaller', - 'eliasis' => 'EliasisInstaller', - 'ee3' => 'ExpressionEngineInstaller', - 'ee2' => 'ExpressionEngineInstaller', - 'ezplatform' => 'EzPlatformInstaller', - 'fuel' => 'FuelInstaller', - 'fuelphp' => 'FuelphpInstaller', - 'grav' => 'GravInstaller', - 'hurad' => 'HuradInstaller', - 'imagecms' => 'ImageCMSInstaller', - 'itop' => 'ItopInstaller', - 'joomla' => 'JoomlaInstaller', - 'kanboard' => 'KanboardInstaller', - 'kirby' => 'KirbyInstaller', - 'kodicms' => 'KodiCMSInstaller', - 'kohana' => 'KohanaInstaller', - 'lms' => 'LanManagementSystemInstaller', - 'laravel' => 'LaravelInstaller', - 'lavalite' => 'LavaLiteInstaller', - 'lithium' => 'LithiumInstaller', - 'magento' => 'MagentoInstaller', - 'majima' => 'MajimaInstaller', - 'mako' => 'MakoInstaller', - 'maya' => 'MayaInstaller', - 'mautic' => 'MauticInstaller', - 'mediawiki' => 'MediaWikiInstaller', - 'microweber' => 'MicroweberInstaller', - 'modulework' => 'MODULEWorkInstaller', - 'modx' => 'ModxInstaller', - 'modxevo' => 'MODXEvoInstaller', - 'moodle' => 'MoodleInstaller', - 'october' => 'OctoberInstaller', - 'ontowiki' => 'OntoWikiInstaller', - 'oxid' => 'OxidInstaller', - 'osclass' => 'OsclassInstaller', - 'pxcms' => 'PxcmsInstaller', - 'phpbb' => 'PhpBBInstaller', - 'pimcore' => 'PimcoreInstaller', - 'piwik' => 'PiwikInstaller', - 'plentymarkets'=> 'PlentymarketsInstaller', - 'ppi' => 'PPIInstaller', - 'puppet' => 'PuppetInstaller', - 'radphp' => 'RadPHPInstaller', - 'phifty' => 'PhiftyInstaller', - 'porto' => 'PortoInstaller', - 'redaxo' => 'RedaxoInstaller', - 'reindex' => 'ReIndexInstaller', - 'roundcube' => 'RoundcubeInstaller', - 'shopware' => 'ShopwareInstaller', - 'sitedirect' => 'SiteDirectInstaller', - 'silverstripe' => 'SilverStripeInstaller', - 'smf' => 'SMFInstaller', - 'sydes' => 'SyDESInstaller', - 'symfony1' => 'Symfony1Installer', - 'thelia' => 'TheliaInstaller', - 'tusk' => 'TuskInstaller', - 'typo3-cms' => 'TYPO3CmsInstaller', - 'typo3-flow' => 'TYPO3FlowInstaller', - 'userfrosting' => 'UserFrostingInstaller', - 'vanilla' => 'VanillaInstaller', - 'whmcs' => 'WHMCSInstaller', - 'wolfcms' => 'WolfCMSInstaller', - 'wordpress' => 'WordPressInstaller', - 'yawik' => 'YawikInstaller', - 'zend' => 'ZendInstaller', - 'zikula' => 'ZikulaInstaller', - 'prestashop' => 'PrestashopInstaller' - ); - - /** - * Installer constructor. - * - * Disables installers specified in main composer extra installer-disable - * list - * - * @param IOInterface $io - * @param Composer $composer - * @param string $type - * @param Filesystem|null $filesystem - * @param BinaryInstaller|null $binaryInstaller - */ - public function __construct( - IOInterface $io, - Composer $composer, - $type = 'library', - Filesystem $filesystem = null, - BinaryInstaller $binaryInstaller = null - ) { - parent::__construct($io, $composer, $type, $filesystem, - $binaryInstaller); - $this->removeDisabledInstallers(); - } - - /** - * {@inheritDoc} - */ - public function getInstallPath(PackageInterface $package) - { - $type = $package->getType(); - $frameworkType = $this->findFrameworkType($type); - - if ($frameworkType === false) { - throw new \InvalidArgumentException( - 'Sorry the package type of this package is not yet supported.' - ); - } - - $class = 'Composer\\Installers\\' . $this->supportedTypes[$frameworkType]; - $installer = new $class($package, $this->composer, $this->getIO()); - - return $installer->getInstallPath($package, $frameworkType); - } - - public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package) - { - parent::uninstall($repo, $package); - $installPath = $this->getPackageBasePath($package); - $this->io->write(sprintf('Deleting %s - %s', $installPath, !file_exists($installPath) ? 'deleted' : 'not deleted')); - } - - /** - * {@inheritDoc} - */ - public function supports($packageType) - { - $frameworkType = $this->findFrameworkType($packageType); - - if ($frameworkType === false) { - return false; - } - - $locationPattern = $this->getLocationPattern($frameworkType); - - return preg_match('#' . $frameworkType . '-' . $locationPattern . '#', $packageType, $matches) === 1; - } - - /** - * Finds a supported framework type if it exists and returns it - * - * @param string $type - * @return string - */ - protected function findFrameworkType($type) - { - $frameworkType = false; - - krsort($this->supportedTypes); - - foreach ($this->supportedTypes as $key => $val) { - if ($key === substr($type, 0, strlen($key))) { - $frameworkType = substr($type, 0, strlen($key)); - break; - } - } - - return $frameworkType; - } - - /** - * Get the second part of the regular expression to check for support of a - * package type - * - * @param string $frameworkType - * @return string - */ - protected function getLocationPattern($frameworkType) - { - $pattern = false; - if (!empty($this->supportedTypes[$frameworkType])) { - $frameworkClass = 'Composer\\Installers\\' . $this->supportedTypes[$frameworkType]; - /** @var BaseInstaller $framework */ - $framework = new $frameworkClass(null, $this->composer, $this->getIO()); - $locations = array_keys($framework->getLocations()); - $pattern = $locations ? '(' . implode('|', $locations) . ')' : false; - } - - return $pattern ? : '(\w+)'; - } - - /** - * Get I/O object - * - * @return IOInterface - */ - private function getIO() - { - return $this->io; - } - - /** - * Look for installers set to be disabled in composer's extra config and - * remove them from the list of supported installers. - * - * Globals: - * - true, "all", and "*" - disable all installers. - * - false - enable all installers (useful with - * wikimedia/composer-merge-plugin or similar) - * - * @return void - */ - protected function removeDisabledInstallers() - { - $extra = $this->composer->getPackage()->getExtra(); - - if (!isset($extra['installer-disable']) || $extra['installer-disable'] === false) { - // No installers are disabled - return; - } - - // Get installers to disable - $disable = $extra['installer-disable']; - - // Ensure $disabled is an array - if (!is_array($disable)) { - $disable = array($disable); - } - - // Check which installers should be disabled - $all = array(true, "all", "*"); - $intersect = array_intersect($all, $disable); - if (!empty($intersect)) { - // Disable all installers - $this->supportedTypes = array(); - } else { - // Disable specified installers - foreach ($disable as $key => $installer) { - if (is_string($installer) && key_exists($installer, $this->supportedTypes)) { - unset($this->supportedTypes[$installer]); - } - } - } - } -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/ItopInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/ItopInstaller.php deleted file mode 100644 index c6c1b3374..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/ItopInstaller.php +++ /dev/null @@ -1,9 +0,0 @@ - 'extensions/{$name}/', - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/JoomlaInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/JoomlaInstaller.php deleted file mode 100644 index 9ee775965..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/JoomlaInstaller.php +++ /dev/null @@ -1,15 +0,0 @@ - 'components/{$name}/', - 'module' => 'modules/{$name}/', - 'template' => 'templates/{$name}/', - 'plugin' => 'plugins/{$name}/', - 'library' => 'libraries/{$name}/', - ); - - // TODO: Add inflector for mod_ and com_ names -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/KanboardInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/KanboardInstaller.php deleted file mode 100644 index 9cb7b8cdb..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/KanboardInstaller.php +++ /dev/null @@ -1,18 +0,0 @@ - 'plugins/{$name}/', - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/KirbyInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/KirbyInstaller.php deleted file mode 100644 index 36b2f84a7..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/KirbyInstaller.php +++ /dev/null @@ -1,11 +0,0 @@ - 'site/plugins/{$name}/', - 'field' => 'site/fields/{$name}/', - 'tag' => 'site/tags/{$name}/' - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/KodiCMSInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/KodiCMSInstaller.php deleted file mode 100644 index 7143e232b..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/KodiCMSInstaller.php +++ /dev/null @@ -1,10 +0,0 @@ - 'cms/plugins/{$name}/', - 'media' => 'cms/media/vendor/{$name}/' - ); -} \ No newline at end of file diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/KohanaInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/KohanaInstaller.php deleted file mode 100644 index dcd6d2632..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/KohanaInstaller.php +++ /dev/null @@ -1,9 +0,0 @@ - 'modules/{$name}/', - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/LanManagementSystemInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/LanManagementSystemInstaller.php deleted file mode 100644 index 903143a55..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/LanManagementSystemInstaller.php +++ /dev/null @@ -1,27 +0,0 @@ - 'plugins/{$name}/', - 'template' => 'templates/{$name}/', - 'document-template' => 'documents/templates/{$name}/', - 'userpanel-module' => 'userpanel/modules/{$name}/', - ); - - /** - * Format package name to CamelCase - */ - public function inflectPackageVars($vars) - { - $vars['name'] = strtolower(preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $vars['name'])); - $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']); - $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); - - return $vars; - } - -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/LaravelInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/LaravelInstaller.php deleted file mode 100644 index be4d53a7b..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/LaravelInstaller.php +++ /dev/null @@ -1,9 +0,0 @@ - 'libraries/{$name}/', - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/LavaLiteInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/LavaLiteInstaller.php deleted file mode 100644 index 412c0b5c0..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/LavaLiteInstaller.php +++ /dev/null @@ -1,10 +0,0 @@ - 'packages/{$vendor}/{$name}/', - 'theme' => 'public/themes/{$name}/', - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/LithiumInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/LithiumInstaller.php deleted file mode 100644 index 47bbd4cab..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/LithiumInstaller.php +++ /dev/null @@ -1,10 +0,0 @@ - 'libraries/{$name}/', - 'source' => 'libraries/_source/{$name}/', - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/MODULEWorkInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/MODULEWorkInstaller.php deleted file mode 100644 index 9c2e9fb40..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/MODULEWorkInstaller.php +++ /dev/null @@ -1,9 +0,0 @@ - 'modules/{$name}/', - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/MODXEvoInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/MODXEvoInstaller.php deleted file mode 100644 index 5a664608d..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/MODXEvoInstaller.php +++ /dev/null @@ -1,16 +0,0 @@ - 'assets/snippets/{$name}/', - 'plugin' => 'assets/plugins/{$name}/', - 'module' => 'assets/modules/{$name}/', - 'template' => 'assets/templates/{$name}/', - 'lib' => 'assets/lib/{$name}/' - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/MagentoInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/MagentoInstaller.php deleted file mode 100644 index cf18e9478..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/MagentoInstaller.php +++ /dev/null @@ -1,11 +0,0 @@ - 'app/design/frontend/{$name}/', - 'skin' => 'skin/frontend/default/{$name}/', - 'library' => 'lib/{$name}/', - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/MajimaInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/MajimaInstaller.php deleted file mode 100644 index e463756fa..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/MajimaInstaller.php +++ /dev/null @@ -1,37 +0,0 @@ - 'plugins/{$name}/', - ); - - /** - * Transforms the names - * @param array $vars - * @return array - */ - public function inflectPackageVars($vars) - { - return $this->correctPluginName($vars); - } - - /** - * Change hyphenated names to camelcase - * @param array $vars - * @return array - */ - private function correctPluginName($vars) - { - $camelCasedName = preg_replace_callback('/(-[a-z])/', function ($matches) { - return strtoupper($matches[0][1]); - }, $vars['name']); - $vars['name'] = ucfirst($camelCasedName); - return $vars; - } -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/MakoInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/MakoInstaller.php deleted file mode 100644 index ca3cfacb4..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/MakoInstaller.php +++ /dev/null @@ -1,9 +0,0 @@ - 'app/packages/{$name}/', - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/MauticInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/MauticInstaller.php deleted file mode 100644 index 3e1ce2b2d..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/MauticInstaller.php +++ /dev/null @@ -1,25 +0,0 @@ - 'plugins/{$name}/', - 'theme' => 'themes/{$name}/', - ); - - /** - * Format package name of mautic-plugins to CamelCase - */ - public function inflectPackageVars($vars) - { - if ($vars['type'] == 'mautic-plugin') { - $vars['name'] = preg_replace_callback('/(-[a-z])/', function ($matches) { - return strtoupper($matches[0][1]); - }, ucfirst($vars['name'])); - } - - return $vars; - } - -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/MayaInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/MayaInstaller.php deleted file mode 100644 index 30a91676d..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/MayaInstaller.php +++ /dev/null @@ -1,33 +0,0 @@ - 'modules/{$name}/', - ); - - /** - * Format package name. - * - * For package type maya-module, cut off a trailing '-module' if present. - * - */ - public function inflectPackageVars($vars) - { - if ($vars['type'] === 'maya-module') { - return $this->inflectModuleVars($vars); - } - - return $vars; - } - - protected function inflectModuleVars($vars) - { - $vars['name'] = preg_replace('/-module$/', '', $vars['name']); - $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']); - $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); - - return $vars; - } -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/MediaWikiInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/MediaWikiInstaller.php deleted file mode 100644 index f5a8957ef..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/MediaWikiInstaller.php +++ /dev/null @@ -1,51 +0,0 @@ - 'core/', - 'extension' => 'extensions/{$name}/', - 'skin' => 'skins/{$name}/', - ); - - /** - * Format package name. - * - * For package type mediawiki-extension, cut off a trailing '-extension' if present and transform - * to CamelCase keeping existing uppercase chars. - * - * For package type mediawiki-skin, cut off a trailing '-skin' if present. - * - */ - public function inflectPackageVars($vars) - { - - if ($vars['type'] === 'mediawiki-extension') { - return $this->inflectExtensionVars($vars); - } - - if ($vars['type'] === 'mediawiki-skin') { - return $this->inflectSkinVars($vars); - } - - return $vars; - } - - protected function inflectExtensionVars($vars) - { - $vars['name'] = preg_replace('/-extension$/', '', $vars['name']); - $vars['name'] = str_replace('-', ' ', $vars['name']); - $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); - - return $vars; - } - - protected function inflectSkinVars($vars) - { - $vars['name'] = preg_replace('/-skin$/', '', $vars['name']); - - return $vars; - } - -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/MicroweberInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/MicroweberInstaller.php deleted file mode 100644 index 4bbbec8c0..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/MicroweberInstaller.php +++ /dev/null @@ -1,111 +0,0 @@ - 'userfiles/modules/{$name}/', - 'module-skin' => 'userfiles/modules/{$name}/templates/', - 'template' => 'userfiles/templates/{$name}/', - 'element' => 'userfiles/elements/{$name}/', - 'vendor' => 'vendor/{$name}/', - 'components' => 'components/{$name}/' - ); - - /** - * Format package name. - * - * For package type microweber-module, cut off a trailing '-module' if present - * - * For package type microweber-template, cut off a trailing '-template' if present. - * - */ - public function inflectPackageVars($vars) - { - if ($vars['type'] === 'microweber-template') { - return $this->inflectTemplateVars($vars); - } - if ($vars['type'] === 'microweber-templates') { - return $this->inflectTemplatesVars($vars); - } - if ($vars['type'] === 'microweber-core') { - return $this->inflectCoreVars($vars); - } - if ($vars['type'] === 'microweber-adapter') { - return $this->inflectCoreVars($vars); - } - if ($vars['type'] === 'microweber-module') { - return $this->inflectModuleVars($vars); - } - if ($vars['type'] === 'microweber-modules') { - return $this->inflectModulesVars($vars); - } - if ($vars['type'] === 'microweber-skin') { - return $this->inflectSkinVars($vars); - } - if ($vars['type'] === 'microweber-element' or $vars['type'] === 'microweber-elements') { - return $this->inflectElementVars($vars); - } - - return $vars; - } - - protected function inflectTemplateVars($vars) - { - $vars['name'] = preg_replace('/-template$/', '', $vars['name']); - $vars['name'] = preg_replace('/template-$/', '', $vars['name']); - - return $vars; - } - - protected function inflectTemplatesVars($vars) - { - $vars['name'] = preg_replace('/-templates$/', '', $vars['name']); - $vars['name'] = preg_replace('/templates-$/', '', $vars['name']); - - return $vars; - } - - protected function inflectCoreVars($vars) - { - $vars['name'] = preg_replace('/-providers$/', '', $vars['name']); - $vars['name'] = preg_replace('/-provider$/', '', $vars['name']); - $vars['name'] = preg_replace('/-adapter$/', '', $vars['name']); - - return $vars; - } - - protected function inflectModuleVars($vars) - { - $vars['name'] = preg_replace('/-module$/', '', $vars['name']); - $vars['name'] = preg_replace('/module-$/', '', $vars['name']); - - return $vars; - } - - protected function inflectModulesVars($vars) - { - $vars['name'] = preg_replace('/-modules$/', '', $vars['name']); - $vars['name'] = preg_replace('/modules-$/', '', $vars['name']); - - return $vars; - } - - protected function inflectSkinVars($vars) - { - $vars['name'] = preg_replace('/-skin$/', '', $vars['name']); - $vars['name'] = preg_replace('/skin-$/', '', $vars['name']); - - return $vars; - } - - protected function inflectElementVars($vars) - { - $vars['name'] = preg_replace('/-elements$/', '', $vars['name']); - $vars['name'] = preg_replace('/elements-$/', '', $vars['name']); - $vars['name'] = preg_replace('/-element$/', '', $vars['name']); - $vars['name'] = preg_replace('/element-$/', '', $vars['name']); - - return $vars; - } -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/ModxInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/ModxInstaller.php deleted file mode 100644 index 0ee140abf..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/ModxInstaller.php +++ /dev/null @@ -1,12 +0,0 @@ - 'core/packages/{$name}/' - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/MoodleInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/MoodleInstaller.php deleted file mode 100644 index a89c82f73..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/MoodleInstaller.php +++ /dev/null @@ -1,57 +0,0 @@ - 'mod/{$name}/', - 'admin_report' => 'admin/report/{$name}/', - 'atto' => 'lib/editor/atto/plugins/{$name}/', - 'tool' => 'admin/tool/{$name}/', - 'assignment' => 'mod/assignment/type/{$name}/', - 'assignsubmission' => 'mod/assign/submission/{$name}/', - 'assignfeedback' => 'mod/assign/feedback/{$name}/', - 'auth' => 'auth/{$name}/', - 'availability' => 'availability/condition/{$name}/', - 'block' => 'blocks/{$name}/', - 'booktool' => 'mod/book/tool/{$name}/', - 'cachestore' => 'cache/stores/{$name}/', - 'cachelock' => 'cache/locks/{$name}/', - 'calendartype' => 'calendar/type/{$name}/', - 'format' => 'course/format/{$name}/', - 'coursereport' => 'course/report/{$name}/', - 'datafield' => 'mod/data/field/{$name}/', - 'datapreset' => 'mod/data/preset/{$name}/', - 'editor' => 'lib/editor/{$name}/', - 'enrol' => 'enrol/{$name}/', - 'filter' => 'filter/{$name}/', - 'gradeexport' => 'grade/export/{$name}/', - 'gradeimport' => 'grade/import/{$name}/', - 'gradereport' => 'grade/report/{$name}/', - 'gradingform' => 'grade/grading/form/{$name}/', - 'local' => 'local/{$name}/', - 'logstore' => 'admin/tool/log/store/{$name}/', - 'ltisource' => 'mod/lti/source/{$name}/', - 'ltiservice' => 'mod/lti/service/{$name}/', - 'message' => 'message/output/{$name}/', - 'mnetservice' => 'mnet/service/{$name}/', - 'plagiarism' => 'plagiarism/{$name}/', - 'portfolio' => 'portfolio/{$name}/', - 'qbehaviour' => 'question/behaviour/{$name}/', - 'qformat' => 'question/format/{$name}/', - 'qtype' => 'question/type/{$name}/', - 'quizaccess' => 'mod/quiz/accessrule/{$name}/', - 'quiz' => 'mod/quiz/report/{$name}/', - 'report' => 'report/{$name}/', - 'repository' => 'repository/{$name}/', - 'scormreport' => 'mod/scorm/report/{$name}/', - 'search' => 'search/engine/{$name}/', - 'theme' => 'theme/{$name}/', - 'tinymce' => 'lib/editor/tinymce/plugins/{$name}/', - 'profilefield' => 'user/profile/field/{$name}/', - 'webservice' => 'webservice/{$name}/', - 'workshopallocation' => 'mod/workshop/allocation/{$name}/', - 'workshopeval' => 'mod/workshop/eval/{$name}/', - 'workshopform' => 'mod/workshop/form/{$name}/' - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/OctoberInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/OctoberInstaller.php deleted file mode 100644 index 08d5dc4e7..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/OctoberInstaller.php +++ /dev/null @@ -1,47 +0,0 @@ - 'modules/{$name}/', - 'plugin' => 'plugins/{$vendor}/{$name}/', - 'theme' => 'themes/{$name}/' - ); - - /** - * Format package name. - * - * For package type october-plugin, cut off a trailing '-plugin' if present. - * - * For package type october-theme, cut off a trailing '-theme' if present. - * - */ - public function inflectPackageVars($vars) - { - if ($vars['type'] === 'october-plugin') { - return $this->inflectPluginVars($vars); - } - - if ($vars['type'] === 'october-theme') { - return $this->inflectThemeVars($vars); - } - - return $vars; - } - - protected function inflectPluginVars($vars) - { - $vars['name'] = preg_replace('/^oc-|-plugin$/', '', $vars['name']); - $vars['vendor'] = preg_replace('/[^a-z0-9_]/i', '', $vars['vendor']); - - return $vars; - } - - protected function inflectThemeVars($vars) - { - $vars['name'] = preg_replace('/^oc-|-theme$/', '', $vars['name']); - - return $vars; - } -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/OntoWikiInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/OntoWikiInstaller.php deleted file mode 100644 index 5dd3438d9..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/OntoWikiInstaller.php +++ /dev/null @@ -1,24 +0,0 @@ - 'extensions/{$name}/', - 'theme' => 'extensions/themes/{$name}/', - 'translation' => 'extensions/translations/{$name}/', - ); - - /** - * Format package name to lower case and remove ".ontowiki" suffix - */ - public function inflectPackageVars($vars) - { - $vars['name'] = strtolower($vars['name']); - $vars['name'] = preg_replace('/.ontowiki$/', '', $vars['name']); - $vars['name'] = preg_replace('/-theme$/', '', $vars['name']); - $vars['name'] = preg_replace('/-translation$/', '', $vars['name']); - - return $vars; - } -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/OsclassInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/OsclassInstaller.php deleted file mode 100644 index 3ca7954c9..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/OsclassInstaller.php +++ /dev/null @@ -1,14 +0,0 @@ - 'oc-content/plugins/{$name}/', - 'theme' => 'oc-content/themes/{$name}/', - 'language' => 'oc-content/languages/{$name}/', - ); - -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/OxidInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/OxidInstaller.php deleted file mode 100644 index 49940ff6d..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/OxidInstaller.php +++ /dev/null @@ -1,59 +0,0 @@ -.+)\/.+/'; - - protected $locations = array( - 'module' => 'modules/{$name}/', - 'theme' => 'application/views/{$name}/', - 'out' => 'out/{$name}/', - ); - - /** - * getInstallPath - * - * @param PackageInterface $package - * @param string $frameworkType - * @return void - */ - public function getInstallPath(PackageInterface $package, $frameworkType = '') - { - $installPath = parent::getInstallPath($package, $frameworkType); - $type = $this->package->getType(); - if ($type === 'oxid-module') { - $this->prepareVendorDirectory($installPath); - } - return $installPath; - } - - /** - * prepareVendorDirectory - * - * Makes sure there is a vendormetadata.php file inside - * the vendor folder if there is a vendor folder. - * - * @param string $installPath - * @return void - */ - protected function prepareVendorDirectory($installPath) - { - $matches = ''; - $hasVendorDirectory = preg_match(self::VENDOR_PATTERN, $installPath, $matches); - if (!$hasVendorDirectory) { - return; - } - - $vendorDirectory = $matches['vendor']; - $vendorPath = getcwd() . '/modules/' . $vendorDirectory; - if (!file_exists($vendorPath)) { - mkdir($vendorPath, 0755, true); - } - - $vendorMetaDataPath = $vendorPath . '/vendormetadata.php'; - touch($vendorMetaDataPath); - } -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/PPIInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/PPIInstaller.php deleted file mode 100644 index 170136f98..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/PPIInstaller.php +++ /dev/null @@ -1,9 +0,0 @@ - 'modules/{$name}/', - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/PhiftyInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/PhiftyInstaller.php deleted file mode 100644 index 4e59a8a74..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/PhiftyInstaller.php +++ /dev/null @@ -1,11 +0,0 @@ - 'bundles/{$name}/', - 'library' => 'libraries/{$name}/', - 'framework' => 'frameworks/{$name}/', - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/PhpBBInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/PhpBBInstaller.php deleted file mode 100644 index deb2b77a6..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/PhpBBInstaller.php +++ /dev/null @@ -1,11 +0,0 @@ - 'ext/{$vendor}/{$name}/', - 'language' => 'language/{$name}/', - 'style' => 'styles/{$name}/', - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/PimcoreInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/PimcoreInstaller.php deleted file mode 100644 index 4781fa6d1..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/PimcoreInstaller.php +++ /dev/null @@ -1,21 +0,0 @@ - 'plugins/{$name}/', - ); - - /** - * Format package name to CamelCase - */ - public function inflectPackageVars($vars) - { - $vars['name'] = strtolower(preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $vars['name'])); - $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']); - $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); - - return $vars; - } -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/PiwikInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/PiwikInstaller.php deleted file mode 100644 index c17f4572b..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/PiwikInstaller.php +++ /dev/null @@ -1,32 +0,0 @@ - 'plugins/{$name}/', - ); - - /** - * Format package name to CamelCase - * @param array $vars - * - * @return array - */ - public function inflectPackageVars($vars) - { - $vars['name'] = strtolower(preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $vars['name'])); - $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']); - $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); - - return $vars; - } -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/PlentymarketsInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/PlentymarketsInstaller.php deleted file mode 100644 index 903e55f62..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/PlentymarketsInstaller.php +++ /dev/null @@ -1,29 +0,0 @@ - '{$name}/' - ); - - /** - * Remove hyphen, "plugin" and format to camelcase - * @param array $vars - * - * @return array - */ - public function inflectPackageVars($vars) - { - $vars['name'] = explode("-", $vars['name']); - foreach ($vars['name'] as $key => $name) { - $vars['name'][$key] = ucfirst($vars['name'][$key]); - if (strcasecmp($name, "Plugin") == 0) { - unset($vars['name'][$key]); - } - } - $vars['name'] = implode("",$vars['name']); - - return $vars; - } -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/Plugin.php b/twitter/vendor/composer/installers/src/Composer/Installers/Plugin.php deleted file mode 100644 index 5eb04af17..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/Plugin.php +++ /dev/null @@ -1,17 +0,0 @@ -getInstallationManager()->addInstaller($installer); - } -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/PortoInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/PortoInstaller.php deleted file mode 100644 index dbf85e635..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/PortoInstaller.php +++ /dev/null @@ -1,9 +0,0 @@ - 'app/Containers/{$name}/', - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/PrestashopInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/PrestashopInstaller.php deleted file mode 100644 index 4c8421e36..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/PrestashopInstaller.php +++ /dev/null @@ -1,10 +0,0 @@ - 'modules/{$name}/', - 'theme' => 'themes/{$name}/', - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/PuppetInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/PuppetInstaller.php deleted file mode 100644 index 77cc3dd87..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/PuppetInstaller.php +++ /dev/null @@ -1,11 +0,0 @@ - 'modules/{$name}/', - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/PxcmsInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/PxcmsInstaller.php deleted file mode 100644 index 65510580e..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/PxcmsInstaller.php +++ /dev/null @@ -1,63 +0,0 @@ - 'app/Modules/{$name}/', - 'theme' => 'themes/{$name}/', - ); - - /** - * Format package name. - * - * @param array $vars - * - * @return array - */ - public function inflectPackageVars($vars) - { - if ($vars['type'] === 'pxcms-module') { - return $this->inflectModuleVars($vars); - } - - if ($vars['type'] === 'pxcms-theme') { - return $this->inflectThemeVars($vars); - } - - return $vars; - } - - /** - * For package type pxcms-module, cut off a trailing '-plugin' if present. - * - * return string - */ - protected function inflectModuleVars($vars) - { - $vars['name'] = str_replace('pxcms-', '', $vars['name']); // strip out pxcms- just incase (legacy) - $vars['name'] = str_replace('module-', '', $vars['name']); // strip out module- - $vars['name'] = preg_replace('/-module$/', '', $vars['name']); // strip out -module - $vars['name'] = str_replace('-', '_', $vars['name']); // make -'s be _'s - $vars['name'] = ucwords($vars['name']); // make module name camelcased - - return $vars; - } - - - /** - * For package type pxcms-module, cut off a trailing '-plugin' if present. - * - * return string - */ - protected function inflectThemeVars($vars) - { - $vars['name'] = str_replace('pxcms-', '', $vars['name']); // strip out pxcms- just incase (legacy) - $vars['name'] = str_replace('theme-', '', $vars['name']); // strip out theme- - $vars['name'] = preg_replace('/-theme$/', '', $vars['name']); // strip out -theme - $vars['name'] = str_replace('-', '_', $vars['name']); // make -'s be _'s - $vars['name'] = ucwords($vars['name']); // make module name camelcased - - return $vars; - } -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/RadPHPInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/RadPHPInstaller.php deleted file mode 100644 index 0f78b5ca6..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/RadPHPInstaller.php +++ /dev/null @@ -1,24 +0,0 @@ - 'src/{$name}/' - ); - - /** - * Format package name to CamelCase - */ - public function inflectPackageVars($vars) - { - $nameParts = explode('/', $vars['name']); - foreach ($nameParts as &$value) { - $value = strtolower(preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $value)); - $value = str_replace(array('-', '_'), ' ', $value); - $value = str_replace(' ', '', ucwords($value)); - } - $vars['name'] = implode('/', $nameParts); - return $vars; - } -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/ReIndexInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/ReIndexInstaller.php deleted file mode 100644 index 252c7339f..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/ReIndexInstaller.php +++ /dev/null @@ -1,10 +0,0 @@ - 'themes/{$name}/', - 'plugin' => 'plugins/{$name}/' - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/RedaxoInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/RedaxoInstaller.php deleted file mode 100644 index 09544576b..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/RedaxoInstaller.php +++ /dev/null @@ -1,10 +0,0 @@ - 'redaxo/include/addons/{$name}/', - 'bestyle-plugin' => 'redaxo/include/addons/be_style/plugins/{$name}/' - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/RoundcubeInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/RoundcubeInstaller.php deleted file mode 100644 index d8d795be0..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/RoundcubeInstaller.php +++ /dev/null @@ -1,22 +0,0 @@ - 'plugins/{$name}/', - ); - - /** - * Lowercase name and changes the name to a underscores - * - * @param array $vars - * @return array - */ - public function inflectPackageVars($vars) - { - $vars['name'] = strtolower(str_replace('-', '_', $vars['name'])); - - return $vars; - } -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/SMFInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/SMFInstaller.php deleted file mode 100644 index 1acd3b14c..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/SMFInstaller.php +++ /dev/null @@ -1,10 +0,0 @@ - 'Sources/{$name}/', - 'theme' => 'Themes/{$name}/', - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/ShopwareInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/ShopwareInstaller.php deleted file mode 100644 index 7d20d27a2..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/ShopwareInstaller.php +++ /dev/null @@ -1,60 +0,0 @@ - 'engine/Shopware/Plugins/Local/Backend/{$name}/', - 'core-plugin' => 'engine/Shopware/Plugins/Local/Core/{$name}/', - 'frontend-plugin' => 'engine/Shopware/Plugins/Local/Frontend/{$name}/', - 'theme' => 'templates/{$name}/', - 'plugin' => 'custom/plugins/{$name}/', - 'frontend-theme' => 'themes/Frontend/{$name}/', - ); - - /** - * Transforms the names - * @param array $vars - * @return array - */ - public function inflectPackageVars($vars) - { - if ($vars['type'] === 'shopware-theme') { - return $this->correctThemeName($vars); - } - - return $this->correctPluginName($vars); - } - - /** - * Changes the name to a camelcased combination of vendor and name - * @param array $vars - * @return array - */ - private function correctPluginName($vars) - { - $camelCasedName = preg_replace_callback('/(-[a-z])/', function ($matches) { - return strtoupper($matches[0][1]); - }, $vars['name']); - - $vars['name'] = ucfirst($vars['vendor']) . ucfirst($camelCasedName); - - return $vars; - } - - /** - * Changes the name to a underscore separated name - * @param array $vars - * @return array - */ - private function correctThemeName($vars) - { - $vars['name'] = str_replace('-', '_', $vars['name']); - - return $vars; - } -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/SilverStripeInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/SilverStripeInstaller.php deleted file mode 100644 index 81910e9f1..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/SilverStripeInstaller.php +++ /dev/null @@ -1,35 +0,0 @@ - '{$name}/', - 'theme' => 'themes/{$name}/', - ); - - /** - * Return the install path based on package type. - * - * Relies on built-in BaseInstaller behaviour with one exception: silverstripe/framework - * must be installed to 'sapphire' and not 'framework' if the version is <3.0.0 - * - * @param PackageInterface $package - * @param string $frameworkType - * @return string - */ - public function getInstallPath(PackageInterface $package, $frameworkType = '') - { - if ( - $package->getName() == 'silverstripe/framework' - && preg_match('/^\d+\.\d+\.\d+/', $package->getVersion()) - && version_compare($package->getVersion(), '2.999.999') < 0 - ) { - return $this->templatePath($this->locations['module'], array('name' => 'sapphire')); - } - - return parent::getInstallPath($package, $frameworkType); - } -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/SiteDirectInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/SiteDirectInstaller.php deleted file mode 100644 index 762d94c68..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/SiteDirectInstaller.php +++ /dev/null @@ -1,25 +0,0 @@ - 'modules/{$vendor}/{$name}/', - 'plugin' => 'plugins/{$vendor}/{$name}/' - ); - - public function inflectPackageVars($vars) - { - return $this->parseVars($vars); - } - - protected function parseVars($vars) - { - $vars['vendor'] = strtolower($vars['vendor']) == 'sitedirect' ? 'SiteDirect' : $vars['vendor']; - $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']); - $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); - - return $vars; - } -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/SyDESInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/SyDESInstaller.php deleted file mode 100644 index 83ef9d091..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/SyDESInstaller.php +++ /dev/null @@ -1,49 +0,0 @@ - 'app/modules/{$name}/', - 'theme' => 'themes/{$name}/', - ); - - /** - * Format module name. - * - * Strip `sydes-` prefix and a trailing '-theme' or '-module' from package name if present. - * - * @param array @vars - * - * @return array - */ - public function inflectPackageVars($vars) - { - if ($vars['type'] == 'sydes-module') { - return $this->inflectModuleVars($vars); - } - - if ($vars['type'] === 'sydes-theme') { - return $this->inflectThemeVars($vars); - } - - return $vars; - } - - public function inflectModuleVars($vars) - { - $vars['name'] = preg_replace('/(^sydes-|-module$)/i', '', $vars['name']); - $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']); - $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); - - return $vars; - } - - protected function inflectThemeVars($vars) - { - $vars['name'] = preg_replace('/(^sydes-|-theme$)/', '', $vars['name']); - $vars['name'] = strtolower($vars['name']); - - return $vars; - } -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/Symfony1Installer.php b/twitter/vendor/composer/installers/src/Composer/Installers/Symfony1Installer.php deleted file mode 100644 index 1675c4f21..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/Symfony1Installer.php +++ /dev/null @@ -1,26 +0,0 @@ - - */ -class Symfony1Installer extends BaseInstaller -{ - protected $locations = array( - 'plugin' => 'plugins/{$name}/', - ); - - /** - * Format package name to CamelCase - */ - public function inflectPackageVars($vars) - { - $vars['name'] = preg_replace_callback('/(-[a-z])/', function ($matches) { - return strtoupper($matches[0][1]); - }, $vars['name']); - - return $vars; - } -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/TYPO3CmsInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/TYPO3CmsInstaller.php deleted file mode 100644 index b1663e843..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/TYPO3CmsInstaller.php +++ /dev/null @@ -1,16 +0,0 @@ - - */ -class TYPO3CmsInstaller extends BaseInstaller -{ - protected $locations = array( - 'extension' => 'typo3conf/ext/{$name}/', - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/TYPO3FlowInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/TYPO3FlowInstaller.php deleted file mode 100644 index 42572f44f..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/TYPO3FlowInstaller.php +++ /dev/null @@ -1,38 +0,0 @@ - 'Packages/Application/{$name}/', - 'framework' => 'Packages/Framework/{$name}/', - 'plugin' => 'Packages/Plugins/{$name}/', - 'site' => 'Packages/Sites/{$name}/', - 'boilerplate' => 'Packages/Boilerplates/{$name}/', - 'build' => 'Build/{$name}/', - ); - - /** - * Modify the package name to be a TYPO3 Flow style key. - * - * @param array $vars - * @return array - */ - public function inflectPackageVars($vars) - { - $autoload = $this->package->getAutoload(); - if (isset($autoload['psr-0']) && is_array($autoload['psr-0'])) { - $namespace = key($autoload['psr-0']); - $vars['name'] = str_replace('\\', '.', $namespace); - } - if (isset($autoload['psr-4']) && is_array($autoload['psr-4'])) { - $namespace = key($autoload['psr-4']); - $vars['name'] = rtrim(str_replace('\\', '.', $namespace), '.'); - } - - return $vars; - } -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/TheliaInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/TheliaInstaller.php deleted file mode 100644 index 158af5261..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/TheliaInstaller.php +++ /dev/null @@ -1,12 +0,0 @@ - 'local/modules/{$name}/', - 'frontoffice-template' => 'templates/frontOffice/{$name}/', - 'backoffice-template' => 'templates/backOffice/{$name}/', - 'email-template' => 'templates/email/{$name}/', - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/TuskInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/TuskInstaller.php deleted file mode 100644 index 7c0113b85..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/TuskInstaller.php +++ /dev/null @@ -1,14 +0,0 @@ - - */ - class TuskInstaller extends BaseInstaller - { - protected $locations = array( - 'task' => '.tusk/tasks/{$name}/', - 'command' => '.tusk/commands/{$name}/', - 'asset' => 'assets/tusk/{$name}/', - ); - } diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/UserFrostingInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/UserFrostingInstaller.php deleted file mode 100644 index fcb414ab7..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/UserFrostingInstaller.php +++ /dev/null @@ -1,9 +0,0 @@ - 'app/sprinkles/{$name}/', - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/VanillaInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/VanillaInstaller.php deleted file mode 100644 index 24ca64512..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/VanillaInstaller.php +++ /dev/null @@ -1,10 +0,0 @@ - 'plugins/{$name}/', - 'theme' => 'themes/{$name}/', - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/VgmcpInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/VgmcpInstaller.php deleted file mode 100644 index 7d90c5e6e..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/VgmcpInstaller.php +++ /dev/null @@ -1,49 +0,0 @@ - 'src/{$vendor}/{$name}/', - 'theme' => 'themes/{$name}/' - ); - - /** - * Format package name. - * - * For package type vgmcp-bundle, cut off a trailing '-bundle' if present. - * - * For package type vgmcp-theme, cut off a trailing '-theme' if present. - * - */ - public function inflectPackageVars($vars) - { - if ($vars['type'] === 'vgmcp-bundle') { - return $this->inflectPluginVars($vars); - } - - if ($vars['type'] === 'vgmcp-theme') { - return $this->inflectThemeVars($vars); - } - - return $vars; - } - - protected function inflectPluginVars($vars) - { - $vars['name'] = preg_replace('/-bundle$/', '', $vars['name']); - $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']); - $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); - - return $vars; - } - - protected function inflectThemeVars($vars) - { - $vars['name'] = preg_replace('/-theme$/', '', $vars['name']); - $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']); - $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); - - return $vars; - } -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/WHMCSInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/WHMCSInstaller.php deleted file mode 100644 index 2cbb4a463..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/WHMCSInstaller.php +++ /dev/null @@ -1,10 +0,0 @@ - 'modules/gateways/{$name}/', - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/WolfCMSInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/WolfCMSInstaller.php deleted file mode 100644 index cb387881d..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/WolfCMSInstaller.php +++ /dev/null @@ -1,9 +0,0 @@ - 'wolf/plugins/{$name}/', - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/WordPressInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/WordPressInstaller.php deleted file mode 100644 index 91c46ad99..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/WordPressInstaller.php +++ /dev/null @@ -1,12 +0,0 @@ - 'wp-content/plugins/{$name}/', - 'theme' => 'wp-content/themes/{$name}/', - 'muplugin' => 'wp-content/mu-plugins/{$name}/', - 'dropin' => 'wp-content/{$name}/', - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/YawikInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/YawikInstaller.php deleted file mode 100644 index 27f429ff2..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/YawikInstaller.php +++ /dev/null @@ -1,32 +0,0 @@ - 'module/{$name}/', - ); - - /** - * Format package name to CamelCase - * @param array $vars - * - * @return array - */ - public function inflectPackageVars($vars) - { - $vars['name'] = strtolower(preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $vars['name'])); - $vars['name'] = str_replace(array('-', '_'), ' ', $vars['name']); - $vars['name'] = str_replace(' ', '', ucwords($vars['name'])); - - return $vars; - } -} \ No newline at end of file diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/ZendInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/ZendInstaller.php deleted file mode 100644 index bde9bc8c8..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/ZendInstaller.php +++ /dev/null @@ -1,11 +0,0 @@ - 'library/{$name}/', - 'extra' => 'extras/library/{$name}/', - 'module' => 'module/{$name}/', - ); -} diff --git a/twitter/vendor/composer/installers/src/Composer/Installers/ZikulaInstaller.php b/twitter/vendor/composer/installers/src/Composer/Installers/ZikulaInstaller.php deleted file mode 100644 index 56cdf5da7..000000000 --- a/twitter/vendor/composer/installers/src/Composer/Installers/ZikulaInstaller.php +++ /dev/null @@ -1,10 +0,0 @@ - 'modules/{$vendor}-{$name}/', - 'theme' => 'themes/{$vendor}-{$name}/' - ); -} diff --git a/twitter/vendor/composer/installers/src/bootstrap.php b/twitter/vendor/composer/installers/src/bootstrap.php deleted file mode 100644 index 0de276ee2..000000000 --- a/twitter/vendor/composer/installers/src/bootstrap.php +++ /dev/null @@ -1,13 +0,0 @@ - - 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. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state 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 program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/twitter/vendor/jublonet/codebird-php/README.md b/twitter/vendor/jublonet/codebird-php/README.md deleted file mode 100644 index 6b0a5c730..000000000 --- a/twitter/vendor/jublonet/codebird-php/README.md +++ /dev/null @@ -1,891 +0,0 @@ -codebird-php -============ -*Easy access to the Twitter REST API, Direct Messages API, Account Activity API, TON (Object Nest) API and Twitter Ads API — all from one PHP library.* - -Copyright (C) 2010-2018 Jublo Limited - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program 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 General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . - -[![Codacy Badge](https://api.codacy.com/project/badge/Grade/3cd81a521d334648b9958327621a3070)](https://www.codacy.com/app/jublonet/codebird-php?utm_source=github.com&utm_medium=referral&utm_content=jublonet/codebird-php&utm_campaign=badger) -[![Coverage Status](https://img.shields.io/coveralls/jublonet/codebird-php/develop.svg)](https://coveralls.io/github/jublonet/codebird-php?branch=develop) -[![Travis Status](https://img.shields.io/travis/jublonet/codebird-php/develop.svg)](https://travis-ci.org/jublonet/codebird-php/branches) - -### Requirements - -- PHP 7.1.0 or higher -- OpenSSL extension - - -Summary -------- - -Use Codebird to connect to the Twitter **REST API, Streaming API, Collections API, TON (Object Nest) API** -and **Twitter Ads API** from your PHP code — all using just one library. -Codebird supports full 3-way OAuth as well as application-only auth. - - -Authentication --------------- - -To authenticate your API requests on behalf of a certain Twitter user -(following OAuth 1.0a), take a look at these steps: - -```php -require_once ('codebird.php'); -\Codebird\Codebird::setConsumerKey('YOURKEY', 'YOURSECRET'); // static, see README - -$cb = \Codebird\Codebird::getInstance(); -``` - -You may either set the OAuth token and secret, if you already have them: -```php -$cb->setToken('YOURTOKEN', 'YOURTOKENSECRET'); -``` - -Or you authenticate, like this: - -```php -session_start(); - -if (! isset($_SESSION['oauth_token'])) { - // get the request token - $reply = $cb->oauth_requestToken([ - 'oauth_callback' => 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] - ]); - - // store the token - $cb->setToken($reply->oauth_token, $reply->oauth_token_secret); - $_SESSION['oauth_token'] = $reply->oauth_token; - $_SESSION['oauth_token_secret'] = $reply->oauth_token_secret; - $_SESSION['oauth_verify'] = true; - - // redirect to auth website - $auth_url = $cb->oauth_authorize(); - header('Location: ' . $auth_url); - die(); - -} elseif (isset($_GET['oauth_verifier']) && isset($_SESSION['oauth_verify'])) { - // verify the token - $cb->setToken($_SESSION['oauth_token'], $_SESSION['oauth_token_secret']); - unset($_SESSION['oauth_verify']); - - // get the access token - $reply = $cb->oauth_accessToken([ - 'oauth_verifier' => $_GET['oauth_verifier'] - ]); - - // store the token (which is different from the request token!) - $_SESSION['oauth_token'] = $reply->oauth_token; - $_SESSION['oauth_token_secret'] = $reply->oauth_token_secret; - - // send to same URL, without oauth GET parameters - header('Location: ' . basename(__FILE__)); - die(); -} - -// assign access token on each page load -$cb->setToken($_SESSION['oauth_token'], $_SESSION['oauth_token_secret']); -``` - -### Logging out - -In case you want to log out the current user (to log in a different user without -creating a new Codebird object), just call the `logout()` method. - -``` -$cb->logout(); -``` - -### Application-only auth - -Some API methods also support authenticating on a per-application level. -This is useful for getting data that are not directly related to a specific -Twitter user, but generic to the Twitter ecosystem (such as ```search/tweets```). - -To obtain an app-only bearer token, call the appropriate API: - -```php -$reply = $cb->oauth2_token(); -$bearer_token = $reply->access_token; -``` - -I strongly recommend that you store the obtained bearer token in your database. -There is no need to re-obtain the token with each page load, as it becomes invalid -only when you call the ```oauth2/invalidate_token``` method. - -If you already have your token, tell Codebird to use it: -```php -\Codebird\Codebird::setBearerToken('YOURBEARERTOKEN'); -``` -In this case, you don't need to set the consumer key and secret. -For sending an API request with app-only auth, see the ‘Usage examples’ section. - - -### A word on your callback URL - -Twitter is very restrictive about which URLs may be used for your callback URL. -For example, even the presence of the ‘www’ subdomain must match with the domain -that you specified in the settings of your app at https://developer.twitter.com/en/apps. - - -Mapping API methods to Codebird function calls ----------------------------------------------- - -As you can see from the last example, there is a general way how Twitter’s API methods -map to Codebird function calls. The general rules are: - -1. For each slash in a Twitter API method, use an underscore in the Codebird function. - - Example: ```statuses/update``` maps to ```Codebird::statuses_update()```. - -2. For each underscore in a Twitter API method, use camelCase in the Codebird function. - - Example: ```statuses/home_timeline``` maps to ```Codebird::statuses_homeTimeline()```. - -3. For each parameter template in method, use UPPERCASE in the Codebird function. - Also don’t forget to include the parameter in your parameter list. - - Examples: - - ```statuses/show/:id``` maps to ```Codebird::statuses_show_ID('id=12345')```. - - ```users/profile_image/:screen_name``` maps to - `Codebird::users_profileImage_SCREEN_NAME('screen_name=jublonet')`. - -Usage examples --------------- - -When you have an access token, calling the API is simple: - -```php -$cb->setToken($_SESSION['oauth_token'], $_SESSION['oauth_token_secret']); // see above - -$reply = (array) $cb->statuses_homeTimeline(); -print_r($reply); -``` - -Tweeting is as easy as this: - -```php -$reply = $cb->statuses_update('status=Whohoo, I just Tweeted!'); -``` - -:warning: *Make sure to urlencode any parameter values that contain -query-reserved characters, like Tweeting the `&` sign:* - -```php -$reply = $cb->statuses_update('status=' . urlencode('Fish & chips')); -// will result in this: -$reply = $cb->statuses_update('status=Fish+%26+chips'); -``` - -In most cases, giving all parameters in an array is easier, -because no encoding is needed: - -```php -$params = [ - 'status' => 'Fish & chips' -]; -$reply = $cb->statuses_update($params); -``` - -```php -$params = [ - 'status' => 'I love London', - 'lat' => 51.5033, - 'long' => 0.1197 -]; -$reply = $cb->statuses_update($params); -``` - -```php -$params = [ - 'screen_name' => 'jublonet' -]; -$reply = $cb->users_show($params); -``` -This is the [resulting Tweet](https://twitter.com/LarryMcTweet/status/482239971399835648) -sent with the code above. - -### Requests with app-only auth - -To send API requests without an access token for a user (app-only auth), -add a second parameter to your method call, like this: - -```php -$reply = $cb->search_tweets('q=Twitter', true); -``` - -Bear in mind that not all API methods support application-only auth. - - -HTTP methods (GET, POST, DELETE etc.) -------------------------------------- - -Never care about which HTTP method (verb) to use when calling a Twitter API. -Codebird is intelligent enough to find out on its own. - -Response codes --------------- - -The HTTP response code that the API gave is included in any return values. -You can find it within the return object’s ```httpstatus``` property. - -### Dealing with rate-limits - -Basically, Codebird leaves it up to you to handle Twitter’s rate limit. -The library returns the response HTTP status code, so you can detect rate limits. - -I suggest you to check if the ```$reply->httpstatus``` property is ```400``` -and check with the Twitter API to find out if you are currently being -rate-limited. -See the [Rate Limiting FAQ](https://developer.twitter.com/en/docs/basics/rate-limiting) -for more information. - -Unless your return format is JSON, you will receive rate-limiting details -in the returned data’s ```$reply->rate``` property, -if the Twitter API responds with rate-limiting HTTP headers. - -Return formats --------------- -The default return format for API calls is a PHP object. -For API methods returning multiple data (like ```statuses/home_timeline```), -you should cast the reply to array, like this: - -```php -$reply = $cb->statuses_homeTimeline(); -$data = (array) $reply; -``` - -Upon your choice, you may also get PHP arrays directly: - -```php -$cb->setReturnFormat(CODEBIRD_RETURNFORMAT_ARRAY); -``` - -The Twitter API natively responds to API calls in JSON (JS Object Notation). -To get a JSON string, set the corresponding return format: - -```php -$cb->setReturnFormat(CODEBIRD_RETURNFORMAT_JSON); -``` - -Uploading images and videos ---------------------------- - -Twitter will accept the following media types, all of which are supported by Codebird: -- PNG -- JPEG -- BMP -- WebP -- GIF -- Animated GIF -- Video - -Tweet media can be uploaded in a 2-step process: - -**First** you send each media to Twitter. For **images**, it works like this: - -```php -// these files to upload. You can also just upload 1 image! -$media_files = [ - 'bird1.jpg', 'bird2.jpg', 'bird3.jpg' -]; -// will hold the uploaded IDs -$media_ids = []; - -foreach ($media_files as $file) { - // upload all media files - $reply = $cb->media_upload([ - 'media' => $file - ]); - // and collect their IDs - $media_ids[] = $reply->media_id_string; -} -``` - -Uploading **videos** requires you to send the data in chunks. See the next section on this. - -**Second,** you attach the collected media ids for all images to your call -to ```statuses/update```, like this: - -```php -// convert media ids to string list -$media_ids = implode(',', $media_ids); - -// send Tweet with these medias -$reply = $cb->statuses_update([ - 'status' => 'These are some of my relatives.', - 'media_ids' => $media_ids -]); -print_r($reply); -``` - -Here is a [sample Tweet](https://twitter.com/LarryMcTweet/status/475276535386365952) -sent with the code above. - -More [documentation for uploading media](https://developer.twitter.com/en/docs/media/upload-media/overview) is available on the Twitter Developer site. - -### Remote files - -Remote files received from `http` and `https` servers are supported, too: -```php -$reply = $cb->media_upload(array( - 'media' => 'http://www.bing.com/az/hprichbg/rb/BilbaoGuggenheim_EN-US11232447099_1366x768.jpg' -)); -``` - -:warning: *URLs containing Unicode characters should be normalised. A sample normalisation function can be found at http://stackoverflow.com/a/6059053/1816603* - -To circumvent download issues when remote servers are slow to respond, -you may customise the remote download timeout, like this: - -```php -$cb->setRemoteDownloadTimeout(10000); // milliseconds -``` - -### Video files - -Uploading videos to Twitter (≤ 15MB, MP4) requires you to send them in chunks. -You need to perform at least 3 calls to obtain your `media_id` for the video: - -1. Send an `INIT` event to get a `media_id` draft. -2. Upload your chunks with `APPEND` events, each one up to 5MB in size. -3. Send a `FINALIZE` event to convert the draft to a ready-to-Tweet `media_id`. -4. Post your Tweet with video attached. - -Here’s a sample for video uploads: - -```php -$file = 'demo-video.mp4'; -$size_bytes = filesize($file); -$fp = fopen($file, 'r'); - -// INIT the upload - -$reply = $cb->media_upload([ - 'command' => 'INIT', - 'media_type' => 'video/mp4', - 'total_bytes' => $size_bytes -]); - -$media_id = $reply->media_id_string; - -// APPEND data to the upload - -$segment_id = 0; - -while (! feof($fp)) { - $chunk = fread($fp, 1048576); // 1MB per chunk for this sample - - $reply = $cb->media_upload([ - 'command' => 'APPEND', - 'media_id' => $media_id, - 'segment_index' => $segment_id, - 'media' => $chunk - ]); - - $segment_id++; -} - -fclose($fp); - -// FINALIZE the upload - -$reply = $cb->media_upload([ - 'command' => 'FINALIZE', - 'media_id' => $media_id -]); - -var_dump($reply); - -if ($reply->httpstatus < 200 || $reply->httpstatus > 299) { - die(); -} - -// if you have a field `processing_info` in the reply, -// use the STATUS command to check if the video has finished processing. - -// Now use the media_id in a Tweet -$reply = $cb->statuses_update([ - 'status' => 'Twitter now accepts video uploads.', - 'media_ids' => $media_id -]); - -``` - -**Find more information about [accepted media formats](https://developer.twitter.com/en/docs/media/upload-media/uploading-media/media-best-practices) in the Twitter Developer docs.** - -:warning: When uploading a video in multiple chunks, you may run into an error `The validation of media ids failed.` even though the `media_id` is correct. This is known. Please check back in the [Twitter community forums](https://twittercommunity.com/tags/video). - - -Twitter Streaming API ---------------------- - -The Streaming APIs give developers low latency access to Twitter’s global stream of -Tweet data. A proper implementation of a streaming client will be pushed messages -indicating Tweets and other events have occurred, without any of the overhead -associated with polling a REST endpoint. - -To consume one of the available Twitter streams, follow these **two steps:** - -1. Set up a callback function that gets called for every new streaming message that arrives. - - Codebird also calls this function once per second, to allow you to work on any due tasks, and to give you the chance to cancel the stream even if no new messages appear. - -2. After creating the callback, tell Codebird about it using a [callable](http://php.net/manual/en/language.types.callable.php). Then start consuming the stream. - -```php -// First, create a callback function: - -function some_callback($message) -{ - // gets called for every new streamed message - // gets called with $message = NULL once per second - - if ($message !== null) { - print_r($message); - flush(); - } - - // return false to continue streaming - // return true to close the stream - - // close streaming after 1 minute for this simple sample - // don't rely on globals in your code! - if (time() - $GLOBALS['time_start'] >= 60) { - return true; - } - - return false; -} - -// set the streaming callback in Codebird -$cb->setStreamingCallback('some_callback'); - -// any callable is accepted: -// $cb->setStreamingCallback(['MyClass', 'some_callback']); - -// for canceling, see callback function body -// not considered good practice in real world! -$GLOBALS['time_start'] = time(); - -// Second, start consuming the stream: -$reply = $cb->statuses_filter(); - -// See the *Mapping API methods to Codebird function calls* section for method names. -// $reply = $cb->statuses_filter('track=Windows'); -``` - -You should be able to set a timeout for the streaming API using `setTimeout`. -In addition, your callback will receive empty messages if no events occur, -and you should make your function `return true;` in order to cancel the stream. - -Find more information on the [Streaming API](https://developer.twitter.com/en/docs/tweets/filter-realtime/overview) -in the developer documentation website. - - -Twitter Collections, Direct Messages and Account Activity APIs --------------------------------------------------------------- - -Collections are a type of timeline that you control and can be hand curated -and/or programmed using an API. - -Pay close attention to the differences in how collections are presented — -often they will be decomposed, efficient objects with information about users, -Tweets, and timelines grouped, simplified, and stripped of unnecessary repetition. - -Never care about the OAuth signing specialities and the JSON POST body -for POST and PUT calls to these special APIs. Codebird takes off the work for you -and will always send the correct Content-Type automatically. - -Find out more about the [Collections API](https://developer.twitter.com/en/docs/tweets/curate-a-collection/overview/about_collections) in the Twitter API docs. -More information on the [Direct Messages API](https://developer.twitter.com/en/docs/direct-messages/api-features) and the [Account Activity API](https://developer.twitter.com/en/docs/accounts-and-users/subscribe-account-activity/overview) is available there as well. - -Here’s a sample for adding a Tweet using the Collections API: - -```php -$reply = $cb->collections_entries_curate([ - 'id' => 'custom-672852634622144512', - 'changes' => [ - ['op' => 'add', 'tweet_id' => '672727928262828032'] - ] -]); - -var_dump($reply); -``` - -TON (Twitter Object Nest) API ------------------------------ - -The [TON (Twitter Object Nest) API](https://developer.twitter.com/en/docs/ads/audiences/overview/ton-upload.html) allows implementers to upload media and various assets to Twitter. -The TON API supports non-resumable and resumable upload methods based on the size of the file. -For files less than 64MB, non-resumable may be used. For files greater than or equal to 64MB, -resumable must be used. Resumable uploads require chunk sizes of less than 64MB. - -For accessing the TON API, please adapt the following code samples for uploading: - -### Single-chunk upload - -```php -// single-chunk upload - -$reply = $cb->ton_bucket_BUCKET([ - 'bucket' => 'ta_partner', - 'Content-Type' => 'image/jpeg', - 'media' => $file -]); - -var_dump($reply); - -// use the Location header now... -echo $reply->Location; -``` - -As you see from that sample, Codebird rewrites the special TON API headers into the reply, -so you can easily access them. This also applies to the `X-TON-Min-Chunk-Size` and -`X-Ton-Max-Chunk-Size` for chunked uploads: - -### Multi-chunk upload - -```php -// multi-chunk upload -$file = 'demo-video.mp4'; -$size_bytes = filesize($file); -$fp = fopen($file, 'r'); - -// INIT the upload - -$reply = $cb->__call( - 'ton/bucket/BUCKET?resumable=true', - [[ // note the double square braces when using __call - 'bucket' => 'ta_partner', - 'Content-Type' => 'video/mp4', - 'X-Ton-Content-Type' => 'video/mp4', - 'X-Ton-Content-Length' => $size_bytes - ]] -); - -$target = $reply->Location; -// something like: '/1.1/ton/bucket/ta_partner/SzFxGfAg_Zj.mp4?resumable=true&resumeId=28401873' -$match = []; - -// match the location parts -preg_match('/ton\/bucket\/.+\/(.+)\?resumable=true&resumeId=(\d+)/', $target, $match); -list ($target, $file, $resumeId) = $match; - -// APPEND data to the upload - -$segment_id = 0; - -while (! feof($fp)) { - $chunk = fread($fp, 1048576); // 1MB per chunk for this sample - - // special way to call Codebird for the upload chunks - $reply = $cb->__call( - 'ton/bucket/BUCKET/FILE?resumable=true&resumeId=RESUMEID', - [[ // note the double square braces when using __call - 'bucket' => 'ta_partner', - 'file' => $file, // you get real filename from INIT, see above - 'Content-Type' => 'image/jpeg', - 'Content-Range' => 'bytes ' - . ($segment_id * 1048576) . '-' . strlen($chunk) . '/' . $size_bytes, - 'resumeId' => $resumeId, - 'media' => $chunk - ]] - ); - - $segment_id++; -} - -fclose($fp); -``` - -Twitter Ads API ---------------- - -The [Twitter Ads API](https://developer.twitter.com/en/docs/ads/general/overview) allows partners to -integrate with the Twitter advertising platform in their own advertising solutions. -Selected partners have the ability to create custom tools to manage and execute -Twitter Ad campaigns. - -When accessing the Ads API or Ads Sandbox API, access it by prefixing your call -with `ads_`. Watch out for the usual replacements for in-url parameters, -particularly `:account_id`. - -**Tip:** For accessing the Ads Sandbox API, use the `ads_sandbox_` prefix, -like shown further down. - -Here is an example for calling the Twitter Ads API: - -```php -$reply = $cb->ads_accounts_ACCOUNT_ID_cards_appDownload([ - 'account_id' => '123456789', - 'name' => 'Test', - 'app_country_code' => 'DE' -]); -``` - -### Multiple-method API calls - -In the Twitter Ads API, there are multiple methods that can be reached by -HTTP `GET`, `POST`, `PUT` and/or `DELETE`. While Codebird does its best to guess -which HTTP verb you’ll want to use, it’s the safest bet to give a hint yourself, -like this: - -```php -$reply = $cb->ads_sandbox_accounts_ACCOUNT_ID_cards_imageConversation_CARD_ID([ - 'httpmethod' => 'DELETE', - 'account_id' => '123456789', - 'card_id' => '2468013579' -]); -``` - -Codebird will remove the `httpmethod` parameter from the parameters list automatically, -and set the corresponding HTTP verb. - - -How Do I…? ----------- - -### …use multiple Codebird instances? - -By default, Codebird works with just one instance. This programming paradigma is -called a *singleton*. - -Getting the main Codebird object is done like this: - -```php -$cb = \Codebird\Codebird::getInstance(); -``` - -If you need to run requests to the Twitter API for multiple users at once, -Codebird supports this as well. Instead of getting the instance like shown above, -create a new object: - -```php -$cb1 = new \Codebird\Codebird; -$cb2 = new \Codebird\Codebird; -``` - -Please note that your OAuth consumer key and secret is shared within -multiple Codebird instances, while the OAuth request and access tokens with their -secrets are *not* shared. - - -### …access a user’s profile image? - -First retrieve the user object using - -```$reply = $cb->users_show("screen_name=$username");``` - - -with ```$username``` being the username of the account you wish to retrieve the profile image from. - -Then get the value from the index ```profile_image_url``` or ```profile_image_url_https``` of the user object previously retrieved. - - -For example: - -```$reply['profile_image_url']``` will then return the profile image url without https. - -### …get user ID, screen name and more details about the current user? - -When the user returns from the authentication screen, you need to trade -the obtained request token for an access token, using the OAuth verifier. -As discussed in the section ‘Usage example,’ you use a call to -```oauth/access_token``` to do that. - -The API reply to this method call tells you details about the user that just logged in. -These details contain the **user ID** and the **screen name.** - -Take a look at the returned data as follows: - -``` -stdClass Object -( - [oauth_token] => 14648265-rPn8EJwfB********************** - [oauth_token_secret] => agvf3L3************************** - [user_id] => 14648265 - [screen_name] => jublonet - [httpstatus] => 200 -) -``` - -If you need to get more details, such as the user’s latest Tweet, -you should fetch the complete User Entity. The simplest way to get the -user entity of the currently authenticated user is to use the -```account/verify_credentials``` API method. In Codebird, it works like this: - -```php -$reply = $cb->account_verifyCredentials(); -print_r($reply); -``` - -I suggest to cache the User Entity after obtaining it, as the -```account/verify_credentials``` method is rate-limited by 15 calls per 15 minutes. - -### …walk through cursored results? - -The Twitter REST API utilizes a technique called ‘cursoring’ to paginate -large result sets. Cursoring separates results into pages of no more than -5000 results at a time, and provides a means to move backwards and -forwards through these pages. - -Here is how you can walk through cursored results with Codebird. - -1. Get the first result set of a cursored method: -```php -$result1 = $cb->followers_list(); -``` - -2. To navigate forth, take the ```next_cursor_str```: -```php -$nextCursor = $result1->next_cursor_str; -``` - -3. If ```$nextCursor``` is not 0, use this cursor to request the next result page: -```php - if ($nextCursor > 0) { - $result2 = $cb->followers_list('cursor=' . $nextCursor); - } -``` - -To navigate back instead of forth, use the field ```$resultX->previous_cursor_str``` -instead of ```next_cursor_str```. - -It might make sense to use the cursors in a loop. Watch out, though, -not to send more than the allowed number of requests to ```followers/list``` -per rate-limit timeframe, or else you will hit your rate-limit. - -### …use xAuth with Codebird? - -Codebird supports xAuth just like every other authentication used at Twitter. -Remember that your application needs to be whitelisted to be able to use xAuth. - -Here’s an example: -```php -$reply = $cb->oauth_accessToken([ - 'x_auth_username' => 'username', - 'x_auth_password' => '4h3_p4$$w0rd', - 'x_auth_mode' => 'client_auth' -]); -``` - -Are you getting a strange error message? If the user is enrolled in -login verification, the server will return a HTTP 401 error with a custom body. -If you are using the ```send_error_codes``` parameter, you will receive the -following error message in the response body: - -```xml - - -User must verify login - -``` - -Otherwise, the response body will contain a plaintext response: -``` -User must verify login -``` - -When this error occurs, advise the user to -[generate a temporary password](https://twitter.com/settings/applications) -on twitter.com and use that to complete signing in to the application. - -### …know what cacert.pem is for? - -Connections to the Twitter API are done over a secured SSL connection. -Codebird-php checks if the Twitter API server has a valid SSL certificate. -Valid certificates have a correct signature-chain. -The cacert.pem file contains a list of all public certificates for root -certificate authorities. You can find more information about this file -at http://curl.haxx.se/docs/caextract.html. - -### …set the timeout for requests to the Twitter API? - -For connecting to Twitter, Codebird uses the cURL library, if available. -You can specify both the connection timeout and the request timeout, -in milliseconds: - -```php -$cb->setConnectionTimeout(2000); -$cb->setTimeout(5000); -``` - -If you don't specify the timeout, codebird uses these values: - -- connection time = 3000 ms = 3 s -- timeout = 10000 ms = 10 s - -### …disable cURL? - -Codebird automatically detects whether you have the PHP cURL extension enabled. -If not, the library will try to connect to Twitter via socket. -For this to work, the PHP setting `allow_url_fopen` must be enabled. - -You may also manually disable cURL. Use the following call: - -```php -$cb->setUseCurl(false); -``` - -### …use a proxy? - -Codebird allows proxy support for both cURL handles and sockets. - -To activate proxy mode, use the following call: - -```php -$cb->setProxy('', ''); -``` - -You may also use an authenticated proxy. Use the following call: - -```php -$cb->setProxy('', ''); -$cb->setProxyAuthentication(':'); -``` - -By default, a HTTP proxy is assumed. To use a different proxy type, -use the corresponding [`CURLPROXY_*` constants](http://php.net/curl_setopt), like this: - -```php -$cb->setProxy('', '', CURLPROXY_SOCKS5); -``` - -### …quote a Tweet? - -Quoting a Tweet is different from a Retweet because you may add your own text. -The original Tweet will appear below your quote. -To quote a Tweet, add a link to the original Tweet to your quote, like in this sample: - -```php -$original_tweet = [ - 'id_str' => '684483801687392256', - 'user' => [ - 'screen_name' => 'LarryMcTweet' - ] -]; -$original_tweet = (object) $original_tweet; // sample, get real Tweet from API - -$id = $original_tweet->id_str; // use the `id_str` field because of long numbers -$screen_name = $original_tweet->user->screen_name; - -// looks like this: https://twitter.com/LarryMcTweet/status/684483801687392256 -$url = "https://twitter.com/$screen_name/status/$id"; -$text = 'I’d like to quote a Tweet.'; // maximum length = 140 minus 24 (link length) minus 1 space - -$reply = $cb->statuses_update([ - 'status' => "$text $url" -]); -``` diff --git a/twitter/vendor/jublonet/codebird-php/bower.json b/twitter/vendor/jublonet/codebird-php/bower.json deleted file mode 100644 index 6c724a2ad..000000000 --- a/twitter/vendor/jublonet/codebird-php/bower.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "codebird-php", - "version": "3.1.0", - "homepage": "https://www.jublo.net/projects/codebird/php", - "authors": [ - "Joshua Atkins ", - "J.M. " - ], - "description": "Easy access to the Twitter REST, Direct Messages, Account Activity, TON (Object Nest) and Twitter Ads API — all from one PHP library.", - "main": "src/codebird.php", - "moduleType": [], - "keywords": [ - "Twitter", - "API", - "networking" - ], - "license": "GPL-3.0+", - "ignore": [ - "**/.*", - "node_modules", - "bower_components", - "test", - "tests" - ] -} diff --git a/twitter/vendor/jublonet/codebird-php/build.xml b/twitter/vendor/jublonet/codebird-php/build.xml deleted file mode 100644 index 7addea7e1..000000000 --- a/twitter/vendor/jublonet/codebird-php/build.xml +++ /dev/null @@ -1,115 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/twitter/vendor/jublonet/codebird-php/composer.json b/twitter/vendor/jublonet/codebird-php/composer.json deleted file mode 100644 index 586f39c27..000000000 --- a/twitter/vendor/jublonet/codebird-php/composer.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "name": "jublonet/codebird-php", - "description" : "Easy access to the Twitter REST API, Direct Messages API, Account Activity API, TON (Object Nest) API and Twitter Ads API — all from one PHP library.", - "keywords": [ - "Twitter", - "API", - "networking" - ], - "homepage": "https://www.jublo.net/projects/codebird/php", - "license": "GPL-3.0+", - "authors": [ - { - "name": "Joshua Atkins", - "email": "joshua.atkins@jublo.net", - "homepage": "http://atkins.im/", - "role": "Developer" - }, - { - "name": "J.M.", - "email": "jm@jublo.net", - "homepage": "http://mynetx.net/", - "role": "Developer" - } - ], - "support": { - "email": "support@jublo.net", - "issues": "https://github.com/jublonet/codebird-php/issues", - "source": "https://github.com/jublonet/codebird-php/releases" - }, - "require": { - "php": ">=5.5.0", - "ext-hash": "*", - "ext-json": "*", - "lib-openssl": "*", - "composer/installers": "~1.0" - }, - "autoload": { - "classmap": ["src/"] - }, - "require-dev": { - "php-coveralls/php-coveralls": ">=0.6", - "phpunit/phpunit": ">=7.3", - "squizlabs/php_codesniffer": "2.*" - } -} diff --git a/twitter/vendor/jublonet/codebird-php/phpunit.xml b/twitter/vendor/jublonet/codebird-php/phpunit.xml deleted file mode 100644 index cd28e1c91..000000000 --- a/twitter/vendor/jublonet/codebird-php/phpunit.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - test/environment_test.php - - - test - - - - - - - - - - - src - - - diff --git a/twitter/vendor/jublonet/codebird-php/phpunit.xml.hhvm b/twitter/vendor/jublonet/codebird-php/phpunit.xml.hhvm deleted file mode 100644 index 87e7409c1..000000000 --- a/twitter/vendor/jublonet/codebird-php/phpunit.xml.hhvm +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - test/environment_test.php - - - test - - - - - - - diff --git a/twitter/vendor/jublonet/codebird-php/src/cacert.pem b/twitter/vendor/jublonet/codebird-php/src/cacert.pem deleted file mode 100644 index ee25bee11..000000000 --- a/twitter/vendor/jublonet/codebird-php/src/cacert.pem +++ /dev/null @@ -1,3314 +0,0 @@ -## -## Bundle of CA Root Certificates -## -## Certificate data from Mozilla as of: Wed Jun 20 03:12:06 2018 GMT -## -## 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: -## https://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt -## -## 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. -## -## Conversion done with mk-ca-bundle.pl version 1.27. -## SHA256: c80f571d9f4ebca4a91e0ad3a546f263153d71afffc845c6f8f52ce9d1a2e8ec -## - - -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----- - -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----- - -Entrust.net Premium 2048 Secure Server CA -========================================= ------BEGIN CERTIFICATE----- -MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVzdC5u -ZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxp -bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV -BAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQx -NzUwNTFaFw0yOTA3MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3 -d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTEl -MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5u -ZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A -MIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOL -Gp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSr -hRSGlVuXMlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzW -nLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUi -VBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQABo0IwQDAOBgNVHQ8BAf8E -BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJ -KoZIhvcNAQEFBQADggEBADubj1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPy -T/4xmf3IDExoU8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf -zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5bu/8j72gZyxKT -J1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+bYQLCIt+jerXmCHG8+c8eS9e -nNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/ErfF6adulZkMV8gzURZVE= ------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----- - -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----- - -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----- - -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 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----- - -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----- - -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----- - -QuoVadis Root CA -================ ------BEGIN CERTIFICATE----- -MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJCTTEZMBcGA1UE -ChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 -eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAz -MTkxODMzMzNaFw0yMTAzMTcxODMzMzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRp -cyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQD -EyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF -AAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Ypli4kVEAkOPcahdxYTMuk -J0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2DrOpm2RgbaIr1VxqYuvXtdj182d6UajtL -F8HVj71lODqV0D1VNk7feVcxKh7YWWVJWCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeL -YzcS19Dsw3sgQUSj7cugF+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWen -AScOospUxbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCCAk4w -PQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVvdmFkaXNvZmZzaG9y -ZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREwggENMIIBCQYJKwYBBAG+WAABMIH7 -MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNlIG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmlj -YXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJs -ZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh -Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYIKwYBBQUHAgEW -Fmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3TKbkGGew5Oanwl4Rqy+/fMIGu -BgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rqy+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkw -FwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0 -aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6 -tlCLMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSkfnIYj9lo -fFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf87C9TqnN7Az10buYWnuul -LsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1RcHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2x -gI4JVrmcGmD+XcHXetwReNDWXcG31a0ymQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi -5upZIof4l/UO/erMkqQWxFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi -5nrQNiOKSnQ2+Q== ------END CERTIFICATE----- - -QuoVadis Root CA 2 -================== ------BEGIN CERTIFICATE----- -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 ------END CERTIFICATE----- - -QuoVadis Root CA 3 -================== ------BEGIN CERTIFICATE----- -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 ------END CERTIFICATE----- - -Security Communication Root CA -============================== ------BEGIN CERTIFICATE----- -MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP -U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw -HhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP -U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw -8yl89f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJDKaVv0uM -DPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9Ms+k2Y7CI9eNqPPYJayX -5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/NQV3Is00qVUarH9oe4kA92819uZKAnDfd -DJZkndwi92SL32HeFZRSFaB9UslLqCHJxrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2 -JChzAgMBAAGjPzA9MB0GA1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYw -DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vGkl3g -0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfrUj94nK9NrvjVT8+a -mCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5Bw+SUEmK3TGXX8npN6o7WWWXlDLJ -s58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJUJRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ -6rBK+1YWc26sTfcioU+tHXotRSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAi -FL39vmwLAw== ------END CERTIFICATE----- - -Sonera Class 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----- - -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----- - -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----- - -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----- - -SwissSign Gold CA - G2 -====================== ------BEGIN CERTIFICATE----- -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 ------END CERTIFICATE----- - -SwissSign Silver CA - G2 -======================== ------BEGIN CERTIFICATE----- -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 ------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----- - -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----- - -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----- - -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----- - -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----- - -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----- - -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----- - -GeoTrust Primary Certification Authority - G3 -============================================= ------BEGIN CERTIFICATE----- -MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UE -BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA4IEdlb1RydXN0 -IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFy -eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIz -NTk1OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAo -YykgMjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMT -LUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz+uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5j -K/BGvESyiaHAKAxJcCGVn2TAppMSAmUmhsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdE -c5IiaacDiGydY8hS2pgn5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3C -IShwiP/WJmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exALDmKu -dlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZChuOl1UcCAwEAAaNC -MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMR5yo6hTgMdHNxr -2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IBAQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9 -cr5HqQ6XErhK8WTTOd8lNNTBzU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbE -Ap7aDHdlDkQNkv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD -AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUHSJsMC8tJP33s -t/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2Gspki4cErx5z481+oghLrGREt ------END CERTIFICATE----- - -thawte Primary Root CA - G2 -=========================== ------BEGIN CERTIFICATE----- -MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDELMAkGA1UEBhMC -VVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMpIDIwMDcgdGhhd3RlLCBJbmMu -IC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3Qg -Q0EgLSBHMjAeFw0wNzExMDUwMDAwMDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEV -MBMGA1UEChMMdGhhd3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBG -b3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAt -IEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/BebfowJPDQfGAFG6DAJS -LSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6papu+7qzcMBniKI11KOasf2twu8x+qi5 -8/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU -mtgAMADna3+FGO6Lts6KDPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUN -G4k8VIZ3KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41oxXZ3K -rr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg== ------END CERTIFICATE----- - -thawte Primary Root CA - G3 -=========================== ------BEGIN CERTIFICATE----- -MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCBrjELMAkGA1UE -BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2 -aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv -cml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0w -ODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh -d3RlLCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9uMTgwNgYD -VQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIG -A1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A -MIIBCgKCAQEAsr8nLPvb2FvdeHsbnndmgcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2At -P0LMqmsywCPLLEHd5N/8YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC -+BsUa0Lfb1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS99irY -7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2SzhkGcuYMXDhpxwTW -vGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUkOQIDAQABo0IwQDAPBgNVHRMBAf8E -BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJ -KoZIhvcNAQELBQADggEBABpA2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweK -A3rD6z8KLFIWoCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu -t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7cKUGRIjxpp7sC -8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fMm7v/OeZWYdMKp8RcTGB7BXcm -er/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZuMdRAGmI0Nj81Aa6sY6A= ------END CERTIFICATE----- - -GeoTrust Primary Certification Authority - G2 -============================================= ------BEGIN CERTIFICATE----- -MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDELMAkGA1UEBhMC -VVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA3IEdlb1RydXN0IElu -Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBD -ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1 -OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg -MjAwNyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMTLUdl -b1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjB2MBAGByqGSM49AgEG -BSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcLSo17VDs6bl8VAsBQps8lL33KSLjHUGMc -KiEIfJo22Av+0SbFWDEwKCXzXV2juLaltJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYD -VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+ -EVXVMAoGCCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGTqQ7m -ndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBuczrD6ogRLQy7rQkgu2 -npaqBA+K ------END CERTIFICATE----- - -VeriSign Universal Root Certification Authority -=============================================== ------BEGIN CERTIFICATE----- -MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCBvTELMAkGA1UE -BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO -ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk -IHVzZSBvbmx5MTgwNgYDVQQDEy9WZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9u -IEF1dGhvcml0eTAeFw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJV -UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv -cmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl -IG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0 -aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj -1mCOkdeQmIN65lgZOIzF9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGP -MiJhgsWHH26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+HLL72 -9fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN/BMReYTtXlT2NJ8I -AfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPTrJ9VAMf2CGqUuV/c4DPxhGD5WycR -tPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0G -CCsGAQUFBwEMBGEwX6FdoFswWTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2O -a8PPgGrUSBgsexkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud -DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4sAPmLGd75JR3 -Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+seQxIcaBlVZaDrHC1LGmWazx -Y8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTx -P/jgdFcrGJ2BtMQo2pSXpXDrrB2+BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+P -wGZsY6rp2aQW9IHRlRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4 -mJO37M2CYfE45k+XmCpajQ== ------END CERTIFICATE----- - -VeriSign Class 3 Public Primary Certification Authority - G4 -============================================================ ------BEGIN CERTIFICATE----- -MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjELMAkGA1UEBhMC -VVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3 -b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVz -ZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmlj -YXRpb24gQXV0aG9yaXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjEL -MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBU -cnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRo -b3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5 -IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8 -Utpkmw4tXNherJI9/gHmGUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGz -rl0Bp3vefLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUwAwEB -/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEw -HzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVyaXNpZ24u -Y29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMWkf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMD -A2gAMGUCMGYhDBgmYFo4e1ZC4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIx -AJw9SDkjOVgaFRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA== ------END CERTIFICATE----- - -NetLock Arany (Class Gold) Főtanúsítvány -======================================== ------BEGIN CERTIFICATE----- -MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQGEwJIVTERMA8G -A1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610 -dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBB -cmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgx -MjA2MTUwODIxWjCBpzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxO -ZXRMb2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlmaWNhdGlv -biBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNzIEdvbGQpIEbFkXRhbsO6 -c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxCRec75LbRTDofTjl5Bu -0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrTlF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw -/HpYzY6b7cNGbIRwXdrzAZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAk -H3B5r9s5VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRGILdw -fzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2BJtr+UBdADTHLpl1 -neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAGAQH/AgEEMA4GA1UdDwEB/wQEAwIB -BjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2MU9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwW -qZw8UQCgwBEIBaeZ5m8BiFRhbvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTta -YtOUZcTh5m2C+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC -bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2FuLjbvrW5Kfna -NwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2XjG4Kvte9nHfRCaexOYNkbQu -dZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= ------END CERTIFICATE----- - -Staat der Nederlanden Root CA - G2 -================================== ------BEGIN CERTIFICATE----- -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 -66+KAQ== ------END CERTIFICATE----- - -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----- - -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----- - -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----- - -Autoridad de Certificacion Firmaprofesional CIF A62634068 -========================================================= ------BEGIN CERTIFICATE----- -MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UEBhMCRVMxQjBA -BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2 -MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEyMzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIw -QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB -NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD -Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P -B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY -7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH -ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI -plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX -MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX -LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK -bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU -vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1Ud -EwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNH -DhpkLzCBpgYDVR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp -cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBvACAAZABlACAA -bABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBlAGwAbwBuAGEAIAAwADgAMAAx -ADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx -51tkljYyGOylMnfX40S2wBEqgLk9am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qk -R71kMrv2JYSiJ0L1ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaP -T481PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS3a/DTg4f -Jl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5kSeTy36LssUzAKh3ntLFl -osS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF3dvd6qJ2gHN99ZwExEWN57kci57q13XR -crHedUTnQn3iV2t93Jm8PYMo6oCTjcVMZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoR -saS8I8nkvof/uZS2+F0gStRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTD -KCOM/iczQ0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQBjLMi -6Et8Vcad+qMUu2WFbm5PEn4KPJ2V ------END CERTIFICATE----- - -Izenpe.com -========== ------BEGIN CERTIFICATE----- -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 ------END CERTIFICATE----- - -Chambers of Commerce Root - 2008 -================================ ------BEGIN CERTIFICATE----- -MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYDVQQGEwJFVTFD -MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv -bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu -QS4xKTAnBgNVBAMTIENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEy -Mjk1MFoXDTM4MDczMTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNl -ZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQF -EwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJl -cnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC -AQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW928sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKA -XuFixrYp4YFs8r/lfTJqVKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorj -h40G072QDuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR5gN/ -ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfLZEFHcpOrUMPrCXZk -NNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05aSd+pZgvMPMZ4fKecHePOjlO+Bd5g -D2vlGts/4+EhySnB8esHnFIbAURRPHsl18TlUlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331 -lubKgdaX8ZSD6e2wsWsSaR6s+12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ -0wlf2eOKNcx5Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj -ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAxhduub+84Mxh2 -EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNVHQ4EFgQU+SSsD7K1+HnA+mCI -G8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1+HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJ -BgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNh -bWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENh -bWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDiC -CQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUH -AgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAJASryI1 -wqM58C7e6bXpeHxIvj99RZJe6dqxGfwWPJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH -3qLPaYRgM+gQDROpI9CF5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbU -RWpGqOt1glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaHFoI6 -M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2pSB7+R5KBWIBpih1 -YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MDxvbxrN8y8NmBGuScvfaAFPDRLLmF -9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QGtjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcK -zBIKinmwPQN/aUv0NCB9szTqjktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvG -nrDQWzilm1DefhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg -OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZd0jQ ------END CERTIFICATE----- - -Global Chambersign Root - 2008 -============================== ------BEGIN CERTIFICATE----- -MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYDVQQGEwJFVTFD -MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv -bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu -QS4xJzAlBgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMx -NDBaFw0zODA3MzExMjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUg -Y3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJ -QTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD -aGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDf -VtPkOpt2RbQT2//BthmLN0EYlVJH6xedKYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXf -XjaOcNFccUMd2drvXNL7G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0 -ZJJ0YPP2zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4ddPB -/gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyGHoiMvvKRhI9lNNgA -TH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2Id3UwD2ln58fQ1DJu7xsepeY7s2M -H/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3VyJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfe -Ox2YItaswTXbo6Al/3K1dh3ebeksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSF -HTynyQbehP9r6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh -wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsogzCtLkykPAgMB -AAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQWBBS5CcqcHtvTbDprru1U8VuT -BjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDprru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UE -BhMCRVUxQzBBBgNVBAcTOk1hZHJpZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJm -aXJtYS5jb20vYWRkcmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJm -aXJtYSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiCCQDJzdPp -1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEWHGh0 -dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAICIf3DekijZBZRG -/5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZUohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6 -ReAJ3spED8IXDneRRXozX1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/s -dZ7LoR/xfxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVza2Mg -9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yydYhz2rXzdpjEetrHH -foUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMdSqlapskD7+3056huirRXhOukP9Du -qqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9OAP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETr -P3iZ8ntxPjzxmKfFGBI/5rsoM0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVq -c5iJWzouE4gev8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z -09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B ------END CERTIFICATE----- - -Go Daddy Root Certificate Authority - G2 -======================================== ------BEGIN CERTIFICATE----- -MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT -B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY29tLCBJbmMu -MTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5 -MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6 -b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8G -A1UEAxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKDE6bFIEMBO4Tx5oVJnyfq -9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD -+qK+ihVqf94Lw7YZFAXK6sOoBJQ7RnwyDfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutd -fMh8+7ArU6SSYmlRJQVhGkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMl -NAJWJwGRtDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEAAaNC -MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9 -BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmXWWcDYfF+OwYxdS2hII5PZYe096ac -vNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r -5N9ss4UXnT3ZJE95kTXWXwTrgIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYV -N8Gb5DKj7Tjo2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO -LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI4uJEvlz36hz1 ------END CERTIFICATE----- - -Starfield Root Certificate Authority - G2 -========================================= ------BEGIN CERTIFICATE----- -MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT -B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s -b2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVsZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0 -eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAw -DgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQg -VGVjaG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZpY2F0ZSBB -dXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3twQP89o/8ArFv -W59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMgnLRJdzIpVv257IzdIvpy3Cdhl+72WoTs -bhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNk -N3mSwOxGXn/hbVNMYq/NHwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7Nf -ZTD4p7dNdloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0HZbU -JtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC -AQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0GCSqGSIb3DQEBCwUAA4IBAQARWfol -TwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjUsHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx -4mcujJUDJi5DnUox9g61DLu34jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUw -F5okxBDgBPfg8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K -pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1mMpYjn0q7pBZ -c2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 ------END CERTIFICATE----- - -Starfield Services Root Certificate Authority - G2 -================================================== ------BEGIN CERTIFICATE----- -MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgT -B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s -b2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRl -IEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNV -BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxT -dGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2VydmljZXMg -Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC -AQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20pOsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2 -h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm28xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4Pa -hHQUw2eeBGg6345AWh1KTs9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLP -LJGmpufehRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk6mFB -rMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAwDwYDVR0TAQH/BAUw -AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMA0GCSqG -SIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMIbw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPP -E95Dz+I0swSdHynVv/heyNXBve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTy -xQGjhdByPq1zqwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd -iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn0q23KXB56jza -YyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCNsSi6 ------END CERTIFICATE----- - -AffirmTrust Commercial -====================== ------BEGIN CERTIFICATE----- -MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCVVMxFDAS -BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMB4XDTEw -MDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly -bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEF -AAOCAQ8AMIIBCgKCAQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6Eqdb -DuKPHx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yrba0F8PrV -C8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPALMeIrJmqbTFeurCA+ukV6 -BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1yHp52UKqK39c/s4mT6NmgTWvRLpUHhww -MmWd5jyTXlBOeuM61G7MGvv50jeuJCqrVwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNV -HQ4EFgQUnZPGU4teyq8/nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC -AQYwDQYJKoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYGXUPG -hi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNjvbz4YYCanrHOQnDi -qX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivtZ8SOyUOyXGsViQK8YvxO8rUzqrJv -0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9gN53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0kh -sUlHRUe072o0EclNmsxZt9YCnlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= ------END CERTIFICATE----- - -AffirmTrust Networking -====================== ------BEGIN CERTIFICATE----- -MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UEBhMCVVMxFDAS -BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMB4XDTEw -MDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly -bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEF -AAOCAQ8AMIIBCgKCAQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SE -Hi3yYJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbuakCNrmreI -dIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRLQESxG9fhwoXA3hA/Pe24 -/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gb -h+0t+nvujArjqWaJGctB+d1ENmHP4ndGyH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNV -HQ4EFgQUBx/S55zawm6iQLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC -AQYwDQYJKoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfOtDIu -UFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzuQY0x2+c06lkh1QF6 -12S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZLgo/bNjR9eUJtGxUAArgFU2HdW23 -WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4uolu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9 -/ZFvgrG+CJPbFEfxojfHRZ48x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= ------END CERTIFICATE----- - -AffirmTrust Premium -=================== ------BEGIN CERTIFICATE----- -MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UEBhMCVVMxFDAS -BgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMB4XDTEwMDEy -OTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRy -dXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A -MIICCgKCAgEAxBLfqV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtn -BKAQJG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ+jjeRFcV -5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrSs8PhaJyJ+HoAVt70VZVs -+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmd -GPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d770O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5R -p9EixAqnOEhss/n/fauGV+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NI -S+LI+H+SqHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S5u04 -6uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4IaC1nEWTJ3s7xgaVY5 -/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TXOwF0lkLgAOIua+rF7nKsu7/+6qqo -+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYEFJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB -/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByv -MiPIs0laUZx2KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg -Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B8OWycvpEgjNC -6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQMKSOyARiqcTtNd56l+0OOF6S -L5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK -+4w1IX2COPKpVJEZNZOUbWo6xbLQu4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmV -BtWVyuEklut89pMFu+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFg -IxpHYoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8GKa1qF60 -g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaORtGdFNrHF+QFlozEJLUb -zxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6eKeC2uAloGRwYQw== ------END CERTIFICATE----- - -AffirmTrust Premium ECC -======================= ------BEGIN CERTIFICATE----- -MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMCVVMxFDASBgNV -BAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQcmVtaXVtIEVDQzAeFw0xMDAx -MjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1U -cnVzdDEgMB4GA1UEAwwXQWZmaXJtVHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQA -IgNiAAQNMF4bFZ0D0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQ -N8O9ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0GA1UdDgQW -BBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAK -BggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/VsaobgxCd05DhT1wV/GzTjxi+zygk8N53X -57hG8f2h4nECMEJZh0PUUd+60wkyWs6Iflc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKM -eQ== ------END CERTIFICATE----- - -Certum Trusted Network CA -========================= ------BEGIN CERTIFICATE----- -MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQK -ExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlv -biBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIy -MTIwNzM3WhcNMjkxMjMxMTIwNzM3WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBU -ZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 -MSIwIAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC -AQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rHUV+rpDKmYYe2bg+G0jAC -l/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LMTXPb865Px1bVWqeWifrzq2jUI4ZZJ88J -J7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVUBBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4 -fOQtf/WsX+sWn7Et0brMkUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0 -cvW0QM8xAcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNVHRMB -Af8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNVHQ8BAf8EBAMCAQYw -DQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15ysHhE49wcrwn9I0j6vSrEuVUEtRCj -jSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfLI9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1 -mS1FhIrlQgnXdAIv94nYmem8J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5aj -Zt3hrvJBW8qYVoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI -03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw= ------END CERTIFICATE----- - -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----- - -Buypass Class 2 Root CA -======================= ------BEGIN CERTIFICATE----- -MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU -QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMiBSb290IENBMB4X -DTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1owTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1 -eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIw -DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1 -g1Lr6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPVL4O2fuPn -9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC911K2GScuVr1QGbNgGE41b -/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHxMlAQTn/0hpPshNOOvEu/XAFOBz3cFIqU -CqTqc/sLUegTBxj6DvEr0VQVfTzh97QZQmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeff -awrbD02TTqigzXsu8lkBarcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgI -zRFo1clrUs3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLiFRhn -Bkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRSP/TizPJhk9H9Z2vX -Uq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN9SG9dKpN6nIDSdvHXx1iY8f93ZHs -M+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxPAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD -VR0OBBYEFMmAd+BikoL1RpzzuvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF -AAOCAgEAU18h9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s -A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3tOluwlN5E40EI -osHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo+fsicdl9sz1Gv7SEr5AcD48S -aq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYd -DnkM/crqJIByw5c/8nerQyIKx+u2DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWD -LfJ6v9r9jv6ly0UsH8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0 -oyLQI+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK75t98biGC -wWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h3PFaTWwyI0PurKju7koS -CTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPzY11aWOIv4x3kqdbQCtCev9eBCfHJxyYN -rJgWVqA= ------END CERTIFICATE----- - -Buypass Class 3 Root CA -======================= ------BEGIN CERTIFICATE----- -MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU -QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMyBSb290IENBMB4X -DTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFowTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1 -eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIw -DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRH -sJ8YZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3EN3coTRiR -5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9tznDDgFHmV0ST9tD+leh -7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX0DJq1l1sDPGzbjniazEuOQAnFN44wOwZ -ZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH -2xc519woe2v1n/MuwU8XKhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV -/afmiSTYzIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvSO1UQ -RwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D34xFMFbG02SrZvPA -Xpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgPK9Dx2hzLabjKSWJtyNBjYt1gD1iq -j6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD -VR0OBBYEFEe4zf/lb+74suwvTg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF -AAOCAgEAACAjQTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV -cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXSIGrs/CIBKM+G -uIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2HJLw5QY33KbmkJs4j1xrG0aG -Q0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsaO5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8 -ZORK15FTAaggiG6cX0S5y2CBNOxv033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2 -KSb12tjE8nVhz36udmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz -6MkEkbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg413OEMXbug -UZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvDu79leNKGef9JOxqDDPDe -eOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq4/g7u9xN12TyUb7mqqta6THuBrxzvxNi -Cp/HuZc= ------END CERTIFICATE----- - -T-TeleSec GlobalRoot Class 3 -============================ ------BEGIN CERTIFICATE----- -MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM -IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU -cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgx -MDAxMTAyOTU2WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz -dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD -ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0GCSqGSIb3 -DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN8ELg63iIVl6bmlQdTQyK -9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/RLyTPWGrTs0NvvAgJ1gORH8EGoel15YU -NpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZF -iP0Zf3WHHx+xGwpzJFu5ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W -0eDrXltMEnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGjQjBA -MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1A/d2O2GCahKqGFPr -AyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOyWL6ukK2YJ5f+AbGwUgC4TeQbIXQb -fsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzT -ucpH9sry9uetuUg/vBa3wW306gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7h -P0HHRwA11fXT91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml -e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4pTpPDpFQUWw== ------END CERTIFICATE----- - -EE Certification Centre Root CA -=============================== ------BEGIN CERTIFICATE----- -MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQG -EwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1czEoMCYGA1UEAwwfRUUgQ2Vy -dGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYGCSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIw -MTAxMDMwMTAxMDMwWhgPMjAzMDEyMTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlB -UyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRy -ZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEBAQUAA4IB -DwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUyeuuOF0+W2Ap7kaJjbMeM -TC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvObntl8jixwKIy72KyaOBhU8E2lf/slLo2 -rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIwWFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw -93X2PaRka9ZP585ArQ/dMtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtN -P2MbRMNE1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYDVR0T -AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/zQas8fElyalL1BSZ -MEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEF -BQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEFBQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+Rj -xY6hUFaTlrg4wCQiZrxTFGGVv9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqM -lIpPnTX/dqQGE5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u -uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIWiAYLtqZLICjU -3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/vGVCJYMzpJJUPwssd8m92kMfM -dcGWxZ0= ------END CERTIFICATE----- - -D-TRUST Root Class 3 CA 2 2009 -============================== ------BEGIN CERTIFICATE----- -MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQK -DAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTAe -Fw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NThaME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxE -LVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIw -DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOAD -ER03UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42tSHKXzlA -BF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9RySPocq60vFYJfxLLHLGv -KZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsMlFqVlNpQmvH/pStmMaTJOKDfHR+4CS7z -p+hnUquVH+BGPtikw8paxTGA6Eian5Rp/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUC -AwEAAaOCARowggEWMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ -4PGEMA4GA1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVjdG9y -eS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUyMENBJTIwMiUyMDIw -MDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRlcmV2b2NhdGlvbmxpc3QwQ6BBoD+G -PWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAw -OS5jcmwwDQYJKoZIhvcNAQELBQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm -2H6NMLVwMeniacfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0 -o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4KzCUqNQT4YJEV -dT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8PIWmawomDeCTmGCufsYkl4ph -X5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3YJohw1+qRzT65ysCQblrGXnRl11z+o+I= ------END CERTIFICATE----- - -D-TRUST Root Class 3 CA 2 EV 2009 -================================= ------BEGIN CERTIFICATE----- -MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK -DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw -OTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUwNDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK -DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw -OTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfS -egpnljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM03TP1YtHh -zRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6ZqQTMFexgaDbtCHu39b+T -7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lRp75mpoo6Kr3HGrHhFPC+Oh25z1uxav60 -sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure35 -11H3a6UCAwEAAaOCASQwggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyv -cop9NteaHNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFwOi8v -ZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xhc3MlMjAzJTIwQ0El -MjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1ERT9jZXJ0aWZpY2F0ZXJldm9jYXRp -b25saXN0MEagRKBChkBodHRwOi8vd3d3LmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xh -c3NfM19jYV8yX2V2XzIwMDkuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+ -PPoeUSbrh/Yp3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05 -nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNFCSuGdXzfX2lX -ANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7naxpeG0ILD5EJt/rDiZE4OJudA -NCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqXKVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVv -w9y4AyHqnxbxLFS1 ------END CERTIFICATE----- - -CA Disig Root R2 -================ ------BEGIN CERTIFICATE----- -MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNVBAYTAlNLMRMw -EQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNp -ZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQyMDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sx -EzARBgNVBAcTCkJyYXRpc2xhdmExEzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERp -c2lnIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbC -w3OeNcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNHPWSb6Wia -xswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3Ix2ymrdMxp7zo5eFm1tL7 -A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbeQTg06ov80egEFGEtQX6sx3dOy1FU+16S -GBsEWmjGycT6txOgmLcRK7fWV8x8nhfRyyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqV -g8NTEQxzHQuyRpDRQjrOQG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa -5Beny912H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJQfYE -koopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUDi/ZnWejBBhG93c+A -Ak9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORsnLMOPReisjQS1n6yqEm70XooQL6i -Fh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNV -HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5u -Qu0wDQYJKoZIhvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM -tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqfGopTpti72TVV -sRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkblvdhuDvEK7Z4bLQjb/D907Je -dR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka+elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W8 -1k/BfDxujRNt+3vrMNDcTa/F1balTFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjx -mHHEt38OFdAlab0inSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01 -utI3gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18DrG5gPcFw0 -sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3OszMOl6W8KjptlwlCFtaOg -UxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8xL4ysEr3vQCj8KWefshNPZiTEUxnpHikV -7+ZtsH8tZ/3zbBt1RqPlShfppNcL ------END CERTIFICATE----- - -ACCVRAIZ1 -========= ------BEGIN CERTIFICATE----- -MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UEAwwJQUNDVlJB -SVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQswCQYDVQQGEwJFUzAeFw0xMTA1 -MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQBgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwH -UEtJQUNDVjENMAsGA1UECgwEQUNDVjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4IC -DwAwggIKAoICAQCbqau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gM -jmoYHtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWoG2ioPej0 -RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpAlHPrzg5XPAOBOp0KoVdD -aaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhrIA8wKFSVf+DuzgpmndFALW4ir50awQUZ -0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDG -WuzndN9wrqODJerWx5eHk6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs7 -8yM2x/474KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMOm3WR -5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpacXpkatcnYGMN285J -9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPluUsXQA+xtrn13k/c4LOsOxFwYIRK -Q26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYIKwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRw -Oi8vd3d3LmFjY3YuZXMvZmlsZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEu -Y3J0MB8GCCsGAQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2 -VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeTVfZW6oHlNsyM -Hj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIGCCsGAQUFBwICMIIBFB6CARAA -QQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUAcgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBh -AO0AegAgAGQAZQAgAGwAYQAgAEEAQwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUA -YwBuAG8AbABvAGcA7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBj -AHQAcgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAAQwBQAFMA -IABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUAczAwBggrBgEFBQcCARYk -aHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2MuaHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0 -dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRtaW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2 -MV9kZXIuY3JsMA4GA1UdDwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZI -hvcNAQEFBQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdpD70E -R9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gUJyCpZET/LtZ1qmxN -YEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+mAM/EKXMRNt6GGT6d7hmKG9Ww7Y49 -nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepDvV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJ -TS+xJlsndQAJxGJ3KQhfnlmstn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3 -sCPdK6jT2iWH7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h -I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szAh1xA2syVP1Xg -Nce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xFd3+YJ5oyXSrjhO7FmGYvliAd -3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2HpPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3p -EfbRD0tVNEYqi4Y7 ------END CERTIFICATE----- - -TWCA Global Root CA -=================== ------BEGIN CERTIFICATE----- -MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcxEjAQBgNVBAoT -CVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMTVFdDQSBHbG9iYWwgUm9vdCBD -QTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQK -EwlUQUlXQU4tQ0ExEDAOBgNVBAsTB1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3Qg -Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2C -nJfF10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz0ALfUPZV -r2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfChMBwqoJimFb3u/Rk28OKR -Q4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbHzIh1HrtsBv+baz4X7GGqcXzGHaL3SekV -tTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1W -KKD+u4ZqyPpcC1jcxkt2yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99 -sy2sbZCilaLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYPoA/p -yJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQABDzfuBSO6N+pjWxn -kjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcEqYSjMq+u7msXi7Kx/mzhkIyIqJdI -zshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMC -AQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6g -cFGn90xHNcgL1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn -LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WFH6vPNOw/KP4M -8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNoRI2T9GRwoD2dKAXDOXC4Ynsg -/eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlg -lPx4mI88k1HtQJAH32RjJMtOcQWh15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryP -A9gK8kxkRr05YuWW6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3m -i4TWnsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5jwa19hAM8 -EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWzaGHQRiapIVJpLesux+t3 -zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmyKwbQBM0= ------END CERTIFICATE----- - -TeliaSonera Root CA v1 -====================== ------BEGIN CERTIFICATE----- -MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAwNzEUMBIGA1UE -CgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJvb3QgQ0EgdjEwHhcNMDcxMDE4 -MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYDVQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwW -VGVsaWFTb25lcmEgUm9vdCBDQSB2MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+ -6yfwIaPzaSZVfp3FVRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA -3GV17CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+XZ75Ljo1k -B1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+/jXh7VB7qTCNGdMJjmhn -Xb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxH -oLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkmdtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3 -F0fUTPHSiXk+TT2YqGHeOh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJ -oWjiUIMusDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4pgd7 -gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fsslESl1MpWtTwEhDc -TwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQarMCpgKIv7NHfirZ1fpoeDVNAgMB -AAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qW -DNXr+nuqF+gTEjANBgkqhkiG9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNm -zqjMDfz1mgbldxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx -0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1TjTQpgcmLNkQfW -pb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBedY2gea+zDTYa4EzAvXUYNR0PV -G6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpc -c41teyWRyu5FrgZLAMzTsVlQ2jqIOylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOT -JsjrDNYmiLbAJM+7vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2 -qReWt88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcnHL/EVlP6 -Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVxSK236thZiNSQvxaz2ems -WWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY= ------END CERTIFICATE----- - -E-Tugra Certification Authority -=============================== ------BEGIN CERTIFICATE----- -MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNVBAYTAlRSMQ8w -DQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamls -ZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN -ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMw -NTEyMDk0OFoXDTIzMDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmEx -QDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxl -cmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQD -DB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A -MIICCgKCAgEA4vU/kwVRHoViVF56C/UYB4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vd -hQd2h8y/L5VMzH2nPbxHD5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5K -CKpbknSFQ9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEoq1+g -ElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3Dk14opz8n8Y4e0ypQ -BaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcHfC425lAcP9tDJMW/hkd5s3kc91r0 -E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsutdEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gz -rt48Ue7LE3wBf4QOXVGUnhMMti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAq -jqFGOjGY5RH8zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn -rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUXU8u3Zg5mTPj5 -dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6Jyr+zE7S6E5UMA8GA1UdEwEB -/wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEG -MA0GCSqGSIb3DQEBCwUAA4ICAQAFNzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAK -kEh47U6YA5n+KGCRHTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jO -XKqYGwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c77NCR807 -VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3+GbHeJAAFS6LrVE1Uweo -a2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WKvJUawSg5TB9D0pH0clmKuVb8P7Sd2nCc -dlqMQ1DujjByTd//SffGqWfZbawCEeI6FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEV -KV0jq9BgoRJP3vQXzTLlyb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gT -Dx4JnW2PAJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpDy4Q0 -8ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8dNL/+I5c30jn6PQ0G -C7TbO6Orb1wdtn7os4I07QZcJA== ------END CERTIFICATE----- - -T-TeleSec GlobalRoot Class 2 -============================ ------BEGIN CERTIFICATE----- -MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM -IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU -cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgx -MDAxMTA0MDE0WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz -dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD -ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0GCSqGSIb3 -DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUdAqSzm1nzHoqvNK38DcLZ -SBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiCFoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/F -vudocP05l03Sx5iRUKrERLMjfTlH6VJi1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx970 -2cu+fjOlbpSD8DT6IavqjnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGV -WOHAD3bZwI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGjQjBA -MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/WSA2AHmgoCJrjNXy -YdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhyNsZt+U2e+iKo4YFWz827n+qrkRk4 -r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPACuvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNf -vNoBYimipidx5joifsFvHZVwIEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR -3p1m0IvVVGb6g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN -9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlPBSeOE6Fuwg== ------END CERTIFICATE----- - -Atos TrustedRoot 2011 -===================== ------BEGIN CERTIFICATE----- -MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UEAwwVQXRvcyBU -cnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0xMTA3MDcxNDU4 -MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMMFUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsG -A1UECgwEQXRvczELMAkGA1UEBhMCREUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCV -hTuXbyo7LjvPpvMpNb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr -54rMVD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+SZFhyBH+ -DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ4J7sVaE3IqKHBAUsR320 -HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0Lcp2AMBYHlT8oDv3FdU9T1nSatCQujgKR -z3bFmx5VdJx4IbHwLfELn8LVlhgf8FQieowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7R -l+lwrrw7GWzbITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZ -bNshMBgGA1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB -CwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8jvZfza1zv7v1Apt+h -k6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kPDpFrdRbhIfzYJsdHt6bPWHJxfrrh -TZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pcmaHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a9 -61qn8FYiqTxlVMYVqL2Gns2Dlmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G -3mB/ufNPRJLvKrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed ------END CERTIFICATE----- - -QuoVadis Root CA 1 G3 -===================== ------BEGIN CERTIFICATE----- -MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQELBQAwSDELMAkG -A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv -b3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJN -MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEg -RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakE -PBtVwedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWerNrwU8lm -PNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF34168Xfuw6cwI2H44g4hWf6 -Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh4Pw5qlPafX7PGglTvF0FBM+hSo+LdoIN -ofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXpUhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/l -g6AnhF4EwfWQvTA9xO+oabw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV -7qJZjqlc3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/GKubX -9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSthfbZxbGL0eUQMk1f -iyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KOTk0k+17kBL5yG6YnLUlamXrXXAkg -t3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOtzCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD -AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZI -hvcNAQELBQADggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC -MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2cDMT/uFPpiN3 -GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUNqXsCHKnQO18LwIE6PWThv6ct -Tr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP -+V04ikkwj+3x6xn0dxoxGE1nVGwvb2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh -3jRJjehZrJ3ydlo28hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fa -wx/kNSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNjZgKAvQU6 -O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhpq1467HxpvMc7hU6eFbm0 -FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFtnh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOV -hMJKzRwuJIczYOXD ------END CERTIFICATE----- - -QuoVadis Root CA 2 G3 -===================== ------BEGIN CERTIFICATE----- -MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQELBQAwSDELMAkG -A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv -b3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJN -MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIg -RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFh -ZiFfqq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMWn4rjyduY -NM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ymc5GQYaYDFCDy54ejiK2t -oIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+O7q414AB+6XrW7PFXmAqMaCvN+ggOp+o -MiwMzAkd056OXbxMmO7FGmh77FOm6RQ1o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+l -V0POKa2Mq1W/xPtbAd0jIaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZo -L1NesNKqIcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz8eQQ -sSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43ehvNURG3YBZwjgQQvD -6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l7ZizlWNof/k19N+IxWA1ksB8aRxh -lRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALGcC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTAD -AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZI -hvcNAQELBQADggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66 -AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RCroijQ1h5fq7K -pVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0GaW/ZZGYjeVYg3UQt4XAoeo0L9 -x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4nlv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgz -dWqTHBLmYF5vHX/JHyPLhGGfHoJE+V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6X -U/IyAgkwo1jwDQHVcsaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+Nw -mNtddbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNgKCLjsZWD -zYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeMHVOyToV7BjjHLPj4sHKN -JeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4WSr2Rz0ZiC3oheGe7IUIarFsNMkd7Egr -O3jtZsSOeWmD3n+M ------END CERTIFICATE----- - -QuoVadis Root CA 3 G3 -===================== ------BEGIN CERTIFICATE----- -MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQELBQAwSDELMAkG -A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv -b3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJN -MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMg -RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286 -IxSR/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNuFoM7pmRL -Mon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXRU7Ox7sWTaYI+FrUoRqHe -6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+cra1AdHkrAj80//ogaX3T7mH1urPnMNA3 -I4ZyYUUpSFlob3emLoG+B01vr87ERRORFHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3U -VDmrJqMz6nWB2i3ND0/kA9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f7 -5li59wzweyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634RylsSqi -Md5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBpVzgeAVuNVejH38DM -dyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0QA4XN8f+MFrXBsj6IbGB/kE+V9/Yt -rQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD -AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZI -hvcNAQELBQADggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px -KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnIFUBhynLWcKzS -t/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5WvvoxXqA/4Ti2Tk08HS6IT7SdEQ -TXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFgu/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9Du -DcpmvJRPpq3t/O5jrFc/ZSXPsoaP0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGib -Ih6BJpsQBJFxwAYf3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmD -hPbl8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+DhcI00iX -0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HNPlopNLk9hM6xZdRZkZFW -dSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ywaZWWDYWGWVjUTR939+J399roD1B0y2 -PpxxVJkES/1Y+Zj0 ------END CERTIFICATE----- - -DigiCert Assured ID Root G2 -=========================== ------BEGIN CERTIFICATE----- -MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQG -EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw -IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgw -MTE1MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL -ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIw -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSAn61UQbVH -35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4HteccbiJVMWWXvdMX0h5i89vq -bFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9HpEgjAALAcKxHad3A2m67OeYfcgnDmCXRw -VWmvo2ifv922ebPynXApVfSr/5Vh88lAbx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OP -YLfykqGxvYmJHzDNw6YuYjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+Rn -lTGNAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTO -w0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPIQW5pJ6d1Ee88hjZv -0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I0jJmwYrA8y8678Dj1JGG0VDjA9tz -d29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4GnilmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAW -hsI6yLETcDbYz+70CjTVW0z9B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0M -jomZmWzwPDCvON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo -IhNzbM8m9Yop5w== ------END CERTIFICATE----- - -DigiCert Assured ID Root G3 -=========================== ------BEGIN CERTIFICATE----- -MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQswCQYDVQQGEwJV -UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYD -VQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1 -MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQ -BgcqhkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJfZn4f5dwb -RXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17QRSAPWXYQ1qAk8C3eNvJs -KTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgF -UaFNN6KDec6NHSrkhDAKBggqhkjOPQQDAwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5Fy -YZ5eEJJZVrmDxxDnOOlYJjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy -1vUhZscv6pZjamVFkpUBtA== ------END CERTIFICATE----- - -DigiCert Global Root G2 -======================= ------BEGIN CERTIFICATE----- -MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQG -EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw -HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUx -MjAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 -dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkq -hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI2/Ou8jqJ -kTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx1x7e/dfgy5SDN67sH0NO -3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQq2EGnI/yuum06ZIya7XzV+hdG82MHauV -BJVJ8zUtluNJbd134/tJS7SsVQepj5WztCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyM -UNGPHgm+F6HmIcr9g+UQvIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQAB -o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV5uNu -5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY1Yl9PMWLSn/pvtsr -F9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4NeF22d+mQrvHRAiGfzZ0JFrabA0U -WTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NGFdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBH -QRFXGU7Aj64GxJUTFy8bJZ918rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/ -iyK5S9kJRaTepLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl -MrY= ------END CERTIFICATE----- - -DigiCert Global Root G3 -======================= ------BEGIN CERTIFICATE----- -MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQswCQYDVQQGEwJV -UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYD -VQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAw -MDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5k -aWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0C -AQYFK4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FGfp4tn+6O -YwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPOZ9wj/wMco+I+o0IwQDAP -BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNp -Yim8S8YwCgYIKoZIzj0EAwMDaAAwZQIxAK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y -3maTD/HMsQmP3Wyr+mt/oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34 -VOKa5Vt8sycX ------END CERTIFICATE----- - -DigiCert Trusted Root G4 -======================== ------BEGIN CERTIFICATE----- -MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBiMQswCQYDVQQG -EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEw -HwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1 -MTIwMDAwWjBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0G -CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3yithZwuEp -pz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9o -k3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7Fsa -vOvJz82sNEBfsXpm7nfISKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGY -QJB5w3jHtrHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6 -MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCiEhtm -mnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADMfRyVw4/3IbKyEbe7 -f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFH -dL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8 -oR7FwI+isX4KJpn15GkvmB0t9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud -DwEB/wQEAwIBhjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD -ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2SV1EY+CtnJYY -ZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd+SeuMIW59mdNOj6PWTkiU0Tr -yF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWcfFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy -7zBZLq7gcfJW5GqXb5JQbZaNaHqasjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iah -ixTXTBmyUEFxPT9NcCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN -5r5N0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie4u1Ki7wb -/UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mIr/OSmbaz5mEP0oUA51Aa -5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tK -G48BtieVU+i2iW1bvGjUI+iLUaJW+fCmgKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP -82Z+ ------END CERTIFICATE----- - -COMODO RSA Certification Authority -================================== ------BEGIN CERTIFICATE----- -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 -LaZRfyHBNVOFBkpdn627G190 ------END CERTIFICATE----- - -USERTrust RSA Certification Authority -===================================== ------BEGIN CERTIFICATE----- -MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCBiDELMAkGA1UE -BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK -ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UE -BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK -ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh -dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCAEmUXNg7D2wiz -0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2j -Y0K2dvKpOyuR+OJv0OwWIJAJPuLodMkYtJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFn -RghRy4YUVD+8M/5+bJz/Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O -+T23LLb2VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT79uq -/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6c0Plfg6lZrEpfDKE -Y1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmTYo61Zs8liM2EuLE/pDkP2QKe6xJM -lXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97lc6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8 -yexDJtC/QV9AqURE9JnnV4eeUB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+ -eLf8ZxXhyVeEHg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd -BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF -MAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPFUp/L+M+ZBn8b2kMVn54CVVeW -FPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KOVWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ -7l8wXEskEVX/JJpuXior7gtNn3/3ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQ -Eg9zKC7F4iRO/Fjs8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM -8WcRiQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYzeSf7dNXGi -FSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZXHlKYC6SQK5MNyosycdi -yA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9c -J2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRBVXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGw -sAvgnEzDHNb842m1R0aBL6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gx -Q+6IHdfGjjxDah2nGN59PRbxYvnKkKj9 ------END CERTIFICATE----- - -USERTrust ECC Certification Authority -===================================== ------BEGIN CERTIFICATE----- -MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDELMAkGA1UEBhMC -VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU -aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv -biBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMC -VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU -aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv -biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqfloI+d61SRvU8Za2EurxtW2 -0eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinngo4N+LZfQYcTxmdwlkWOrfzCjtHDix6Ez -nPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0GA1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNV -HQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBB -HU6+4WMBzzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbWRNZu -9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg= ------END CERTIFICATE----- - -GlobalSign ECC Root CA - R4 -=========================== ------BEGIN CERTIFICATE----- -MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEkMCIGA1UECxMb -R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD -EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb -R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD -EwpHbG9iYWxTaWduMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprl -OQcJFspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAwDgYDVR0P -AQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61FuOJAf/sKbvu+M8k8o4TV -MAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGXkPoUVy0D7O48027KqGx2vKLeuwIgJ6iF -JzWbVsaj8kfSt24bAgAXqmemFZHe+pTsewv4n4Q= ------END CERTIFICATE----- - -GlobalSign ECC Root CA - R5 -=========================== ------BEGIN CERTIFICATE----- -MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEkMCIGA1UECxMb -R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD -EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb -R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD -EwpHbG9iYWxTaWduMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6 -SFkc8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8kehOvRnkmS -h5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd -BgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYIKoZIzj0EAwMDaAAwZQIxAOVpEslu28Yx -uglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7 -yFz9SO8NdCKoCOJuxUnOxwy8p2Fp8fc74SrL+SvzZpA3 ------END CERTIFICATE----- - -Staat der Nederlanden Root CA - G3 -================================== ------BEGIN CERTIFICATE----- -MIIFdDCCA1ygAwIBAgIEAJiiOTANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJOTDEeMBwGA1UE -CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFhdCBkZXIgTmVkZXJsYW5kZW4g -Um9vdCBDQSAtIEczMB4XDTEzMTExNDExMjg0MloXDTI4MTExMzIzMDAwMFowWjELMAkGA1UEBhMC -TkwxHjAcBgNVBAoMFVN0YWF0IGRlciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5l -ZGVybGFuZGVuIFJvb3QgQ0EgLSBHMzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL4y -olQPcPssXFnrbMSkUeiFKrPMSjTysF/zDsccPVMeiAho2G89rcKezIJnByeHaHE6n3WWIkYFsO2t -x1ueKt6c/DrGlaf1F2cY5y9JCAxcz+bMNO14+1Cx3Gsy8KL+tjzk7FqXxz8ecAgwoNzFs21v0IJy -EavSgWhZghe3eJJg+szeP4TrjTgzkApyI/o1zCZxMdFyKJLZWyNtZrVtB0LrpjPOktvA9mxjeM3K -Tj215VKb8b475lRgsGYeCasH/lSJEULR9yS6YHgamPfJEf0WwTUaVHXvQ9Plrk7O53vDxk5hUUur -mkVLoR9BvUhTFXFkC4az5S6+zqQbwSmEorXLCCN2QyIkHxcE1G6cxvx/K2Ya7Irl1s9N9WMJtxU5 -1nus6+N86U78dULI7ViVDAZCopz35HCz33JvWjdAidiFpNfxC95DGdRKWCyMijmev4SH8RY7Ngzp -07TKbBlBUgmhHbBqv4LvcFEhMtwFdozL92TkA1CvjJFnq8Xy7ljY3r735zHPbMk7ccHViLVlvMDo -FxcHErVc0qsgk7TmgoNwNsXNo42ti+yjwUOH5kPiNL6VizXtBznaqB16nzaeErAMZRKQFWDZJkBE -41ZgpRDUajz9QdwOWke275dhdU/Z/seyHdTtXUmzqWrLZoQT1Vyg3N9udwbRcXXIV2+vD3dbAgMB -AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRUrfrHkleu -yjWcLhL75LpdINyUVzANBgkqhkiG9w0BAQsFAAOCAgEAMJmdBTLIXg47mAE6iqTnB/d6+Oea31BD -U5cqPco8R5gu4RV78ZLzYdqQJRZlwJ9UXQ4DO1t3ApyEtg2YXzTdO2PCwyiBwpwpLiniyMMB8jPq -KqrMCQj3ZWfGzd/TtiunvczRDnBfuCPRy5FOCvTIeuXZYzbB1N/8Ipf3YF3qKS9Ysr1YvY2WTxB1 -v0h7PVGHoTx0IsL8B3+A3MSs/mrBcDCw6Y5p4ixpgZQJut3+TcCDjJRYwEYgr5wfAvg1VUkvRtTA -8KCWAg8zxXHzniN9lLf9OtMJgwYh/WA9rjLA0u6NpvDntIJ8CsxwyXmA+P5M9zWEGYox+wrZ13+b -8KKaa8MFSu1BYBQw0aoRQm7TIwIEC8Zl3d1Sd9qBa7Ko+gE4uZbqKmxnl4mUnrzhVNXkanjvSr0r -mj1AfsbAddJu+2gw7OyLnflJNZoaLNmzlTnVHpL3prllL+U9bTpITAjc5CgSKL59NVzq4BZ+Extq -1z7XnvwtdbLBFNUjA9tbbws+eC8N3jONFrdI54OagQ97wUNNVQQXOEpR1VmiiXTTn74eS9fGbbeI -JG9gkaSChVtWQbzQRKtqE77RLFi3EjNYsjdj3BP1lB0/QFH1T/U67cjF68IeHRaVesd+QnGTbksV -tzDfqu1XhUisHWrdOWnk4Xl4vs4Fv6EM94B7IWcnMFk= ------END CERTIFICATE----- - -Staat der Nederlanden EV Root CA -================================ ------BEGIN CERTIFICATE----- -MIIFcDCCA1igAwIBAgIEAJiWjTANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJOTDEeMBwGA1UE -CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSkwJwYDVQQDDCBTdGFhdCBkZXIgTmVkZXJsYW5kZW4g -RVYgUm9vdCBDQTAeFw0xMDEyMDgxMTE5MjlaFw0yMjEyMDgxMTEwMjhaMFgxCzAJBgNVBAYTAk5M -MR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xKTAnBgNVBAMMIFN0YWF0IGRlciBOZWRl -cmxhbmRlbiBFViBSb290IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA48d+ifkk -SzrSM4M1LGns3Amk41GoJSt5uAg94JG6hIXGhaTK5skuU6TJJB79VWZxXSzFYGgEt9nCUiY4iKTW -O0Cmws0/zZiTs1QUWJZV1VD+hq2kY39ch/aO5ieSZxeSAgMs3NZmdO3dZ//BYY1jTw+bbRcwJu+r -0h8QoPnFfxZpgQNH7R5ojXKhTbImxrpsX23Wr9GxE46prfNeaXUmGD5BKyF/7otdBwadQ8QpCiv8 -Kj6GyzyDOvnJDdrFmeK8eEEzduG/L13lpJhQDBXd4Pqcfzho0LKmeqfRMb1+ilgnQ7O6M5HTp5gV -XJrm0w912fxBmJc+qiXbj5IusHsMX/FjqTf5m3VpTCgmJdrV8hJwRVXj33NeN/UhbJCONVrJ0yPr -08C+eKxCKFhmpUZtcALXEPlLVPxdhkqHz3/KRawRWrUgUY0viEeXOcDPusBCAUCZSCELa6fS/ZbV -0b5GnUngC6agIk440ME8MLxwjyx1zNDFjFE7PZQIZCZhfbnDZY8UnCHQqv0XcgOPvZuM5l5Tnrmd -74K74bzickFbIZTTRTeU0d8JOV3nI6qaHcptqAqGhYqCvkIH1vI4gnPah1vlPNOePqc7nvQDs/nx -fRN0Av+7oeX6AHkcpmZBiFxgV6YuCcS6/ZrPpx9Aw7vMWgpVSzs4dlG4Y4uElBbmVvMCAwEAAaNC -MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFP6rAJCYniT8qcwa -ivsnuL8wbqg7MA0GCSqGSIb3DQEBCwUAA4ICAQDPdyxuVr5Os7aEAJSrR8kN0nbHhp8dB9O2tLsI -eK9p0gtJ3jPFrK3CiAJ9Brc1AsFgyb/E6JTe1NOpEyVa/m6irn0F3H3zbPB+po3u2dfOWBfoqSmu -c0iH55vKbimhZF8ZE/euBhD/UcabTVUlT5OZEAFTdfETzsemQUHSv4ilf0X8rLiltTMMgsT7B/Zq -5SWEXwbKwYY5EdtYzXc7LMJMD16a4/CrPmEbUCTCwPTxGfARKbalGAKb12NMcIxHowNDXLldRqAN -b/9Zjr7dn3LDWyvfjFvO5QxGbJKyCqNMVEIYFRIYvdr8unRu/8G2oGTYqV9Vrp9canaW2HNnh/tN -f1zuacpzEPuKqf2evTY4SUmH9A4U8OmHuD+nT3pajnnUk+S7aFKErGzp85hwVXIy+TSrK0m1zSBi -5Dp6Z2Orltxtrpfs/J92VoguZs9btsmksNcFuuEnL5O7Jiqik7Ab846+HUCjuTaPPoIaGl6I6lD4 -WeKDRikL40Rc4ZW2aZCaFG+XroHPaO+Zmr615+F/+PoTRxZMzG0IQOeLeG9QgkRQP2YGiqtDhFZK -DyAthg710tvSeopLzaXoTvFeJiUBWSOgftL2fiFX1ye8FVdMpEbB4IMeDExNH08GGeL5qPQ6gqGy -eUN51q1veieQA6TqJIc/2b3Z6fJfUEkc7uzXLg== ------END CERTIFICATE----- - -IdenTrust Commercial Root CA 1 -============================== ------BEGIN CERTIFICATE----- -MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBKMQswCQYDVQQG -EwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBS -b290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQwMTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzES -MBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENB -IDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ld -hNlT3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU+ehcCuz/ -mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gpS0l4PJNgiCL8mdo2yMKi -1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1bVoE/c40yiTcdCMbXTMTEl3EASX2MN0C -XZ/g1Ue9tOsbobtJSdifWwLziuQkkORiT0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl -3ZBWzvurpWCdxJ35UrCLvYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzy -NeVJSQjKVsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZKdHzV -WYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHTc+XvvqDtMwt0viAg -xGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hvl7yTmvmcEpB4eoCHFddydJxVdHix -uuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5NiGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMC -AQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZI -hvcNAQELBQADggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH -6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwtLRvM7Kqas6pg -ghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93nAbowacYXVKV7cndJZ5t+qnt -ozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3+wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmV -YjzlVYA211QC//G5Xc7UI2/YRYRKW2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUX -feu+h1sXIFRRk0pTAwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/ro -kTLql1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG4iZZRHUe -2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZmUlO+KWA2yUPHGNiiskz -Z2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7R -cGzM7vRX+Bi6hG6H ------END CERTIFICATE----- - -IdenTrust Public Sector Root CA 1 -================================= ------BEGIN CERTIFICATE----- -MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQG -EwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3Rv -ciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcNMzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJV -UzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBS -b290IENBIDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTy -P4o7ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGyRBb06tD6 -Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlSbdsHyo+1W/CD80/HLaXI -rcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF/YTLNiCBWS2ab21ISGHKTN9T0a9SvESf -qy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoS -mJxZZoY+rfGwyj4GD3vwEUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFn -ol57plzy9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9VGxyh -LrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ2fjXctscvG29ZV/v -iDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsVWaFHVCkugyhfHMKiq3IXAAaOReyL -4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gDW/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8B -Af8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMw -DQYJKoZIhvcNAQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj -t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHVDRDtfULAj+7A -mgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9TaDKQGXSc3z1i9kKlT/YPyNt -GtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8GlwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFt -m6/n6J91eEyrRjuazr8FGF1NFTwWmhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMx -NRF4eKLg6TCMf4DfWN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4 -Mhn5+bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJtshquDDI -ajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhAGaQdp/lLQzfcaFpPz+vC -ZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ -3Wl9af0AVqW3rLatt8o+Ae+c ------END CERTIFICATE----- - -Entrust Root Certification Authority - G2 -========================================= ------BEGIN CERTIFICATE----- -MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMCVVMxFjAUBgNV -BAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVy -bXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ug -b25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIw -HhcNMDkwNzA3MTcyNTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoT -DUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMx -OTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25s -eTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwggEi -MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP -/vaCeb9zYQYKpSfYs1/TRU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXz -HHfV1IWNcCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hWwcKU -s/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1U1+cPvQXLOZprE4y -TGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0jaWvYkxN4FisZDQSA/i2jZRjJKRx -AgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ6 -0B7vfec7aVHUbI2fkBJmqzANBgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5Z -iXMRrEPR9RP/jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ -Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v1fN2D807iDgi -nWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4RnAuknZoh8/CbCzB428Hch0P+ -vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmHVHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xO -e4pIb4tF9g== ------END CERTIFICATE----- - -Entrust Root Certification Authority - EC1 -========================================== ------BEGIN CERTIFICATE----- -MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkGA1UEBhMCVVMx -FjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVn -YWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXpl -ZCB1c2Ugb25seTEzMDEGA1UEAxMqRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5 -IC0gRUMxMB4XDTEyMTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYw -FAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2Fs -LXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQg -dXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt -IEVDMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHy -AsWfoPZb1YsGGYZPUxBtByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef -9eNi1KlHBz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE -FLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVCR98crlOZF7ZvHH3h -vxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nXhTcGtXsI/esni0qU+eH6p44mCOh8 -kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G ------END CERTIFICATE----- - -CFCA EV ROOT -============ ------BEGIN CERTIFICATE----- -MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJDTjEwMC4GA1UE -CgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNB -IEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkxMjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEw -MC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQD -DAxDRkNBIEVWIFJPT1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnV -BU03sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpLTIpTUnrD -7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5/ZOkVIBMUtRSqy5J35DN -uF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp7hZZLDRJGqgG16iI0gNyejLi6mhNbiyW -ZXvKWfry4t3uMCz7zEasxGPrb382KzRzEpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7 -xzbh72fROdOXW3NiGUgthxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9f -py25IGvPa931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqotaK8K -gWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNgTnYGmE69g60dWIol -hdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfVPKPtl8MeNPo4+QgO48BdK4PRVmrJ -tqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hvcWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAf -BgNVHSMEGDAWgBTj/i39KNALtbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB -/wQEAwIBBjAdBgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB -ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObTej/tUxPQ4i9q -ecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdLjOztUmCypAbqTuv0axn96/Ua -4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBSESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sG -E5uPhnEFtC+NiWYzKXZUmhH4J/qyP5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfX -BDrDMlI1Dlb4pd19xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjn -aH9dCi77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN5mydLIhy -PDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe/v5WOaHIz16eGWRGENoX -kbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+ZAAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3C -ekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su ------END CERTIFICATE----- - -Certinomis - Root CA -==================== ------BEGIN CERTIFICATE----- -MIIFkjCCA3qgAwIBAgIBATANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJGUjETMBEGA1UEChMK -Q2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxHTAbBgNVBAMTFENlcnRpbm9taXMg -LSBSb290IENBMB4XDTEzMTAyMTA5MTcxOFoXDTMzMTAyMTA5MTcxOFowWjELMAkGA1UEBhMCRlIx -EzARBgNVBAoTCkNlcnRpbm9taXMxFzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMR0wGwYDVQQDExRD -ZXJ0aW5vbWlzIC0gUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANTMCQos -P5L2fxSeC5yaah1AMGT9qt8OHgZbn1CF6s2Nq0Nn3rD6foCWnoR4kkjW4znuzuRZWJflLieY6pOo -d5tK8O90gC3rMB+12ceAnGInkYjwSond3IjmFPnVAy//ldu9n+ws+hQVWZUKxkd8aRi5pwP5ynap -z8dvtF4F/u7BUrJ1Mofs7SlmO/NKFoL21prbcpjp3vDFTKWrteoB4owuZH9kb/2jJZOLyKIOSY00 -8B/sWEUuNKqEUL3nskoTuLAPrjhdsKkb5nPJWqHZZkCqqU2mNAKthH6yI8H7KsZn9DS2sJVqM09x -RLWtwHkziOC/7aOgFLScCbAK42C++PhmiM1b8XcF4LVzbsF9Ri6OSyemzTUK/eVNfaoqoynHWmgE -6OXWk6RiwsXm9E/G+Z8ajYJJGYrKWUM66A0ywfRMEwNvbqY/kXPLynNvEiCL7sCCeN5LLsJJwx3t -FvYk9CcbXFcx3FXuqB5vbKziRcxXV4p1VxngtViZSTYxPDMBbRZKzbgqg4SGm/lg0h9tkQPTYKbV -PZrdd5A9NaSfD171UkRpucC63M9933zZxKyGIjK8e2uR73r4F2iw4lNVYC2vPsKD2NkJK/DAZNuH -i5HMkesE/Xa0lZrmFAYb1TQdvtj/dBxThZngWVJKYe2InmtJiUZ+IFrZ50rlau7SZRFDAgMBAAGj -YzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTvkUz1pcMw6C8I -6tNxIqSSaHh02TAfBgNVHSMEGDAWgBTvkUz1pcMw6C8I6tNxIqSSaHh02TANBgkqhkiG9w0BAQsF -AAOCAgEAfj1U2iJdGlg+O1QnurrMyOMaauo++RLrVl89UM7g6kgmJs95Vn6RHJk/0KGRHCwPT5iV -WVO90CLYiF2cN/z7ZMF4jIuaYAnq1fohX9B0ZedQxb8uuQsLrbWwF6YSjNRieOpWauwK0kDDPAUw -Pk2Ut59KA9N9J0u2/kTO+hkzGm2kQtHdzMjI1xZSg081lLMSVX3l4kLr5JyTCcBMWwerx20RoFAX -lCOotQqSD7J6wWAsOMwaplv/8gzjqh8c3LigkyfeY+N/IZ865Z764BNqdeuWXGKRlI5nU7aJ+BIJ -y29SWwNyhlCVCNSNh4YVH5Uk2KRvms6knZtt0rJ2BobGVgjF6wnaNsIbW0G+YSrjcOa4pvi2WsS9 -Iff/ql+hbHY5ZtbqTFXhADObE5hjyW/QASAJN1LnDE8+zbz1X5YnpyACleAu6AdBBR8Vbtaw5Bng -DwKTACdyxYvRVB9dSsNAl35VpnzBMwQUAR1JIGkLGZOdblgi90AMRgwjY/M50n92Uaf0yKHxDHYi -I0ZSKS3io0EHVmmY0gUJvGnHWmHNj4FgFU2A3ZDifcRQ8ow7bkrHxuaAKzyBvBGAFhAn1/DNP3nM -cyrDflOR1m749fPH0FFNjkulW+YZFzvWgQncItzujrnEj1PhZ7szuIgVRs/taTX/dQ1G885x4cVr -hkIGuUE= ------END CERTIFICATE----- - -OISTE WISeKey Global Root GB CA -=============================== ------BEGIN CERTIFICATE----- -MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBtMQswCQYDVQQG -EwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl -ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAw -MzJaFw0zOTEyMDExNTEwMzFaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYD -VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEds -b2JhbCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3HEokKtaX -scriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGxWuR51jIjK+FTzJlFXHtP -rby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk -9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNku7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4o -Qnc/nSMbsrY9gBQHTC5P99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvg -GUpuuy9rM2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB -/zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZI -hvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrghcViXfa43FK8+5/ea4n32cZiZBKpD -dHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0 -VQreUGdNZtGn//3ZwLWoo4rOZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEui -HZeeevJuQHHfaPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic -Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM= ------END CERTIFICATE----- - -SZAFIR ROOT CA2 -=============== ------BEGIN CERTIFICATE----- -MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQELBQAwUTELMAkG -A1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6ZW5pb3dhIFMuQS4xGDAWBgNV -BAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkwNzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJ -BgNVBAYTAlBMMSgwJgYDVQQKDB9LcmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYD -VQQDDA9TWkFGSVIgUk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5Q -qEvNQLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT3PSQ1hNK -DJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw3gAeqDRHu5rr/gsUvTaE -2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr63fE9biCloBK0TXC5ztdyO4mTp4CEHCdJ -ckm1/zuVnsHMyAHs6A6KCpbns6aH5db5BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwi -ieDhZNRnvDF5YTy7ykHNXGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P -AQH/BAQDAgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsFAAOC -AQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw8PRBEew/R40/cof5 -O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOGnXkZ7/e7DDWQw4rtTw/1zBLZpD67 -oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCPoky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul -4+vJhaAlIDf7js4MNIThPIGyd05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6 -+/NNIxuZMzSgLvWpCz/UXeHPhJ/iGcJfitYgHuNztw== ------END CERTIFICATE----- - -Certum Trusted Network CA 2 -=========================== ------BEGIN CERTIFICATE----- -MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCBgDELMAkGA1UE -BhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAlBgNVBAsTHkNlcnR1 -bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29y -ayBDQSAyMCIYDzIwMTExMDA2MDgzOTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQ -TDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENl -cnRpZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENB -IDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWADGSdhhuWZGc/IjoedQF9 -7/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+o -CgCXhVqqndwpyeI1B+twTUrWwbNWuKFBOJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40b -Rr5HMNUuctHFY9rnY3lEfktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2p -uTRZCr+ESv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1mo130 -GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02isx7QBlrd9pPPV3WZ -9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOWOZV7bIBaTxNyxtd9KXpEulKkKtVB -Rgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgezTv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pye -hizKV/Ma5ciSixqClnrDvFASadgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vM -BhBgu4M1t15n3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD -AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZI -hvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQF/xlhMcQSZDe28cmk4gmb3DW -Al45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTfCVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuA -L55MYIR4PSFk1vtBHxgP58l1cb29XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMo -clm2q8KMZiYcdywmdjWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tM -pkT/WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jbAoJnwTnb -w3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksqP/ujmv5zMnHCnsZy4Ypo -J/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Kob7a6bINDd82Kkhehnlt4Fj1F4jNy3eFm -ypnTycUm/Q1oBEauttmbjL4ZvrHG8hnjXALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLX -is7VmFxWlgPF7ncGNf/P5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7 -zAYspsbiDrW5viSP ------END CERTIFICATE----- - -Hellenic Academic and Research Institutions RootCA 2015 -======================================================= ------BEGIN CERTIFICATE----- -MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcT -BkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0 -aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNl -YXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAx -MTIxWjCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMg -QWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNV -BAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIw -MTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDC+Kk/G4n8PDwEXT2QNrCROnk8Zlrv -bTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+eh -iGsxr/CL0BgzuNtFajT0AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+ -6PAQZe104S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06CojXd -FPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV9Cz82XBST3i4vTwr -i5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrDgfgXy5I2XdGj2HUb4Ysn6npIQf1F -GQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2 -fu/Z8VFRfS0myGlZYeCsargqNhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9mu -iNX6hME6wGkoLfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc -Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD -AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVdctA4GGqd83EkVAswDQYJKoZI -hvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0IXtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+ -D1hYc2Ryx+hFjtyp8iY/xnmMsVMIM4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrM -d/K4kPFox/la/vot9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+y -d+2VZ5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/eaj8GsGsVn -82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnhX9izjFk0WaSrT2y7Hxjb -davYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQl033DlZdwJVqwjbDG2jJ9SrcR5q+ss7F -Jej6A7na+RZukYT1HCjI/CbM1xyQVqdfbzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVt -J94Cj8rDtSvK6evIIVM4pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGa -JI7ZjnHKe7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0vm9q -p/UsQu0yrbYhnr68 ------END CERTIFICATE----- - -Hellenic Academic and Research Institutions ECC RootCA 2015 -=========================================================== ------BEGIN CERTIFICATE----- -MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0 -aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9u -cyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJj -aCBJbnN0aXR1dGlvbnMgRUNDIFJvb3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEw -MzcxMlowgaoxCzAJBgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmlj -IEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUQwQgYD -VQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIEVDQyBSb290 -Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKgQehLgoRc4vgxEZmGZE4JJS+dQS8KrjVP -dJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJajq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoK -Vlp8aQuqgAkkbH7BRqNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O -BBYEFLQiC4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaeplSTA -GiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7SofTUwJCA3sS61kFyjn -dc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR ------END CERTIFICATE----- - -Certplus Root CA G1 -=================== ------BEGIN CERTIFICATE----- -MIIFazCCA1OgAwIBAgISESBVg+QtPlRWhS2DN7cs3EYRMA0GCSqGSIb3DQEBDQUAMD4xCzAJBgNV -BAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBsdXMgUm9vdCBDQSBHMTAe -Fw0xNDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBaMD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhD -ZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBsdXMgUm9vdCBDQSBHMTCCAiIwDQYJKoZIhvcNAQEBBQAD -ggIPADCCAgoCggIBANpQh7bauKk+nWT6VjOaVj0W5QOVsjQcmm1iBdTYj+eJZJ+622SLZOZ5KmHN -r49aiZFluVj8tANfkT8tEBXgfs+8/H9DZ6itXjYj2JizTfNDnjl8KvzsiNWI7nC9hRYt6kuJPKNx -Qv4c/dMcLRC4hlTqQ7jbxofaqK6AJc96Jh2qkbBIb6613p7Y1/oA/caP0FG7Yn2ksYyy/yARujVj -BYZHYEMzkPZHogNPlk2dT8Hq6pyi/jQu3rfKG3akt62f6ajUeD94/vI4CTYd0hYCyOwqaK/1jpTv -LRN6HkJKHRUxrgwEV/xhc/MxVoYxgKDEEW4wduOU8F8ExKyHcomYxZ3MVwia9Az8fXoFOvpHgDm2 -z4QTd28n6v+WZxcIbekN1iNQMLAVdBM+5S//Ds3EC0pd8NgAM0lm66EYfFkuPSi5YXHLtaW6uOrc -4nBvCGrch2c0798wct3zyT8j/zXhviEpIDCB5BmlIOklynMxdCm+4kLV87ImZsdo/Rmz5yCTmehd -4F6H50boJZwKKSTUzViGUkAksnsPmBIgJPaQbEfIDbsYIC7Z/fyL8inqh3SV4EJQeIQEQWGw9CEj -jy3LKCHyamz0GqbFFLQ3ZU+V/YDI+HLlJWvEYLF7bY5KinPOWftwenMGE9nTdDckQQoRb5fc5+R+ -ob0V8rqHDz1oihYHAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0G -A1UdDgQWBBSowcCbkahDFXxdBie0KlHYlwuBsTAfBgNVHSMEGDAWgBSowcCbkahDFXxdBie0KlHY -lwuBsTANBgkqhkiG9w0BAQ0FAAOCAgEAnFZvAX7RvUz1isbwJh/k4DgYzDLDKTudQSk0YcbX8ACh -66Ryj5QXvBMsdbRX7gp8CXrc1cqh0DQT+Hern+X+2B50ioUHj3/MeXrKls3N/U/7/SMNkPX0XtPG -YX2eEeAC7gkE2Qfdpoq3DIMku4NQkv5gdRE+2J2winq14J2by5BSS7CTKtQ+FjPlnsZlFT5kOwQ/ -2wyPX1wdaR+v8+khjPPvl/aatxm2hHSco1S1cE5j2FddUyGbQJJD+tZ3VTNPZNX70Cxqjm0lpu+F -6ALEUz65noe8zDUa3qHpimOHZR4RKttjd5cUvpoUmRGywO6wT/gUITJDT5+rosuoD6o7BlXGEilX -CNQ314cnrUlZp5GrRHpejXDbl85IULFzk/bwg2D5zfHhMf1bfHEhYxQUqq/F3pN+aLHsIqKqkHWe -tUNy6mSjhEv9DKgma3GX7lZjZuhCVPnHHd/Qj1vfyDBviP4NxDMcU6ij/UgQ8uQKTuEVV/xuZDDC -VRHc6qnNSlSsKWNEz0pAoNZoWRsz+e86i9sgktxChL8Bq4fA1SCC28a5g4VCXA9DO2pJNdWY9BW/ -+mGBDAkgGNLQFwzLSABQ6XaCjGTXOqAHVcweMcDvOrRl++O/QmueD6i9a5jc2NvLi6Td11n0bt3+ -qsOR0C5CB8AMTVPNJLFMWx5R9N/pkvo= ------END CERTIFICATE----- - -Certplus Root CA G2 -=================== ------BEGIN CERTIFICATE----- -MIICHDCCAaKgAwIBAgISESDZkc6uo+jF5//pAq/Pc7xVMAoGCCqGSM49BAMDMD4xCzAJBgNVBAYT -AkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBsdXMgUm9vdCBDQSBHMjAeFw0x -NDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBaMD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0 -cGx1czEcMBoGA1UEAwwTQ2VydHBsdXMgUm9vdCBDQSBHMjB2MBAGByqGSM49AgEGBSuBBAAiA2IA -BM0PW1aC3/BFGtat93nwHcmsltaeTpwftEIRyoa/bfuFo8XlGVzX7qY/aWfYeOKmycTbLXku54uN -Am8xIk0G42ByRZ0OQneezs/lf4WbGOT8zC5y0xaTTsqZY1yhBSpsBqNjMGEwDgYDVR0PAQH/BAQD -AgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNqDYwJ5jtpMxjwjFNiPwyCrKGBZMB8GA1Ud -IwQYMBaAFNqDYwJ5jtpMxjwjFNiPwyCrKGBZMAoGCCqGSM49BAMDA2gAMGUCMHD+sAvZ94OX7PNV -HdTcswYO/jOYnYs5kGuUIe22113WTNchp+e/IQ8rzfcq3IUHnQIxAIYUFuXcsGXCwI4Un78kFmjl -vPl5adytRSv3tjFzzAalU5ORGpOucGpnutee5WEaXw== ------END CERTIFICATE----- - -OpenTrust Root CA G1 -==================== ------BEGIN CERTIFICATE----- -MIIFbzCCA1egAwIBAgISESCzkFU5fX82bWTCp59rY45nMA0GCSqGSIb3DQEBCwUAMEAxCzAJBgNV -BAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5UcnVzdCBSb290IENBIEcx -MB4XDTE0MDUyNjA4NDU1MFoXDTM4MDExNTAwMDAwMFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoM -CU9wZW5UcnVzdDEdMBsGA1UEAwwUT3BlblRydXN0IFJvb3QgQ0EgRzEwggIiMA0GCSqGSIb3DQEB -AQUAA4ICDwAwggIKAoICAQD4eUbalsUwXopxAy1wpLuwxQjczeY1wICkES3d5oeuXT2R0odsN7fa -Yp6bwiTXj/HbpqbfRm9RpnHLPhsxZ2L3EVs0J9V5ToybWL0iEA1cJwzdMOWo010hOHQX/uMftk87 -ay3bfWAfjH1MBcLrARYVmBSO0ZB3Ij/swjm4eTrwSSTilZHcYTSSjFR077F9jAHiOH3BX2pfJLKO -YheteSCtqx234LSWSE9mQxAGFiQD4eCcjsZGT44ameGPuY4zbGneWK2gDqdkVBFpRGZPTBKnjix9 -xNRbxQA0MMHZmf4yzgeEtE7NCv82TWLxp2NX5Ntqp66/K7nJ5rInieV+mhxNaMbBGN4zK1FGSxyO -9z0M+Yo0FMT7MzUj8czxKselu7Cizv5Ta01BG2Yospb6p64KTrk5M0ScdMGTHPjgniQlQ/GbI4Kq -3ywgsNw2TgOzfALU5nsaqocTvz6hdLubDuHAk5/XpGbKuxs74zD0M1mKB3IDVedzagMxbm+WG+Oi -n6+Sx+31QrclTDsTBM8clq8cIqPQqwWyTBIjUtz9GVsnnB47ev1CI9sjgBPwvFEVVJSmdz7QdFG9 -URQIOTfLHzSpMJ1ShC5VkLG631UAC9hWLbFJSXKAqWLXwPYYEQRVzXR7z2FwefR7LFxckvzluFqr -TJOVoSfupb7PcSNCupt2LQIDAQABo2MwYTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB -/zAdBgNVHQ4EFgQUl0YhVyE12jZVx/PxN3DlCPaTKbYwHwYDVR0jBBgwFoAUl0YhVyE12jZVx/Px -N3DlCPaTKbYwDQYJKoZIhvcNAQELBQADggIBAB3dAmB84DWn5ph76kTOZ0BP8pNuZtQ5iSas000E -PLuHIT839HEl2ku6q5aCgZG27dmxpGWX4m9kWaSW7mDKHyP7Rbr/jyTwyqkxf3kfgLMtMrpkZ2Cv -uVnN35pJ06iCsfmYlIrM4LvgBBuZYLFGZdwIorJGnkSI6pN+VxbSFXJfLkur1J1juONI5f6ELlgK -n0Md/rcYkoZDSw6cMoYsYPXpSOqV7XAp8dUv/TW0V8/bhUiZucJvbI/NeJWsZCj9VrDDb8O+WVLh -X4SPgPL0DTatdrOjteFkdjpY3H1PXlZs5VVZV6Xf8YpmMIzUUmI4d7S+KNfKNsSbBfD4Fdvb8e80 -nR14SohWZ25g/4/Ii+GOvUKpMwpZQhISKvqxnUOOBZuZ2mKtVzazHbYNeS2WuOvyDEsMpZTGMKcm -GS3tTAZQMPH9WD25SxdfGbRqhFS0OE85og2WaMMolP3tLR9Ka0OWLpABEPs4poEL0L9109S5zvE/ -bw4cHjdx5RiHdRk/ULlepEU0rbDK5uUTdg8xFKmOLZTW1YVNcxVPS/KyPu1svf0OnWZzsD2097+o -4BGkxK51CUpjAEggpsadCwmKtODmzj7HPiY46SvepghJAwSQiumPv+i2tCqjI40cHLI5kqiPAlxA -OXXUc0ECd97N4EOH1uS6SsNsEn/+KuYj1oxx ------END CERTIFICATE----- - -OpenTrust Root CA G2 -==================== ------BEGIN CERTIFICATE----- -MIIFbzCCA1egAwIBAgISESChaRu/vbm9UpaPI+hIvyYRMA0GCSqGSIb3DQEBDQUAMEAxCzAJBgNV -BAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5UcnVzdCBSb290IENBIEcy -MB4XDTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAwMFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoM -CU9wZW5UcnVzdDEdMBsGA1UEAwwUT3BlblRydXN0IFJvb3QgQ0EgRzIwggIiMA0GCSqGSIb3DQEB -AQUAA4ICDwAwggIKAoICAQDMtlelM5QQgTJT32F+D3Y5z1zCU3UdSXqWON2ic2rxb95eolq5cSG+ -Ntmh/LzubKh8NBpxGuga2F8ORAbtp+Dz0mEL4DKiltE48MLaARf85KxP6O6JHnSrT78eCbY2albz -4e6WiWYkBuTNQjpK3eCasMSCRbP+yatcfD7J6xcvDH1urqWPyKwlCm/61UWY0jUJ9gNDlP7ZvyCV -eYCYitmJNbtRG6Q3ffyZO6v/v6wNj0OxmXsWEH4db0fEFY8ElggGQgT4hNYdvJGmQr5J1WqIP7wt -UdGejeBSzFfdNTVY27SPJIjki9/ca1TSgSuyzpJLHB9G+h3Ykst2Z7UJmQnlrBcUVXDGPKBWCgOz -3GIZ38i1MH/1PCZ1Eb3XG7OHngevZXHloM8apwkQHZOJZlvoPGIytbU6bumFAYueQ4xncyhZW+vj -3CzMpSZyYhK05pyDRPZRpOLAeiRXyg6lPzq1O4vldu5w5pLeFlwoW5cZJ5L+epJUzpM5ChaHvGOz -9bGTXOBut9Dq+WIyiET7vycotjCVXRIouZW+j1MY5aIYFuJWpLIsEPUdN6b4t/bQWVyJ98LVtZR0 -0dX+G7bw5tYee9I8y6jj9RjzIR9u701oBnstXW5DiabA+aC/gh7PU3+06yzbXfZqfUAkBXKJOAGT -y3HCOV0GEfZvePg3DTmEJwIDAQABo2MwYTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB -/zAdBgNVHQ4EFgQUajn6QiL35okATV59M4PLuG53hq8wHwYDVR0jBBgwFoAUajn6QiL35okATV59 -M4PLuG53hq8wDQYJKoZIhvcNAQENBQADggIBAJjLq0A85TMCl38th6aP1F5Kr7ge57tx+4BkJamz -Gj5oXScmp7oq4fBXgwpkTx4idBvpkF/wrM//T2h6OKQQbA2xx6R3gBi2oihEdqc0nXGEL8pZ0keI -mUEiyTCYYW49qKgFbdEfwFFEVn8nNQLdXpgKQuswv42hm1GqO+qTRmTFAHneIWv2V6CG1wZy7HBG -S4tz3aAhdT7cHcCP009zHIXZ/n9iyJVvttN7jLpTwm+bREx50B1ws9efAvSyB7DH5fitIw6mVskp -EndI2S9G/Tvw/HRwkqWOOAgfZDC2t0v7NqwQjqBSM2OdAzVWxWm9xiNaJ5T2pBL4LTM8oValX9YZ -6e18CL13zSdkzJTaTkZQh+D5wVOAHrut+0dSixv9ovneDiK3PTNZbNTe9ZUGMg1RGUFcPk8G97kr -gCf2o6p6fAbhQ8MTOWIaNr3gKC6UAuQpLmBVrkA9sHSSXvAgZJY/X0VdiLWK2gKgW0VU3jg9CcCo -SmVGFvyqv1ROTVu+OEO3KMqLM6oaJbolXCkvW0pujOotnCr2BXbgd5eAiN1nE28daCSLT7d0geX0 -YJ96Vdc+N9oWaz53rK4YcJUIeSkDiv7BO7M/Gg+kO14fWKGVyasvc0rQLW6aWQ9VGHgtPFGml4vm -u7JwqkwR3v98KzfUetF3NI/n+UL3PIEMS1IK ------END CERTIFICATE----- - -OpenTrust Root CA G3 -==================== ------BEGIN CERTIFICATE----- -MIICITCCAaagAwIBAgISESDm+Ez8JLC+BUCs2oMbNGA/MAoGCCqGSM49BAMDMEAxCzAJBgNVBAYT -AkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5UcnVzdCBSb290IENBIEczMB4X -DTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAwMFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9w -ZW5UcnVzdDEdMBsGA1UEAwwUT3BlblRydXN0IFJvb3QgQ0EgRzMwdjAQBgcqhkjOPQIBBgUrgQQA -IgNiAARK7liuTcpm3gY6oxH84Bjwbhy6LTAMidnW7ptzg6kjFYwvWYpa3RTqnVkrQ7cG7DK2uu5B -ta1doYXM6h0UZqNnfkbilPPntlahFVmhTzeXuSIevRHr9LIfXsMUmuXZl5mjYzBhMA4GA1UdDwEB -/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRHd8MUi2I5DMlv4VBN0BBY3JWIbTAf -BgNVHSMEGDAWgBRHd8MUi2I5DMlv4VBN0BBY3JWIbTAKBggqhkjOPQQDAwNpADBmAjEAj6jcnboM -BBf6Fek9LykBl7+BFjNAk2z8+e2AcG+qj9uEwov1NcoG3GRvaBbhj5G5AjEA2Euly8LQCGzpGPta -3U1fJAuwACEl74+nBCZx4nxp5V2a+EEfOzmTk51V6s2N8fvB ------END CERTIFICATE----- - -ISRG Root X1 -============ ------BEGIN CERTIFICATE----- -MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAwTzELMAkGA1UE -BhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2VhcmNoIEdyb3VwMRUwEwYDVQQD -EwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQG -EwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMT -DElTUkcgUm9vdCBYMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54r -Vygch77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+0TM8ukj1 -3Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6UA5/TR5d8mUgjU+g4rk8K -b4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sWT8KOEUt+zwvo/7V3LvSye0rgTBIlDHCN -Aymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyHB5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ -4Q7e2RCOFvu396j3x+UCB5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf -1b0SHzUvKBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWnOlFu -hjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTnjh8BCNAw1FtxNrQH -usEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbwqHyGO0aoSCqI3Haadr8faqU9GY/r -OPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CIrU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4G -A1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY -9umbbjANBgkqhkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL -ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ3BebYhtF8GaV -0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KKNFtY2PwByVS5uCbMiogziUwt -hDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJw -TdwJx4nLCgdNbOhdjsnvzqvHu7UrTkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nx -e5AW0wdeRlN8NwdCjNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZA -JzVcoyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq4RgqsahD -YVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPAmRGunUHBcnWEvgJBQl9n -JEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57demyPxgcYxn/eR44/KJ4EBs+lVDR3veyJ -m+kXQ99b21/+jh5Xos1AnX5iItreGCc= ------END CERTIFICATE----- - -AC RAIZ FNMT-RCM -================ ------BEGIN CERTIFICATE----- -MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNVBAYT -AkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTAeFw0wODEw -MjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJD -TTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC -ggIBALpxgHpMhm5/yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcf -qQgfBBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAzWHFctPVr -btQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxFtBDXaEAUwED653cXeuYL -j2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z374jNUUeAlz+taibmSXaXvMiwzn15Cou -08YfxGyqxRxqAQVKL9LFwag0Jl1mpdICIfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mw -WsXmo8RZZUc1g16p6DULmbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnT -tOmlcYF7wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peSMKGJ -47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2ZSysV4999AeU14EC -ll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMetUqIJ5G+GR4of6ygnXYMgrwTJbFaa -i0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE -FPd9xf3E6Jobd2Sn9R2gzL+HYJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1o -dHRwOi8vd3d3LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD -nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1RXxlDPiyN8+s -D8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYMLVN0V2Ue1bLdI4E7pWYjJ2cJ -j+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrT -Qfv6MooqtyuGC2mDOL7Nii4LcK2NJpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW -+YJF1DngoABd15jmfZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7 -Ixjp6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp1txyM/1d -8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B9kiABdcPUXmsEKvU7ANm -5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wokRqEIr9baRRmW1FMdW4R58MD3R++Lj8UG -rp1MYp3/RgT408m2ECVAdf4WqslKYIYvuu8wd+RU4riEmViAqhOLUTpPSPaLtrM= ------END CERTIFICATE----- - -Amazon Root CA 1 -================ ------BEGIN CERTIFICATE----- -MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsFADA5MQswCQYD -VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAxMB4XDTE1 -MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv -bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBALJ4gHHKeNXjca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgH -FzZM9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qwIFAGbHrQ -gLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6VOujw5H5SNz/0egwLX0t -dHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L93FcXmn/6pUCyziKrlA4b9v7LWIbxcce -VOF34GfID5yHI9Y/QCB/IIDEgEw+OyQmjgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB -/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3 -DQEBCwUAA4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDIU5PM -CCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUsN+gDS63pYaACbvXy -8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vvo/ufQJVtMVT8QtPHRh8jrdkPSHCa -2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2 -xJNDd2ZhwLnoQdeXeGADbkpyrqXRfboQnoZsG4q5WTP468SQvvG5 ------END CERTIFICATE----- - -Amazon Root CA 2 -================ ------BEGIN CERTIFICATE----- -MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwFADA5MQswCQYD -VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAyMB4XDTE1 -MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv -bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC -ggIBAK2Wny2cSkxKgXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4 -kHbZW0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg1dKmSYXp -N+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K8nu+NQWpEjTj82R0Yiw9 -AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvd -fLC6HM783k81ds8P+HgfajZRRidhW+mez/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAEx -kv8LV/SasrlX6avvDXbR8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSS -btqDT6ZjmUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz7Mt0 -Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6+XUyo05f7O0oYtlN -c/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI0u1ufm8/0i2BWSlmy5A5lREedCf+ -3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSw -DPBMMPQFWAJI/TPlUq9LhONmUjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oA -A7CXDpO8Wqj2LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY -+gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kSk5Nrp+gvU5LE -YFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl7uxMMne0nxrpS10gxdr9HIcW -xkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygmbtmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQ -gj9sAq+uEjonljYE1x2igGOpm/HlurR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbW -aQbLU8uz/mtBzUF+fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoV -Yh63n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE76KlXIx3 -KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H9jVlpNMKVv/1F2Rs76gi -JUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT4PsJYGw= ------END CERTIFICATE----- - -Amazon Root CA 3 -================ ------BEGIN CERTIFICATE----- -MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5MQswCQYDVQQG -EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAzMB4XDTE1MDUy -NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ -MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZB -f8ANm+gBG1bG8lKlui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjr -Zt6jQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSrttvXBp43 -rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkrBqWTrBqYaGFy+uGh0Psc -eGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteMYyRIHN8wfdVoOw== ------END CERTIFICATE----- - -Amazon Root CA 4 -================ ------BEGIN CERTIFICATE----- -MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5MQswCQYDVQQG -EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSA0MB4XDTE1MDUy -NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ -MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN -/sGKe0uoe0ZLY7Bi9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri -83BkM6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV -HQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WBMAoGCCqGSM49BAMDA2gA -MGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlwCkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1 -AE47xDqUEpHJWEadIRNyp4iciuRMStuW1KyLa2tJElMzrdfkviT8tQp21KW8EA== ------END CERTIFICATE----- - -LuxTrust Global Root 2 -====================== ------BEGIN CERTIFICATE----- -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 ------END CERTIFICATE----- - -TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1 -============================================= ------BEGIN CERTIFICATE----- -MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIxGDAWBgNVBAcT -D0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxpbXNlbCB2ZSBUZWtub2xvamlr -IEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0wKwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24g -TWVya2V6aSAtIEthbXUgU00xNjA0BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRp -ZmlrYXNpIC0gU3VydW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYD -VQQGEwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXllIEJpbGlt -c2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklUQUsxLTArBgNVBAsTJEth -bXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBTTTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11 -IFNNIFNTTCBLb2sgU2VydGlmaWthc2kgLSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A -MIIBCgKCAQEAr3UwM6q7a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y8 -6Ij5iySrLqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INrN3wc -wv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2XYacQuFWQfw4tJzh0 -3+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/iSIzL+aFCr2lqBs23tPcLG07xxO9 -WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4fAJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQU -ZT/HiobGPN08VFw1+DrtUgxHV8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJ -KoZIhvcNAQELBQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh -AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPfIPP54+M638yc -lNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4lzwDGrpDxpa5RXI4s6ehlj2R -e37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0j -q5Rm+K37DwhuJi1/FwcJsoz7UMCflo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM= ------END CERTIFICATE----- - -GDCA TrustAUTH R5 ROOT -====================== ------BEGIN CERTIFICATE----- -MIIFiDCCA3CgAwIBAgIIfQmX/vBH6nowDQYJKoZIhvcNAQELBQAwYjELMAkGA1UEBhMCQ04xMjAw -BgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZIENPLixMVEQuMR8wHQYDVQQD -DBZHRENBIFRydXN0QVVUSCBSNSBST09UMB4XDTE0MTEyNjA1MTMxNVoXDTQwMTIzMTE1NTk1OVow -YjELMAkGA1UEBhMCQ04xMjAwBgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZ -IENPLixMVEQuMR8wHQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMIICIjANBgkqhkiG9w0B -AQEFAAOCAg8AMIICCgKCAgEA2aMW8Mh0dHeb7zMNOwZ+Vfy1YI92hhJCfVZmPoiC7XJjDp6L3TQs -AlFRwxn9WVSEyfFrs0yw6ehGXTjGoqcuEVe6ghWinI9tsJlKCvLriXBjTnnEt1u9ol2x8kECK62p -OqPseQrsXzrj/e+APK00mxqriCZ7VqKChh/rNYmDf1+uKU49tm7srsHwJ5uu4/Ts765/94Y9cnrr -pftZTqfrlYwiOXnhLQiPzLyRuEH3FMEjqcOtmkVEs7LXLM3GKeJQEK5cy4KOFxg2fZfmiJqwTTQJ -9Cy5WmYqsBebnh52nUpmMUHfP/vFBu8btn4aRjb3ZGM74zkYI+dndRTVdVeSN72+ahsmUPI2JgaQ -xXABZG12ZuGR224HwGGALrIuL4xwp9E7PLOR5G62xDtw8mySlwnNR30YwPO7ng/Wi64HtloPzgsM -R6flPri9fcebNaBhlzpBdRfMK5Z3KpIhHtmVdiBnaM8Nvd/WHwlqmuLMc3GkL30SgLdTMEZeS1SZ -D2fJpcjyIMGC7J0R38IC+xo70e0gmu9lZJIQDSri3nDxGGeCjGHeuLzRL5z7D9Ar7Rt2ueQ5Vfj4 -oR24qoAATILnsn8JuLwwoC8N9VKejveSswoAHQBUlwbgsQfZxw9cZX08bVlX5O2ljelAU58VS6Bx -9hoh49pwBiFYFIeFd3mqgnkCAwEAAaNCMEAwHQYDVR0OBBYEFOLJQJ9NzuiaoXzPDj9lxSmIahlR -MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQDRSVfg -p8xoWLoBDysZzY2wYUWsEe1jUGn4H3++Fo/9nesLqjJHdtJnJO29fDMylyrHBYZmDRd9FBUb1Ov9 -H5r2XpdptxolpAqzkT9fNqyL7FeoPueBihhXOYV0GkLH6VsTX4/5COmSdI31R9KrO9b7eGZONn35 -6ZLpBN79SWP8bfsUcZNnL0dKt7n/HipzcEYwv1ryL3ml4Y0M2fmyYzeMN2WFcGpcWwlyua1jPLHd -+PwyvzeG5LuOmCd+uh8W4XAR8gPfJWIyJyYYMoSf/wA6E7qaTfRPuBRwIrHKK5DOKcFw9C+df/KQ -HtZa37dG/OaG+svgIHZ6uqbL9XzeYqWxi+7egmaKTjowHz+Ay60nugxe19CxVsp3cbK1daFQqUBD -F8Io2c9Si1vIY9RCPqAzekYu9wogRlR+ak8x8YF+QnQ4ZXMn7sZ8uI7XpTrXmKGcjBBV09tL7ECQ -8s1uV9JiDnxXk7Gnbc2dg7sq5+W2O3FYrf3RRbxake5TFW/TRQl1brqQXR4EzzffHqhmsYzmIGrv -/EhOdJhCrylvLmrH+33RZjEizIYAfmaDDEL0vTSSwxrqT8p+ck0LcIymSLumoRT2+1hEmRSuqguT -aaApJUqlyyvdimYHFngVV3Eb7PVHhPOeMTd61X8kreS8/f3MboPoDKi3QWwH3b08hpcv0g== ------END CERTIFICATE----- - -TrustCor RootCert CA-1 -====================== ------BEGIN CERTIFICATE----- -MIIEMDCCAxigAwIBAgIJANqb7HHzA7AZMA0GCSqGSIb3DQEBCwUAMIGkMQswCQYDVQQGEwJQQTEP -MA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3Ig -U3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3Jp -dHkxHzAdBgNVBAMMFlRydXN0Q29yIFJvb3RDZXJ0IENBLTEwHhcNMTYwMjA0MTIzMjE2WhcNMjkx -MjMxMTcyMzE2WjCBpDELMAkGA1UEBhMCUEExDzANBgNVBAgMBlBhbmFtYTEUMBIGA1UEBwwLUGFu -YW1hIENpdHkxJDAiBgNVBAoMG1RydXN0Q29yIFN5c3RlbXMgUy4gZGUgUi5MLjEnMCUGA1UECwwe -VHJ1c3RDb3IgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MR8wHQYDVQQDDBZUcnVzdENvciBSb290Q2Vy -dCBDQS0xMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv463leLCJhJrMxnHQFgKq1mq -jQCj/IDHUHuO1CAmujIS2CNUSSUQIpidRtLByZ5OGy4sDjjzGiVoHKZaBeYei0i/mJZ0PmnK6bV4 -pQa81QBeCQryJ3pS/C3Vseq0iWEk8xoT26nPUu0MJLq5nux+AHT6k61sKZKuUbS701e/s/OojZz0 -JEsq1pme9J7+wH5COucLlVPat2gOkEz7cD+PSiyU8ybdY2mplNgQTsVHCJCZGxdNuWxu72CVEY4h -gLW9oHPY0LJ3xEXqWib7ZnZ2+AYfYW0PVcWDtxBWcgYHpfOxGgMFZA6dWorWhnAbJN7+KIor0Gqw -/Hqi3LJ5DotlDwIDAQABo2MwYTAdBgNVHQ4EFgQU7mtJPHo/DeOxCbeKyKsZn3MzUOcwHwYDVR0j -BBgwFoAU7mtJPHo/DeOxCbeKyKsZn3MzUOcwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC -AYYwDQYJKoZIhvcNAQELBQADggEBACUY1JGPE+6PHh0RU9otRCkZoB5rMZ5NDp6tPVxBb5UrJKF5 -mDo4Nvu7Zp5I/5CQ7z3UuJu0h3U/IJvOcs+hVcFNZKIZBqEHMwwLKeXx6quj7LUKdJDHfXLy11yf -ke+Ri7fc7Waiz45mO7yfOgLgJ90WmMCV1Aqk5IGadZQ1nJBfiDcGrVmVCrDRZ9MZyonnMlo2HD6C -qFqTvsbQZJG2z9m2GM/bftJlo6bEjhcxwft+dtvTheNYsnd6djtsL1Ac59v2Z3kf9YKVmgenFK+P -3CghZwnS1k1aHBkcjndcw5QkPTJrS37UeJSDvjdNzl/HHk484IkzlQsPpTLWPFp5LBk= ------END CERTIFICATE----- - -TrustCor RootCert CA-2 -====================== ------BEGIN CERTIFICATE----- -MIIGLzCCBBegAwIBAgIIJaHfyjPLWQIwDQYJKoZIhvcNAQELBQAwgaQxCzAJBgNVBAYTAlBBMQ8w -DQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5MSQwIgYDVQQKDBtUcnVzdENvciBT -eXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRydXN0Q29yIENlcnRpZmljYXRlIEF1dGhvcml0 -eTEfMB0GA1UEAwwWVHJ1c3RDb3IgUm9vdENlcnQgQ0EtMjAeFw0xNjAyMDQxMjMyMjNaFw0zNDEy -MzExNzI2MzlaMIGkMQswCQYDVQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5h -bWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5U -cnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRydXN0Q29yIFJvb3RDZXJ0 -IENBLTIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCnIG7CKqJiJJWQdsg4foDSq8Gb -ZQWU9MEKENUCrO2fk8eHyLAnK0IMPQo+QVqedd2NyuCb7GgypGmSaIwLgQ5WoD4a3SwlFIIvl9Nk -RvRUqdw6VC0xK5mC8tkq1+9xALgxpL56JAfDQiDyitSSBBtlVkxs1Pu2YVpHI7TYabS3OtB0PAx1 -oYxOdqHp2yqlO/rOsP9+aij9JxzIsekp8VduZLTQwRVtDr4uDkbIXvRR/u8OYzo7cbrPb1nKDOOb -XUm4TOJXsZiKQlecdu/vvdFoqNL0Cbt3Nb4lggjEFixEIFapRBF37120Hapeaz6LMvYHL1cEksr1 -/p3C6eizjkxLAjHZ5DxIgif3GIJ2SDpxsROhOdUuxTTCHWKF3wP+TfSvPd9cW436cOGlfifHhi5q -jxLGhF5DUVCcGZt45vz27Ud+ez1m7xMTiF88oWP7+ayHNZ/zgp6kPwqcMWmLmaSISo5uZk3vFsQP -eSghYA2FFn3XVDjxklb9tTNMg9zXEJ9L/cb4Qr26fHMC4P99zVvh1Kxhe1fVSntb1IVYJ12/+Ctg -rKAmrhQhJ8Z3mjOAPF5GP/fDsaOGM8boXg25NSyqRsGFAnWAoOsk+xWq5Gd/bnc/9ASKL3x74xdh -8N0JqSDIvgmk0H5Ew7IwSjiqqewYmgeCK9u4nBit2uBGF6zPXQIDAQABo2MwYTAdBgNVHQ4EFgQU -2f4hQG6UnrybPZx9mCAZ5YwwYrIwHwYDVR0jBBgwFoAU2f4hQG6UnrybPZx9mCAZ5YwwYrIwDwYD -VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggIBAJ5Fngw7tu/h -Osh80QA9z+LqBrWyOrsGS2h60COXdKcs8AjYeVrXWoSK2BKaG9l9XE1wxaX5q+WjiYndAfrs3fnp -kpfbsEZC89NiqpX+MWcUaViQCqoL7jcjx1BRtPV+nuN79+TMQjItSQzL/0kMmx40/W5ulop5A7Zv -2wnL/V9lFDfhOPXzYRZY5LVtDQsEGz9QLX+zx3oaFoBg+Iof6Rsqxvm6ARppv9JYx1RXCI/hOWB3 -S6xZhBqI8d3LT3jX5+EzLfzuQfogsL7L9ziUwOHQhQ+77Sxzq+3+knYaZH9bDTMJBzN7Bj8RpFxw -PIXAz+OQqIN3+tvmxYxoZxBnpVIt8MSZj3+/0WvitUfW2dCFmU2Umw9Lje4AWkcdEQOsQRivh7dv -DDqPys/cA8GiCcjl/YBeyGBCARsaU1q7N6a3vLqE6R5sGtRk2tRD/pOLS/IseRYQ1JMLiI+h2IYU -RpFHmygk71dSTlxCnKr3Sewn6EAes6aJInKc9Q0ztFijMDvd1GpUk74aTfOTlPf8hAs/hCBcNANE -xdqtvArBAs8e5ZTZ845b2EzwnexhF7sUMlQMAimTHpKG9n/v55IFDlndmQguLvqcAFLTxWYp5KeX -RKQOKIETNcX2b2TmQcTVL8w0RSXPQQCWPUouwpaYT05KnJe32x+SMsj/D1Fu1uwJ ------END CERTIFICATE----- - -TrustCor ECA-1 -============== ------BEGIN CERTIFICATE----- -MIIEIDCCAwigAwIBAgIJAISCLF8cYtBAMA0GCSqGSIb3DQEBCwUAMIGcMQswCQYDVQQGEwJQQTEP -MA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEkMCIGA1UECgwbVHJ1c3RDb3Ig -U3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3Jp -dHkxFzAVBgNVBAMMDlRydXN0Q29yIEVDQS0xMB4XDTE2MDIwNDEyMzIzM1oXDTI5MTIzMTE3Mjgw -N1owgZwxCzAJBgNVBAYTAlBBMQ8wDQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5 -MSQwIgYDVQQKDBtUcnVzdENvciBTeXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRydXN0Q29y -IENlcnRpZmljYXRlIEF1dGhvcml0eTEXMBUGA1UEAwwOVHJ1c3RDb3IgRUNBLTEwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPj+ARtZ+odnbb3w9U73NjKYKtR8aja+3+XzP4Q1HpGjOR -MRegdMTUpwHmspI+ap3tDvl0mEDTPwOABoJA6LHip1GnHYMma6ve+heRK9jGrB6xnhkB1Zem6g23 -xFUfJ3zSCNV2HykVh0A53ThFEXXQmqc04L/NyFIduUd+Dbi7xgz2c1cWWn5DkR9VOsZtRASqnKmc -p0yJF4OuowReUoCLHhIlERnXDH19MURB6tuvsBzvgdAsxZohmz3tQjtQJvLsznFhBmIhVE5/wZ0+ -fyCMgMsq2JdiyIMzkX2woloPV+g7zPIlstR8L+xNxqE6FXrntl019fZISjZFZtS6mFjBAgMBAAGj -YzBhMB0GA1UdDgQWBBREnkj1zG1I1KBLf/5ZJC+Dl5mahjAfBgNVHSMEGDAWgBREnkj1zG1I1KBL -f/5ZJC+Dl5mahjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsF -AAOCAQEABT41XBVwm8nHc2FvcivUwo/yQ10CzsSUuZQRg2dd4mdsdXa/uwyqNsatR5Nj3B5+1t4u -/ukZMjgDfxT2AHMsWbEhBuH7rBiVDKP/mZb3Kyeb1STMHd3BOuCYRLDE5D53sXOpZCz2HAF8P11F -hcCF5yWPldwX8zyfGm6wyuMdKulMY/okYWLW2n62HGz1Ah3UKt1VkOsqEUc8Ll50soIipX1TH0Xs -J5F95yIW6MBoNtjG8U+ARDL54dHRHareqKucBK+tIA5kmE2la8BIWJZpTdwHjFGTot+fDz2LYLSC -jaoITmJF4PkL0uDgPFveXHEnJcLmA4GLEFPjx1WitJ/X5g== ------END CERTIFICATE----- - -SSL.com Root Certification Authority RSA -======================================== ------BEGIN CERTIFICATE----- -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 -WuuA8ShYIc2wBlX7Jz9TkHCpBB5XJ7k= ------END CERTIFICATE----- - -SSL.com Root Certification Authority ECC -======================================== ------BEGIN CERTIFICATE----- -MIICjTCCAhSgAwIBAgIIdebfy8FoW6gwCgYIKoZIzj0EAwIwfDELMAkGA1UEBhMCVVMxDjAMBgNV -BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24xMTAv -BgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEy -MTgxNDAzWhcNNDEwMjEyMTgxNDAzWjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAO -BgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNv -bSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuBBAAiA2IA -BEVuqVDEpiM2nl8ojRfLliJkP9x6jh3MCLOicSS6jkm5BBtHllirLZXI7Z4INcgn64mMU1jrYor+ -8FsPazFSY0E7ic3s7LaNGdM0B9y7xgZ/wkWV7Mt/qCPgCemB+vNH06NjMGEwHQYDVR0OBBYEFILR -hXMw5zUE044CkvvlpNHEIejNMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUgtGFczDnNQTT -jgKS++Wk0cQh6M0wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2cAMGQCMG/n61kRpGDPYbCW -e+0F+S8Tkdzt5fxQaxFGRrMcIQBiu77D5+jNB5n5DQtdcj7EqgIwH7y6C+IwJPt8bYBVCpk+gA0z -5Wajs6O7pdWLjwkspl1+4vAHCGht0nxpbl/f5Wpl ------END CERTIFICATE----- - -SSL.com EV Root Certification Authority RSA R2 -============================================== ------BEGIN CERTIFICATE----- -MIIF6zCCA9OgAwIBAgIIVrYpzTS8ePYwDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNVBAYTAlVTMQ4w -DAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9u -MTcwNQYDVQQDDC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIy -MB4XDTE3MDUzMTE4MTQzN1oXDTQyMDUzMDE4MTQzN1owgYIxCzAJBgNVBAYTAlVTMQ4wDAYDVQQI -DAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTcwNQYD -VQQDDC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIyMIICIjAN -BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjzZlQOHWTcDXtOlG2mvqM0fNTPl9fb69LT3w23jh -hqXZuglXaO1XPqDQCEGD5yhBJB/jchXQARr7XnAjssufOePPxU7Gkm0mxnu7s9onnQqG6YE3Bf7w -cXHswxzpY6IXFJ3vG2fThVUCAtZJycxa4bH3bzKfydQ7iEGonL3Lq9ttewkfokxykNorCPzPPFTO -Zw+oz12WGQvE43LrrdF9HSfvkusQv1vrO6/PgN3B0pYEW3p+pKk8OHakYo6gOV7qd89dAFmPZiw+ -B6KjBSYRaZfqhbcPlgtLyEDhULouisv3D5oi53+aNxPN8k0TayHRwMwi8qFG9kRpnMphNQcAb9Zh -CBHqurj26bNg5U257J8UZslXWNvNh2n4ioYSA0e/ZhN2rHd9NCSFg83XqpyQGp8hLH94t2S42Oim -9HizVcuE0jLEeK6jj2HdzghTreyI/BXkmg3mnxp3zkyPuBQVPWKchjgGAGYS5Fl2WlPAApiiECto -RHuOec4zSnaqW4EWG7WK2NAAe15itAnWhmMOpgWVSbooi4iTsjQc2KRVbrcc0N6ZVTsj9CLg+Slm -JuwgUHfbSguPvuUCYHBBXtSuUDkiFCbLsjtzdFVHB3mBOagwE0TlBIqulhMlQg+5U8Sb/M3kHN48 -+qvWBkofZ6aYMBzdLNvcGJVXZsb/XItW9XcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNV -HSMEGDAWgBT5YLvU49U09rj1BoAlp3PbRmmonjAdBgNVHQ4EFgQU+WC71OPVNPa49QaAJadz20Zp -qJ4wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBWs47LCp1Jjr+kxJG7ZhcFUZh1 -++VQLHqe8RT6q9OKPv+RKY9ji9i0qVQBDb6Thi/5Sm3HXvVX+cpVHBK+Rw82xd9qt9t1wkclf7nx -Y/hoLVUE0fKNsKTPvDxeH3jnpaAgcLAExbf3cqfeIg29MyVGjGSSJuM+LmOW2puMPfgYCdcDzH2G -guDKBAdRUNf/ktUM79qGn5nX67evaOI5JpS6aLe/g9Pqemc9YmeuJeVy6OLk7K4S9ksrPJ/psEDz -OFSz/bdoyNrGj1E8svuR3Bznm53htw1yj+KkxKl4+esUrMZDBcJlOSgYAsOCsp0FvmXtll9ldDz7 -CTUue5wT/RsPXcdtgTpWD8w74a8CLyKsRspGPKAcTNZEtF4uXBVmCeEmKf7GUmG6sXP/wwyc5Wxq -lD8UykAWlYTzWamsX0xhk23RO8yilQwipmdnRC652dKKQbNmC1r7fSOl8hqw/96bg5Qu0T/fkreR -rwU7ZcegbLHNYhLDkBvjJc40vG93drEQw/cFGsDWr3RiSBd3kmmQYRzelYB0VI8YHMPzA9C/pEN1 -hlMYegouCRw2n5H9gooiS9EOUCXdywMMF8mDAAhONU2Ki+3wApRmLER/y5UnlhetCTCstnEXbosX -9hwJ1C07mKVx01QT2WDz9UtmT/rx7iASjbSsV7FFY6GsdqnC+w== ------END CERTIFICATE----- - -SSL.com EV Root Certification Authority ECC -=========================================== ------BEGIN CERTIFICATE----- -MIIClDCCAhqgAwIBAgIILCmcWxbtBZUwCgYIKoZIzj0EAwIwfzELMAkGA1UEBhMCVVMxDjAMBgNV -BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24xNDAy -BgNVBAMMK1NTTC5jb20gRVYgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYw -MjEyMTgxNTIzWhcNNDEwMjEyMTgxNTIzWjB/MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMx -EDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrU1NM -LmNvbSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuB -BAAiA2IABKoSR5CYG/vvw0AHgyBO8TCCogbR8pKGYfL2IWjKAMTH6kMAVIbc/R/fALhBYlzccBYy -3h+Z1MzFB8gIH2EWB1E9fVwHU+M1OIzfzZ/ZLg1KthkuWnBaBu2+8KGwytAJKaNjMGEwHQYDVR0O -BBYEFFvKXuXe0oGqzagtZFG22XKbl+ZPMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUW8pe -5d7SgarNqC1kUbbZcpuX5k8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2gAMGUCMQCK5kCJ -N+vp1RPZytRrJPOwPYdGWBrssd9v+1a6cGvHOMzosYxPD/fxZ3YOg9AeUY8CMD32IygmTMZgh5Mm -m7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg== ------END CERTIFICATE----- diff --git a/twitter/vendor/jublonet/codebird-php/src/codebird.php b/twitter/vendor/jublonet/codebird-php/src/codebird.php deleted file mode 100644 index 52018bde7..000000000 --- a/twitter/vendor/jublonet/codebird-php/src/codebird.php +++ /dev/null @@ -1,2720 +0,0 @@ - - * @copyright 2010-2018 Jublo Limited - * @license https://opensource.org/licenses/GPL-3.0 GNU General Public License 3.0 - * @link https://github.com/jublonet/codebird-php - */ - -/** - * Define constants - */ -$constants = explode(' ', 'OBJECT ARRAY JSON'); -foreach ($constants as $i => $id) { - $id = 'CODEBIRD_RETURNFORMAT_' . $id; - defined($id) or define($id, $i); -} -$constants = [ - 'CURLE_SSL_CERTPROBLEM' => 58, - 'CURLE_SSL_CACERT' => 60, - 'CURLE_SSL_CACERT_BADFILE' => 77, - 'CURLE_SSL_CRL_BADFILE' => 82, - 'CURLE_SSL_ISSUER_ERROR' => 83 -]; -foreach ($constants as $id => $i) { - defined($id) or define($id, $i); -} -unset($constants); -unset($i); -unset($id); - -/** - * A Twitter library in PHP. - * - * @package codebird - * @subpackage codebird-php - * @method bool curl_setopt (resource $ch, int $option, mixed $value) - */ -class Codebird -{ - /** - * The current singleton instance - */ - private static $_instance = null; - - /** - * The OAuth consumer key of your registered app - */ - protected static $_consumer_key = null; - - /** - * The corresponding consumer secret - */ - protected static $_consumer_secret = null; - - /** - * The app-only bearer token. Used to authorize app-only requests - */ - protected static $_bearer_token = null; - - /** - * The API endpoints to use - */ - protected static $_endpoints = [ - 'ads' => [ - 'production' => 'https://ads-api.twitter.com/2/', - 'sandbox' => 'https://ads-api-sandbox.twitter.com/2/' - ], - 'media' => 'https://upload.twitter.com/1.1/', - 'publish' => 'https://publish.twitter.com/', - 'oauth' => 'https://api.twitter.com/', - 'rest' => 'https://api.twitter.com/1.1/', - 'streaming' => [ - 'public' => 'https://stream.twitter.com/1.1/' - ], - 'ton' => 'https://ton.twitter.com/1.1/' - ]; - - /** - * Supported API methods - */ - protected static $_api_methods = [ - 'GET' => [ - 'account/settings', - 'account/verify_credentials', - 'account_activity/all/:env_name/subscriptions', - 'account_activity/all/:env_name/subscriptions/list', - 'account_activity/all/:env_name/webhooks', - 'account_activity/all/webhooks', - 'account_activity/subscriptions/count', - 'account_activity/webhooks', - 'account_activity/webhooks/:webhook_id/subscriptions/all', - 'account_activity/webhooks/:webhook_id/subscriptions/all/list', - 'ads/accounts', - 'ads/accounts/:account_id', - 'ads/accounts/:account_id/account_media', - 'ads/accounts/:account_id/app_event_provider_configurations', - 'ads/accounts/:account_id/app_event_provider_configurations/:id', - 'ads/accounts/:account_id/app_event_tags', - 'ads/accounts/:account_id/app_event_tags/:id', - 'ads/accounts/:account_id/app_lists', - 'ads/accounts/:account_id/auction_insights', - 'ads/accounts/:account_id/authenticated_user_access', - 'ads/accounts/:account_id/campaigns', - 'ads/accounts/:account_id/campaigns/:campaign_id', - 'ads/accounts/:account_id/cards/app_download', - 'ads/accounts/:account_id/cards/app_download/:card_id', - 'ads/accounts/:account_id/cards/image_app_download', - 'ads/accounts/:account_id/cards/image_app_download/:card_id', - 'ads/accounts/:account_id/cards/image_conversation', - 'ads/accounts/:account_id/cards/image_conversation/:card_id', - 'ads/accounts/:account_id/cards/lead_gen', - 'ads/accounts/:account_id/cards/lead_gen/:card_id', - 'ads/accounts/:account_id/cards/video_app_download', - 'ads/accounts/:account_id/cards/video_app_download/:id', - 'ads/accounts/:account_id/cards/video_conversation', - 'ads/accounts/:account_id/cards/video_conversation/:card_id', - 'ads/accounts/:account_id/cards/website', - 'ads/accounts/:account_id/cards/website/:card_id', - 'ads/accounts/:account_id/features', - 'ads/accounts/:account_id/funding_instruments', - 'ads/accounts/:account_id/funding_instruments/:id', - 'ads/accounts/:account_id/line_items', - 'ads/accounts/:account_id/line_items/:line_item_id', - 'ads/accounts/:account_id/media_creatives', - 'ads/accounts/:account_id/media_creatives/:id', - 'ads/accounts/:account_id/preroll_call_to_actions', - 'ads/accounts/:account_id/preroll_call_to_actions/:preroll_call_to_action_id', - 'ads/accounts/:account_id/promotable_users', - 'ads/accounts/:account_id/promoted_accounts', - 'ads/accounts/:account_id/promoted_tweets', - 'ads/accounts/:account_id/reach_estimate', - 'ads/accounts/:account_id/recommendations', - 'ads/accounts/:account_id/recommendations/:recommendation_id', - 'ads/accounts/:account_id/scoped_timeline', - 'ads/accounts/:account_id/tailored_audience_changes', - 'ads/accounts/:account_id/tailored_audience_changes/:id', - 'ads/accounts/:account_id/tailored_audiences', - 'ads/accounts/:account_id/tailored_audiences/:id', - 'ads/accounts/:account_id/tailored_audiences/:id/permissions', - 'ads/accounts/:account_id/targeting_criteria', - 'ads/accounts/:account_id/targeting_criteria/:id', - 'ads/accounts/:account_id/targeting_suggestions', - 'ads/accounts/:account_id/tweet/preview', - 'ads/accounts/:account_id/tweet/preview/:tweet_id', - 'ads/accounts/:account_id/videos', - 'ads/accounts/:account_id/videos/:id', - 'ads/accounts/:account_id/web_event_tags', - 'ads/accounts/:account_id/web_event_tags/:web_event_tag_id', - 'ads/bidding_rules', - 'ads/conversion_attribution', - 'ads/iab_categories', - 'ads/insights/accounts/:account_id', - 'ads/insights/accounts/:account_id/available_audiences', - 'ads/insights/keywords/search', - 'ads/line_items/placements', - 'ads/sandbox/accounts', - 'ads/sandbox/accounts/:account_id', - 'ads/sandbox/accounts/:account_id/account_media', - 'ads/sandbox/accounts/:account_id/app_event_provider_configurations', - 'ads/sandbox/accounts/:account_id/app_event_provider_configurations/:id', - 'ads/sandbox/accounts/:account_id/app_event_tags', - 'ads/sandbox/accounts/:account_id/app_event_tags/:id', - 'ads/sandbox/accounts/:account_id/app_lists', - 'ads/sandbox/accounts/:account_id/auction_insights', - 'ads/sandbox/accounts/:account_id/authenticated_user_access', - 'ads/sandbox/accounts/:account_id/campaigns', - 'ads/sandbox/accounts/:account_id/campaigns/:campaign_id', - 'ads/sandbox/accounts/:account_id/cards/app_download', - 'ads/sandbox/accounts/:account_id/cards/app_download/:card_id', - 'ads/sandbox/accounts/:account_id/cards/image_app_download', - 'ads/sandbox/accounts/:account_id/cards/image_app_download/:card_id', - 'ads/sandbox/accounts/:account_id/cards/image_conversation', - 'ads/sandbox/accounts/:account_id/cards/image_conversation/:card_id', - 'ads/sandbox/accounts/:account_id/cards/lead_gen', - 'ads/sandbox/accounts/:account_id/cards/lead_gen/:card_id', - 'ads/sandbox/accounts/:account_id/cards/video_app_download', - 'ads/sandbox/accounts/:account_id/cards/video_app_download/:id', - 'ads/sandbox/accounts/:account_id/cards/video_conversation', - 'ads/sandbox/accounts/:account_id/cards/video_conversation/:card_id', - 'ads/sandbox/accounts/:account_id/cards/website', - 'ads/sandbox/accounts/:account_id/cards/website/:card_id', - 'ads/sandbox/accounts/:account_id/features', - 'ads/sandbox/accounts/:account_id/funding_instruments', - 'ads/sandbox/accounts/:account_id/funding_instruments/:id', - 'ads/sandbox/accounts/:account_id/line_items', - 'ads/sandbox/accounts/:account_id/line_items/:line_item_id', - 'ads/sandbox/accounts/:account_id/media_creatives', - 'ads/sandbox/accounts/:account_id/media_creatives/:id', - 'ads/sandbox/accounts/:account_id/preroll_call_to_actions', - 'ads/sandbox/accounts/:account_id/preroll_call_to_actions/:preroll_call_to_action_id', - 'ads/sandbox/accounts/:account_id/promotable_users', - 'ads/sandbox/accounts/:account_id/promoted_accounts', - 'ads/sandbox/accounts/:account_id/promoted_tweets', - 'ads/sandbox/accounts/:account_id/reach_estimate', - 'ads/sandbox/accounts/:account_id/recommendations', - 'ads/sandbox/accounts/:account_id/recommendations/:recommendation_id', - 'ads/sandbox/accounts/:account_id/scoped_timeline', - 'ads/sandbox/accounts/:account_id/tailored_audience_changes', - 'ads/sandbox/accounts/:account_id/tailored_audience_changes/:id', - 'ads/sandbox/accounts/:account_id/tailored_audiences', - 'ads/sandbox/accounts/:account_id/tailored_audiences/:id', - 'ads/sandbox/accounts/:account_id/tailored_audiences/:id/permissions', - 'ads/sandbox/accounts/:account_id/targeting_criteria', - 'ads/sandbox/accounts/:account_id/targeting_criteria/:id', - 'ads/sandbox/accounts/:account_id/targeting_suggestions', - 'ads/sandbox/accounts/:account_id/tweet/preview', - 'ads/sandbox/accounts/:account_id/tweet/preview/:tweet_id', - 'ads/sandbox/accounts/:account_id/videos', - 'ads/sandbox/accounts/:account_id/videos/:id', - 'ads/sandbox/accounts/:account_id/web_event_tags', - 'ads/sandbox/accounts/:account_id/web_event_tags/:web_event_tag_id', - 'ads/sandbox/bidding_rules', - 'ads/sandbox/conversion_attribution', - 'ads/sandbox/iab_categories', - 'ads/sandbox/insights/accounts/:account_id', - 'ads/sandbox/insights/accounts/:account_id/available_audiences', - 'ads/sandbox/insights/keywords/search', - 'ads/sandbox/line_items/placements', - 'ads/sandbox/stats/accounts/:account_id', - 'ads/sandbox/stats/accounts/:account_id/reach/campaigns', - 'ads/sandbox/stats/accounts/:account_id/reach/funding_instruments', - 'ads/sandbox/targeting_criteria/app_store_categories', - 'ads/sandbox/targeting_criteria/behavior_taxonomies', - 'ads/sandbox/targeting_criteria/behaviors', - 'ads/sandbox/targeting_criteria/devices', - 'ads/sandbox/targeting_criteria/events', - 'ads/sandbox/targeting_criteria/interests', - 'ads/sandbox/targeting_criteria/languages', - 'ads/sandbox/targeting_criteria/locations', - 'ads/sandbox/targeting_criteria/network_operators', - 'ads/sandbox/targeting_criteria/platform_versions', - 'ads/sandbox/targeting_criteria/platforms', - 'ads/sandbox/targeting_criteria/tv_channels', - 'ads/sandbox/targeting_criteria/tv_genres', - 'ads/sandbox/targeting_criteria/tv_markets', - 'ads/sandbox/targeting_criteria/tv_shows', - 'ads/stats/accounts/:account_id', - 'ads/stats/accounts/:account_id/reach/campaigns', - 'ads/stats/accounts/:account_id/reach/funding_instruments', - 'ads/targeting_criteria/app_store_categories', - 'ads/targeting_criteria/behavior_taxonomies', - 'ads/targeting_criteria/behaviors', - 'ads/targeting_criteria/devices', - 'ads/targeting_criteria/events', - 'ads/targeting_criteria/interests', - 'ads/targeting_criteria/languages', - 'ads/targeting_criteria/locations', - 'ads/targeting_criteria/network_operators', - 'ads/targeting_criteria/platform_versions', - 'ads/targeting_criteria/platforms', - 'ads/targeting_criteria/tv_channels', - 'ads/targeting_criteria/tv_genres', - 'ads/targeting_criteria/tv_markets', - 'ads/targeting_criteria/tv_shows', - 'application/rate_limit_status', - 'blocks/ids', - 'blocks/list', - 'collections/entries', - 'collections/list', - 'collections/show', - 'custom_profiles/:id', - 'custom_profiles/list', - 'direct_messages/events/list', - 'direct_messages/events/show', - 'direct_messages/welcome_messages/list', - 'direct_messages/welcome_messages/rules/list', - 'direct_messages/welcome_messages/rules/show', - 'direct_messages/welcome_messages/show', - 'favorites/list', - 'feedback/events', - 'feedback/show/:id', - 'followers/ids', - 'followers/list', - 'friends/ids', - 'friends/list', - 'friendships/incoming', - 'friendships/lookup', - 'friendships/no_retweets/ids', - 'friendships/outgoing', - 'friendships/show', - 'geo/id/:place_id', - 'geo/reverse_geocode', - 'geo/search', - 'help/configuration', - 'help/languages', - 'help/privacy', - 'help/tos', - 'lists/list', - 'lists/members', - 'lists/members/show', - 'lists/memberships', - 'lists/ownerships', - 'lists/show', - 'lists/statuses', - 'lists/subscribers', - 'lists/subscribers/show', - 'lists/subscriptions', - 'mutes/users/ids', - 'mutes/users/list', - 'oauth/authenticate', - 'oauth/authorize', - 'saved_searches/list', - 'saved_searches/show/:id', - 'search/tweets', - 'statuses/firehose', - 'statuses/home_timeline', - 'statuses/mentions_timeline', - 'statuses/oembed', - 'statuses/retweeters/ids', - 'statuses/retweets/:id', - 'statuses/retweets_of_me', - 'statuses/sample', - 'statuses/show/:id', - 'statuses/user_timeline', - 'trends/available', - 'trends/closest', - 'trends/place', - 'users/profile_banner', - 'users/search', - 'users/show', - 'users/suggestions', - 'users/suggestions/:slug', - 'users/suggestions/:slug/members' - ], - 'POST' => [ - 'account/remove_profile_banner', - 'account/settings', - 'account/update_profile', - 'account/update_profile_banner', - 'account/update_profile_image', - 'account_activity/all/:env_name/subscriptions', - 'account_activity/all/:env_name/webhooks', - 'account_activity/webhooks', - 'account_activity/webhooks/:webhook_id/subscriptions/all', - 'ads/accounts/:account_id/account_media', - 'ads/accounts/:account_id/app_lists', - 'ads/accounts/:account_id/campaigns', - 'ads/accounts/:account_id/cards/app_download', - 'ads/accounts/:account_id/cards/image_app_download', - 'ads/accounts/:account_id/cards/image_conversation', - 'ads/accounts/:account_id/cards/lead_gen', - 'ads/accounts/:account_id/cards/video_app_download', - 'ads/accounts/:account_id/cards/video_conversation', - 'ads/accounts/:account_id/cards/website', - 'ads/accounts/:account_id/line_items', - 'ads/accounts/:account_id/media_creatives', - 'ads/accounts/:account_id/promoted_accounts', - 'ads/accounts/:account_id/promoted_tweets', - 'ads/accounts/:account_id/tailored_audience_changes', - 'ads/accounts/:account_id/tailored_audiences', - 'ads/accounts/:account_id/tailored_audiences/:id/permissions', - 'ads/accounts/:account_id/targeting_criteria', - 'ads/accounts/:account_id/tweet', - 'ads/accounts/:account_id/videos', - 'ads/accounts/:account_id/web_event_tags', - 'ads/batch/accounts/:account_id/campaigns', - 'ads/batch/accounts/:account_id/line_items', - 'ads/batch/accounts/:account_id/tailored_audiences', - 'ads/batch/accounts/:account_id/targeting_criteria', - 'ads/conversion_event', - 'ads/sandbox/accounts', - 'ads/sandbox/accounts/:account_id/account_media', - 'ads/sandbox/accounts/:account_id/app_lists', - 'ads/sandbox/accounts/:account_id/campaigns', - 'ads/sandbox/accounts/:account_id/cards/app_download', - 'ads/sandbox/accounts/:account_id/cards/image_app_download', - 'ads/sandbox/accounts/:account_id/cards/image_conversation', - 'ads/sandbox/accounts/:account_id/cards/lead_gen', - 'ads/sandbox/accounts/:account_id/cards/video_app_download', - 'ads/sandbox/accounts/:account_id/cards/video_conversation', - 'ads/sandbox/accounts/:account_id/cards/website', - 'ads/sandbox/accounts/:account_id/features', - 'ads/sandbox/accounts/:account_id/funding_instruments', - 'ads/sandbox/accounts/:account_id/line_items', - 'ads/sandbox/accounts/:account_id/media_creatives', - 'ads/sandbox/accounts/:account_id/promoted_accounts', - 'ads/sandbox/accounts/:account_id/promoted_tweets', - 'ads/sandbox/accounts/:account_id/tailored_audience_changes', - 'ads/sandbox/accounts/:account_id/tailored_audiences', - 'ads/sandbox/accounts/:account_id/tailored_audiences/:id/permissions', - 'ads/sandbox/accounts/:account_id/targeting_criteria', - 'ads/sandbox/accounts/:account_id/tweet', - 'ads/sandbox/accounts/:account_id/videos', - 'ads/sandbox/accounts/:account_id/web_event_tags', - 'ads/sandbox/batch/accounts/:account_id/campaigns', - 'ads/sandbox/batch/accounts/:account_id/line_items', - 'ads/sandbox/batch/accounts/:account_id/tailored_audiences', - 'ads/sandbox/batch/accounts/:account_id/targeting_criteria', - 'ads/sandbox/conversion_event', - 'ads/sandbox/stats/jobs/accounts/:account_id', - 'ads/sandbox/tailored_audience_memberships', - 'ads/stats/jobs/accounts/:account_id', - 'ads/tailored_audience_memberships', - 'blocks/create', - 'blocks/destroy', - 'collections/create', - 'collections/destroy', - 'collections/entries/add', - 'collections/entries/curate', - 'collections/entries/move', - 'collections/entries/remove', - 'collections/update', - 'custom_profiles/new', - 'direct_messages/events/new', - 'direct_messages/indicate_typing', - 'direct_messages/mark_read', - 'direct_messages/welcome_messages/new', - 'direct_messages/welcome_messages/rules/new', - 'favorites/create', - 'favorites/destroy', - 'feedback/create', - 'friendships/create', - 'friendships/destroy', - 'friendships/update', - 'lists/create', - 'lists/destroy', - 'lists/members/create', - 'lists/members/create_all', - 'lists/members/destroy', - 'lists/members/destroy_all', - 'lists/subscribers/create', - 'lists/subscribers/destroy', - 'lists/update', - 'media/metadata/create', - 'media/upload', - 'mutes/users/create', - 'mutes/users/destroy', - 'oauth/access_token', - 'oauth/request_token', - 'oauth2/invalidate_token', - 'oauth2/token', - 'saved_searches/create', - 'saved_searches/destroy/:id', - 'statuses/destroy/:id', - 'statuses/filter', - 'statuses/lookup', - 'statuses/retweet/:id', - 'statuses/unretweet/:id', - 'statuses/update', - 'ton/bucket/:bucket', - 'ton/bucket/:bucket?resumable=true', - 'tweets/search/30day/:env', - 'tweets/search/30day/:env/counts', - 'tweets/search/fullarchive/:env', - 'tweets/search/fullarchive/:env/counts', - 'users/lookup', - 'users/report_spam' - ], - 'PUT' => [ - 'account_activity/all/:env_name/webhooks/:webhook_id', - 'account_activity/webhooks/:webhook_id', - 'ads/accounts/:account_id/campaigns/:campaign_id', - 'ads/accounts/:account_id/cards/app_download/:card_id', - 'ads/accounts/:account_id/cards/image_app_download/:card_id', - 'ads/accounts/:account_id/cards/image_conversation/:card_id', - 'ads/accounts/:account_id/cards/lead_gen/:card_id', - 'ads/accounts/:account_id/cards/video_app_download/:id', - 'ads/accounts/:account_id/cards/video_conversation/:card_id', - 'ads/accounts/:account_id/cards/website/:card_id', - 'ads/accounts/:account_id/line_items/:line_item_id', - 'ads/accounts/:account_id/preroll_call_to_actions/:preroll_call_to_action_id', - 'ads/accounts/:account_id/promoted_tweets/:id', - 'ads/accounts/:account_id/tailored_audiences/global_opt_out', - 'ads/accounts/:account_id/targeting_criteria', - 'ads/accounts/:account_id/videos/:id', - 'ads/accounts/:account_id/web_event_tags/:web_event_tag_id', - 'ads/sandbox/accounts/:account_id/campaigns/:campaign_id', - 'ads/sandbox/accounts/:account_id/cards/app_download/:card_id', - 'ads/sandbox/accounts/:account_id/cards/image_app_download/:card_id', - 'ads/sandbox/accounts/:account_id/cards/image_conversation/:card_id', - 'ads/sandbox/accounts/:account_id/cards/lead_gen/:card_id', - 'ads/sandbox/accounts/:account_id/cards/video_app_download/:id', - 'ads/sandbox/accounts/:account_id/cards/video_conversation/:card_id', - 'ads/sandbox/accounts/:account_id/cards/website/:card_id', - 'ads/sandbox/accounts/:account_id/line_items/:line_item_id', - 'ads/sandbox/accounts/:account_id/preroll_call_to_actions/:preroll_call_to_action_id', - 'ads/sandbox/accounts/:account_id/promoted_tweets/:id', - 'ads/sandbox/accounts/:account_id/tailored_audiences/global_opt_out', - 'ads/sandbox/accounts/:account_id/targeting_criteria', - 'ads/sandbox/accounts/:account_id/videos/:id', - 'ads/sandbox/accounts/:account_id/web_event_tags/:web_event_tag_id', - 'direct_messages/welcome_messages/update', - 'ton/bucket/:bucket/:file?resumable=true&resumeId=:resumeId' - ], - 'DELETE' => [ - 'account_activity/all/:env_name/subscriptions', - 'account_activity/all/:env_name/webhooks/:webhook_id', - 'account_activity/webhooks/:webhook_id', - 'account_activity/webhooks/:webhook_id/subscriptions/all', - 'ads/accounts/:account_id/campaigns/:campaign_id', - 'ads/accounts/:account_id/cards/app_download/:card_id', - 'ads/accounts/:account_id/cards/image_app_download/:card_id', - 'ads/accounts/:account_id/cards/image_conversation/:card_id', - 'ads/accounts/:account_id/cards/lead_gen/:card_id', - 'ads/accounts/:account_id/cards/video_app_download/:id', - 'ads/accounts/:account_id/cards/video_conversation/:card_id', - 'ads/accounts/:account_id/cards/website/:card_id', - 'ads/accounts/:account_id/line_items/:line_item_id', - 'ads/accounts/:account_id/media_creatives/:id', - 'ads/accounts/:account_id/preroll_call_to_actions/:preroll_call_to_action_id', - 'ads/accounts/:account_id/promoted_tweets/:id', - 'ads/accounts/:account_id/tailored_audiences/:id', - 'ads/accounts/:account_id/targeting_criteria/:id', - 'ads/accounts/:account_id/videos/:id', - 'ads/accounts/:account_id/web_event_tags/:web_event_tag_id', - 'ads/sandbox/accounts/:account_id/campaigns/:campaign_id', - 'ads/sandbox/accounts/:account_id/cards/app_download/:card_id', - 'ads/sandbox/accounts/:account_id/cards/image_app_download/:card_id', - 'ads/sandbox/accounts/:account_id/cards/image_conversation/:card_id', - 'ads/sandbox/accounts/:account_id/cards/lead_gen/:card_id', - 'ads/sandbox/accounts/:account_id/cards/video_app_download/:id', - 'ads/sandbox/accounts/:account_id/cards/video_conversation/:card_id', - 'ads/sandbox/accounts/:account_id/cards/website/:card_id', - 'ads/sandbox/accounts/:account_id/line_items/:line_item_id', - 'ads/sandbox/accounts/:account_id/media_creatives/:id', - 'ads/sandbox/accounts/:account_id/preroll_call_to_actions/:preroll_call_to_action_id', - 'ads/sandbox/accounts/:account_id/promoted_tweets/:id', - 'ads/sandbox/accounts/:account_id/tailored_audiences/:id', - 'ads/sandbox/accounts/:account_id/targeting_criteria/:id', - 'ads/sandbox/accounts/:account_id/videos/:id', - 'ads/sandbox/accounts/:account_id/web_event_tags/:web_event_tag_id', - 'custom_profiles/destroy', - 'direct_messages/events/destroy', - 'direct_messages/welcome_messages/destroy', - 'direct_messages/welcome_messages/rules/destroy' - ] - ]; - - /** - * Possible file name parameters - */ - protected static $_possible_files = [ - // Tweets - 'media/upload' => ['media'], - // Accounts - 'account/update_profile_image' => ['image'], - 'account/update_profile_banner' => ['banner'] - ]; - - /** - * The current Codebird version - */ - protected static $_version = '4.0.0-beta.1'; - - /** - * The Request or access token. Used to sign requests - */ - protected $_oauth_token = null; - - /** - * The corresponding request or access token secret - */ - protected $_oauth_token_secret = null; - - /** - * The format of data to return from API calls - */ - protected $_return_format = CODEBIRD_RETURNFORMAT_OBJECT; - - /** - * The callback to call with any new streaming messages - */ - protected $_streaming_callback = null; - - /** - * Auto-detect cURL absence - */ - protected $_use_curl = true; - - /** - * Timeouts - */ - protected $_timeouts = [ - 'request' => 10000, - 'connect' => 3000, - 'remote' => 5000 - ]; - - /** - * Proxy - */ - protected $_proxy = []; - - /** - * - * Class constructor - * - */ - public function __construct() - { - // Pre-define $_use_curl depending on cURL availability - $this->setUseCurl(function_exists('curl_init')); - } - - /** - * Returns singleton class instance - * Always use this method unless you're working with multiple authenticated users at once - * - * @return Codebird The instance - */ - public static function getInstance() - { - if (self::$_instance === null) { - self::$_instance = new self; - } - return self::$_instance; - } - - /** - * Sets the OAuth consumer key and secret (App key) - * - * @param string $key OAuth consumer key - * @param string $secret OAuth consumer secret - * - * @return void - */ - public static function setConsumerKey($key, $secret) - { - self::$_consumer_key = $key; - self::$_consumer_secret = $secret; - } - - /** - * Sets the OAuth2 app-only auth bearer token - * - * @param string $token OAuth2 bearer token - * - * @return void - */ - public static function setBearerToken($token) - { - self::$_bearer_token = $token; - } - - /** - * Gets the current Codebird version - * - * @return string The version number - */ - public function getVersion() - { - return self::$_version; - } - - /** - * Sets the OAuth request or access token and secret (User key) - * - * @param string $token OAuth request or access token - * @param string $secret OAuth request or access token secret - * - * @return void - */ - public function setToken($token, $secret) - { - $this->_oauth_token = $token; - $this->_oauth_token_secret = $secret; - } - - /** - * Forgets the OAuth request or access token and secret (User key) - * - * @return bool - */ - public function logout() - { - $this->_oauth_token = - $this->_oauth_token_secret = null; - - return true; - } - - /** - * Sets if codebird should use cURL - * - * @param bool $use_curl Request uses cURL or not - * - * @return void - * @throws \Exception - */ - public function setUseCurl($use_curl) - { - if ($use_curl && ! function_exists('curl_init')) { - throw new \Exception('To use cURL, the PHP curl extension must be available.'); - } - - $this->_use_curl = (bool) $use_curl; - } - - /** - * Sets request timeout in milliseconds - * - * @param int $timeout Request timeout in milliseconds - * - * @return void - */ - public function setTimeout($timeout) - { - if ($timeout < 0) { - $timeout = 0; - } - $this->_timeouts['request'] = (int) $timeout; - } - - /** - * Sets connection timeout in milliseconds - * - * @param int $timeout Connection timeout in milliseconds - * - * @return void - */ - public function setConnectionTimeout($timeout) - { - if ($timeout < 0) { - $timeout = 0; - } - $this->_timeouts['connect'] = (int) $timeout; - } - - /** - * Sets remote media download timeout in milliseconds - * - * @param int $timeout Remote media timeout in milliseconds - * - * @return void - */ - public function setRemoteDownloadTimeout($timeout) - { - if ($timeout < 0) { - $timeout = 0; - } - $this->_timeouts['remote'] = (int) $timeout; - } - - /** - * Sets the format for API replies - * - * @param int $return_format One of these: - * CODEBIRD_RETURNFORMAT_OBJECT (default) - * CODEBIRD_RETURNFORMAT_ARRAY - * CODEBIRD_RETURNFORMAT_JSON - * - * @return void - */ - public function setReturnFormat($return_format) - { - $this->_return_format = $return_format; - } - - /** - * Sets the proxy - * - * @param string $host Proxy host - * @param int $port Proxy port - * @param int optional $type Proxy type, defaults to HTTP - * - * @return void - * @throws \Exception - */ - public function setProxy($host, $port, $type = CURLPROXY_HTTP) - { - static $types_str = [ - 'HTTP', 'SOCKS4', 'SOCKS5', 'SOCKS4A', 'SOCKS5_HOSTNAME' - ]; - $types = []; - foreach ($types_str as $type_str) { - if (defined('CURLPROXY_' . $type_str)) { - $types[] = constant('CURLPROXY_' . $type_str); - } - } - if (! in_array($type, $types)) { - throw new \Exception('Invalid proxy type specified.'); - } - - $this->_proxy['host'] = $host; - $this->_proxy['port'] = (int) $port; - $this->_proxy['type'] = $type; - } - - /** - * Sets the proxy authentication - * - * @param string $authentication Proxy authentication - * - * @return void - */ - public function setProxyAuthentication($authentication) - { - $this->_proxy['authentication'] = $authentication; - } - - /** - * Sets streaming callback - * - * @param callable $callback The streaming callback - * - * @return void - * @throws \Exception - */ - public function setStreamingCallback($callback) - { - if (!is_callable($callback)) { - throw new \Exception('This is not a proper callback.'); - } - $this->_streaming_callback = $callback; - } - - /** - * Get allowed API methods, sorted by HTTP method - * Watch out for multiple-method API methods! - * - * @return array $apimethods - */ - public function getApiMethods() - { - return self::$_api_methods; - } - - /** - * Main API handler working on any requests you issue - * - * @param string $function The member function you called - * @param array $params The parameters you sent along - * - * @return string The API reply encoded in the set return_format - */ - - public function __call($function, $params) - { - // cURL function? - if (substr($function, 0, 6) === '_curl_' - || $function === '_time' - || $function === '_microtime' - ) { - return call_user_func_array(substr($function, 1), $params); - } - - // parse parameters - $apiparams = $this->_parseApiParams($params); - - // stringify null and boolean parameters - $apiparams = $this->_stringifyNullBoolParams($apiparams); - - $app_only_auth = false; - if (count($params) > 1) { - // convert app_only_auth param to bool - $app_only_auth = !! $params[1]; - } - - // reset token when requesting a new token - // (causes 401 for signature error on subsequent requests) - if ($function === 'oauth_requestToken') { - $this->setToken(null, null); - } - - // map function name to API method - list($method, $method_template) = $this->_mapFnToApiMethod($function, $apiparams); - - $httpmethod = $this->_detectMethod($method_template, $apiparams); - $multipart = $this->_detectMultipart($method_template); - - return $this->_callApi( - $httpmethod, - $method, - $method_template, - $apiparams, - $multipart, - $app_only_auth - ); - } - - - /** - * __call() helpers - */ - - /** - * Parse given params, detect query-style params - * - * @param array|string $params Parameters to parse - * - * @return array $apiparams - */ - protected function _parseApiParams($params) - { - $apiparams = []; - if (count($params) === 0) { - return $apiparams; - } - - if (is_array($params[0])) { - // given parameters are array - $apiparams = $params[0]; - return $apiparams; - } - - // user gave us query-style params - parse_str($params[0], $apiparams); - if (! is_array($apiparams)) { - $apiparams = []; - } - - return $apiparams; - } - - /** - * Replace null and boolean parameters with their string representations - * - * @param array $apiparams Parameter array to replace in - * - * @return array $apiparams - */ - protected function _stringifyNullBoolParams($apiparams) - { - foreach ($apiparams as $key => $value) { - if (! is_scalar($value)) { - // no need to try replacing arrays - continue; - } - if (is_null($value)) { - $apiparams[$key] = 'null'; - } elseif (is_bool($value)) { - $apiparams[$key] = $value ? 'true' : 'false'; - } - } - - return $apiparams; - } - - /** - * Maps called PHP magic method name to Twitter API method - * - * @param string $function Function called - * @param array $apiparams byref API parameters - * - * @return string[] (string method, string method_template) - */ - protected function _mapFnToApiMethod($function, &$apiparams) - { - // replace _ by / - $method = $this->_mapFnInsertSlashes($function); - - // undo replacement for URL parameters - $method = $this->_mapFnRestoreParamUnderscores($method); - - // replace AA by URL parameters - list ($method, $method_template) = $this->_mapFnInlineParams($method, $apiparams); - - if (substr($method, 0, 4) !== 'ton/') { - // replace A-Z by _a-z - for ($i = 0; $i < 26; $i++) { - $method = str_replace(chr(65 + $i), '_' . chr(97 + $i), $method); - $method_template = str_replace(chr(65 + $i), '_' . chr(97 + $i), $method_template); - } - } - - return [$method, $method_template]; - } - - /** - * API method mapping: Replaces _ with / character - * - * @param string $function Function called - * - * @return string API method to call - */ - protected function _mapFnInsertSlashes($function) - { - return str_replace('_', '/', $function); - } - - /** - * API method mapping: Restore _ character in named parameters - * - * @param string $method API method to call - * - * @return string API method with restored underscores - */ - protected function _mapFnRestoreParamUnderscores($method) - { - $params = [ - 'screen_name', 'place_id', - 'account_id', 'campaign_id', 'card_id', 'line_item_id', - 'tweet_id', 'web_event_tag_id' - ]; - foreach ($params as $param) { - $param = strtoupper($param); - $replacement_was = str_replace('_', '/', $param); - $method = str_replace($replacement_was, $param, $method); - } - - return $method; - } - - /** - * Inserts inline parameters into the method name - * - * @param string $method The method to call - * @param array byref $apiparams The parameters to send along - * - * @return string[] (string method, string method_template) - * @throws \Exception - */ - protected function _mapFnInlineParams($method, &$apiparams) - { - $method_template = $method; - $match = []; - if (preg_match_all('/[A-Z_]{2,}/', $method, $match)) { - foreach ($match[0] as $param) { - $param_l = strtolower($param); - if ($param_l === 'resumeid') { - $param_l = 'resumeId'; - } - $method_template = str_replace($param, ':' . $param_l, $method_template); - if (! isset($apiparams[$param_l])) { - for ($i = 0; $i < 26; $i++) { - $method_template = str_replace(chr(65 + $i), '_' . chr(97 + $i), $method_template); - } - throw new \Exception( - 'To call the templated method "' . $method_template - . '", specify the parameter value for "' . $param_l . '".' - ); - } - $method = str_replace($param, $apiparams[$param_l], $method); - unset($apiparams[$param_l]); - } - } - - return [$method, $method_template]; - } - - /** - * Avoids any JSON_BIGINT_AS_STRING errors - * - * @param string $data JSON data to decode - * @param int optional $need_array Decode as array, otherwise as object - * - * @return array|object The decoded object - */ - protected function _json_decode($data, $need_array = false) - { - if (!(defined('JSON_C_VERSION') && PHP_INT_SIZE > 4)) { - return json_decode($data, $need_array, 512, JSON_BIGINT_AS_STRING); - } - $max_int_length = strlen((string) PHP_INT_MAX) - 1; - $json_without_bigints = preg_replace('/:\s*(-?\d{'.$max_int_length.',})/', ': "$1"', $data); - $obj = json_decode($json_without_bigints, $need_array); - return $obj; - } - - /** - * Uncommon API methods - */ - - /** - * Gets the OAuth authenticate URL for the current request token - * - * @param optional bool $force_login Whether to force the user to enter their login data - * @param optional string $screen_name Screen name to repopulate the user name with - * @param optional string $type 'authenticate' or 'authorize', to avoid duplicate code - * - * @return string The OAuth authenticate/authorize URL - * @throws \Exception - */ - public function oauth_authenticate($force_login = NULL, $screen_name = NULL, $type = 'authenticate') - { - if (! in_array($type, ['authenticate', 'authorize'])) { - throw new \Exception('To get the ' . $type . ' URL, use the correct third parameter, or omit it.'); - } - if ($this->_oauth_token === null) { - throw new CodebirdCredentialsException('To get the ' . $type . ' URL, the OAuth token must be set.'); - } - $url = self::$_endpoints['oauth'] . 'oauth/' . $type . '?oauth_token=' . $this->_url($this->_oauth_token); - if ($force_login) { - $url .= "&force_login=1"; - } - if ($screen_name) { - $url .= "&screen_name=" . $screen_name; - } - return $url; - } - - /** - * Gets the OAuth authorize URL for the current request token - * @param optional bool $force_login Whether to force the user to enter their login data - * @param optional string $screen_name Screen name to repopulate the user name with - * - * @return string The OAuth authorize URL - */ - public function oauth_authorize($force_login = NULL, $screen_name = NULL) - { - return $this->oauth_authenticate($force_login, $screen_name, 'authorize'); - } - - /** - * Gets the OAuth bearer token - * - * @return string The OAuth bearer token - */ - - public function oauth2_token() - { - if ($this->_use_curl) { - return $this->_oauth2TokenCurl(); - } - return $this->_oauth2TokenNoCurl(); - } - - /** - * Gets a cURL handle - * @param string $url the URL for the curl initialization - * @return resource handle - */ - protected function _getCurlInitialization($url) - { - $connection = $this->_curl_init($url); - - $this->_curl_setopt($connection, CURLOPT_RETURNTRANSFER, 1); - $this->_curl_setopt($connection, CURLOPT_FOLLOWLOCATION, 0); - $this->_curl_setopt($connection, CURLOPT_HEADER, 1); - $this->_curl_setopt($connection, CURLOPT_SSL_VERIFYPEER, 1); - $this->_curl_setopt($connection, CURLOPT_SSL_VERIFYHOST, 2); - $this->_curl_setopt($connection, CURLOPT_CAINFO, __DIR__ . '/cacert.pem'); - $this->_curl_setopt( - $connection, CURLOPT_USERAGENT, - 'codebird-php/' . $this->getVersion() . ' +https://github.com/jublonet/codebird-php' - ); - - if ($this->_hasProxy()) { - $this->_curl_setopt($connection, CURLOPT_PROXYTYPE, $this->_getProxyType()); - $this->_curl_setopt($connection, CURLOPT_PROXY, $this->_getProxyHost()); - $this->_curl_setopt($connection, CURLOPT_PROXYPORT, $this->_getProxyPort()); - - if ($this->_getProxyAuthentication()) { - $this->_curl_setopt($connection, CURLOPT_PROXYAUTH, CURLAUTH_BASIC); - $this->_curl_setopt($connection, CURLOPT_PROXYUSERPWD, $this->_getProxyAuthentication()); - } - } - - return $connection; - } - - /** - * Gets a non cURL initialization - * - * @param string $url the URL for the curl initialization - * @param array $contextOptions the options for the stream context - * @param string $hostname the hostname to verify the SSL FQDN for - * - * @return array the read data - */ - protected function _getNoCurlInitialization($url, $contextOptions, $hostname = '') - { - $httpOptions = []; - - $httpOptions['header'] = [ - 'User-Agent: codebird-php/' . $this->getVersion() . ' +https://github.com/jublonet/codebird-php' - ]; - - $httpOptions['ssl'] = [ - 'verify_peer' => true, - 'cafile' => __DIR__ . '/cacert.pem', - 'verify_depth' => 5, - 'peer_name' => $hostname - ]; - - if ($this->_hasProxy()) { - $httpOptions['request_fulluri'] = true; - $httpOptions['proxy'] = $this->_getProxyHost() . ':' . $this->_getProxyPort(); - - if ($this->_getProxyAuthentication()) { - $httpOptions['header'][] = - 'Proxy-Authorization: Basic ' . base64_encode($this->_getProxyAuthentication()); - } - } - - // merge the http options with the context options - $options = array_merge_recursive( - $contextOptions, - ['http' => $httpOptions] - ); - - // concatenate $options['http']['header'] - $options['http']['header'] = implode("\r\n", $options['http']['header']); - - // silent the file_get_contents function - $content = @file_get_contents($url, false, stream_context_create($options)); - - $headers = []; - // API is responding - if (isset($http_response_header)) { - $headers = $http_response_header; - } - - return [ - $content, - $headers - ]; - } - - protected function _hasProxy() - { - return isset($this->_proxy['host']) || isset($this->_proxy['port']); - } - - /** - * Gets the proxy host - * - * @return string The proxy host - */ - protected function _getProxyHost() - { - return $this->_getProxyData('host'); - } - - /** - * Gets the proxy port - * - * @return string The proxy port - */ - protected function _getProxyPort() - { - return $this->_getProxyData('port'); - } - - /** - * Gets the proxy authentication - * - * @return string The proxy authentication - */ - protected function _getProxyAuthentication() - { - return $this->_getProxyData('authentication'); - } - - /** - * Gets the proxy type - * - * @return string The proxy type - */ - protected function _getProxyType() - { - return $this->_getProxyData('type'); - } - - /** - * Gets data from the proxy configuration - * - * @param string $name - */ - private function _getProxyData($name) - { - return empty($this->_proxy[$name]) ? null : $this->_proxy[$name]; - } - - /** - * Gets the OAuth bearer token, using cURL - * - * @return string The OAuth bearer token - * @throws \Exception - */ - - protected function _oauth2TokenCurl() - { - if (self::$_consumer_key === null) { - throw new CodebirdCredentialsException('To obtain a bearer token, the consumer key must be set.'); - } - $post_fields = [ - 'grant_type' => 'client_credentials' - ]; - $url = self::$_endpoints['oauth'] . 'oauth2/token'; - $connection = $this->_getCurlInitialization($url); - $this->_curl_setopt($connection, CURLOPT_POST, 1); - $this->_curl_setopt($connection, CURLOPT_POSTFIELDS, $post_fields); - - $this->_curl_setopt($connection, CURLOPT_USERPWD, self::$_consumer_key . ':' . self::$_consumer_secret); - $this->_curl_setopt($connection, CURLOPT_HTTPHEADER, [ - 'Expect:' - ]); - $result = $this->_curl_exec($connection); - - // catch request errors - if ($result === false) { - throw new CodebirdAuthException('Request error for bearer token: ' . $this->_curl_error($connection)); - } - - // certificate validation results - $validation_result = $this->_curl_errno($connection); - $this->_validateSslCertificate($validation_result); - - $httpstatus = $this->_curl_getinfo($connection, CURLINFO_HTTP_CODE); - $reply = $this->_parseBearerReply($result, $httpstatus); - return $reply; - } - - /** - * Gets the OAuth bearer token, without cURL - * - * @return string The OAuth bearer token - * @throws \Exception - */ - - protected function _oauth2TokenNoCurl() - { - if (self::$_consumer_key == null) { - throw new CodebirdCredentialsException('To obtain a bearer token, the consumer key must be set.'); - } - - $url = self::$_endpoints['oauth'] . 'oauth2/token'; - $hostname = parse_url($url, PHP_URL_HOST); - - if ($hostname === false) { - throw new CodebirdEndpointException('Incorrect API endpoint host.'); - } - - $contextOptions = [ - 'http' => [ - 'method' => 'POST', - 'protocol_version' => '1.1', - 'header' => "Accept: */*\r\n" - . 'Authorization: Basic ' - . base64_encode( - self::$_consumer_key - . ':' - . self::$_consumer_secret - ), - 'timeout' => $this->_timeouts['request'] / 1000, - 'content' => 'grant_type=client_credentials', - 'ignore_errors' => true - ] - ]; - list($reply, $headers) = $this->_getNoCurlInitialization($url, $contextOptions, $hostname); - $result = ''; - foreach ($headers as $header) { - $result .= $header . "\r\n"; - } - $result .= "\r\n" . $reply; - - // find HTTP status - $httpstatus = $this->_getHttpStatusFromHeaders($headers); - $reply = $this->_parseBearerReply($result, $httpstatus); - return $reply; - } - - - /** - * General helpers to avoid duplicate code - */ - - /** - * Extract HTTP status code from headers - * - * @param array $headers The headers to parse - * - * @return string The HTTP status code - */ - protected function _getHttpStatusFromHeaders($headers) - { - $httpstatus = '500'; - $match = []; - if (!empty($headers[0]) && preg_match('/HTTP\/\d\.\d (\d{3})/', $headers[0], $match)) { - $httpstatus = $match[1]; - } - return $httpstatus; - } - - /** - * Parse oauth2_token reply and set bearer token, if found - * - * @param string $result Raw HTTP response - * @param int $httpstatus HTTP status code - * - * @return string reply - */ - protected function _parseBearerReply($result, $httpstatus) - { - list($headers, $reply) = $this->_parseApiHeaders($result); - $reply = $this->_parseApiReply($reply); - $rate = $this->_getRateLimitInfo($headers); - switch ($this->_return_format) { - case CODEBIRD_RETURNFORMAT_ARRAY: - $reply['httpstatus'] = $httpstatus; - $reply['rate'] = $rate; - if ($httpstatus === 200) { - self::setBearerToken($reply['access_token']); - } - break; - case CODEBIRD_RETURNFORMAT_JSON: - if ($httpstatus === 200) { - $parsed = $this->_json_decode($reply); - self::setBearerToken($parsed->access_token); - } - break; - case CODEBIRD_RETURNFORMAT_OBJECT: - $reply->httpstatus = $httpstatus; - $reply->rate = $rate; - if ($httpstatus === 200) { - self::setBearerToken($reply->access_token); - } - break; - } - return $reply; - } - - /** - * Extract rate-limiting data from response headers - * - * @param array $headers The CURL response headers - * - * @return null|array|object The rate-limiting information - */ - protected function _getRateLimitInfo($headers) - { - if (! isset($headers['x-rate-limit-limit'])) { - return null; - } - $rate = [ - 'limit' => $headers['x-rate-limit-limit'], - 'remaining' => $headers['x-rate-limit-remaining'], - 'reset' => $headers['x-rate-limit-reset'] - ]; - if ($this->_return_format === CODEBIRD_RETURNFORMAT_OBJECT) { - return (object) $rate; - } - return $rate; - } - - /** - * Check if there were any SSL certificate errors - * - * @param int $validation_result The curl error number - * - * @return void - * @throws \Exception - */ - protected function _validateSslCertificate($validation_result) - { - if (in_array( - $validation_result, - [ - CURLE_SSL_CERTPROBLEM, - CURLE_SSL_CACERT, - CURLE_SSL_CACERT_BADFILE, - CURLE_SSL_CRL_BADFILE, - CURLE_SSL_ISSUER_ERROR - ] - ) - ) { - throw new \Exception( - 'Error ' . $validation_result - . ' while validating the Twitter API certificate.' - ); - } - } - - /** - * Signing helpers - */ - - /** - * URL-encodes the given data - * - * @param mixed $data - * - * @return mixed The encoded data - */ - protected function _url($data) - { - if (is_array($data)) { - return array_map([ - $this, - '_url' - ], $data); - } elseif (is_scalar($data)) { - return str_replace([ - '+', - '!', - '*', - "'", - '(', - ')' - ], [ - ' ', - '%21', - '%2A', - '%27', - '%28', - '%29' - ], rawurlencode($data)); - } - return ''; - } - - /** - * Gets the base64-encoded SHA1 hash for the given data - * - * @param string $data The data to calculate the hash from - * - * @return string The hash - * @throws \Exception - */ - protected function _sha1($data) - { - if (self::$_consumer_secret === null) { - throw new CodebirdCredentialsException('To generate a hash, the consumer secret must be set.'); - } - if (!function_exists('hash_hmac')) { - throw new \Exception('To generate a hash, the PHP hash extension must be available.'); - } - return base64_encode(hash_hmac( - 'sha1', - $data, - self::$_consumer_secret - . '&' - . ($this->_oauth_token_secret !== null - ? $this->_oauth_token_secret - : '' - ), - true - )); - } - - /** - * Generates a (hopefully) unique random string - * - * @param int optional $length The length of the string to generate - * - * @return string The random string - * @throws \Exception - */ - protected function _nonce($length = 8) - { - if ($length < 1) { - throw new \Exception('Invalid nonce length.'); - } - return substr(md5($this->_microtime(true)), 0, $length); - } - - /** - * Signature helper - * - * @param string $httpmethod Usually either 'GET' or 'POST' or 'DELETE' - * @param string $method The API method to call - * @param array $base_params The signature base parameters - * - * @return string signature - */ - protected function _getSignature($httpmethod, $method, $base_params) - { - // convert params to string - $base_string = ''; - foreach ($base_params as $key => $value) { - $base_string .= $key . '=' . $value . '&'; - } - - // trim last ampersand - $base_string = substr($base_string, 0, -1); - - // hash it - return $this->_sha1( - $httpmethod . '&' . - $this->_url($method) . '&' . - $this->_url($base_string) - ); - } - - /** - * Generates an OAuth signature - * - * @param string $httpmethod Usually either 'GET' or 'POST' or 'DELETE' - * @param string $method The API method to call - * @param array optional $params The API call parameters, associative - * - * @return string Authorization HTTP header - * @throws \Exception - */ - protected function _sign($httpmethod, $method, $params = []) - { - if (self::$_consumer_key === null) { - throw new CodebirdCredentialsException('To generate a signature, the consumer key must be set.'); - } - $sign_base_params = array_map( - [$this, '_url'], - [ - 'oauth_consumer_key' => self::$_consumer_key, - 'oauth_version' => '1.0', - 'oauth_timestamp' => $this->_time(), - 'oauth_nonce' => $this->_nonce(), - 'oauth_signature_method' => 'HMAC-SHA1' - ] - ); - if ($this->_oauth_token !== null) { - $sign_base_params['oauth_token'] = $this->_url($this->_oauth_token); - } - $oauth_params = $sign_base_params; - - // merge in the non-OAuth params - $sign_base_params = array_merge( - $sign_base_params, - array_map([$this, '_url'], $params) - ); - ksort($sign_base_params); - - $signature = $this->_getSignature($httpmethod, $method, $sign_base_params); - - $params = $oauth_params; - $params['oauth_signature'] = $signature; - - ksort($params); - $authorization = 'OAuth '; - foreach ($params as $key => $value) { - $authorization .= $key . "=\"" . $this->_url($value) . "\", "; - } - return substr($authorization, 0, -2); - } - - /** - * Detects HTTP method to use for API call - * - * @param string $method The API method to call - * @param array byref $params The parameters to send along - * - * @return string The HTTP method that should be used - */ - protected function _detectMethod($method, &$params) - { - if (isset($params['httpmethod'])) { - $httpmethod = $params['httpmethod']; - unset($params['httpmethod']); - return $httpmethod; - } - $apimethods = $this->getApiMethods(); - - // multi-HTTP method API methods - // parameter-based detection - $httpmethods_by_param = [ - 'POST' => [ - 'campaign_id' => [ - 'ads/accounts/:account_id/line_items', - 'ads/sandbox/accounts/:account_id/line_items' - ], - 'media_id' => [ - 'ads/accounts/:account_id/account_media', - 'ads/sandbox/accounts/:account_id/account_media' - ], - 'name' => [ - 'ads/accounts/:account_id/app_lists', - 'ads/accounts/:account_id/campaigns', - 'ads/accounts/:account_id/cards/app_download', - 'ads/accounts/:account_id/cards/image_app_download', - 'ads/accounts/:account_id/cards/image_conversation', - 'ads/accounts/:account_id/cards/lead_gen', - 'ads/accounts/:account_id/cards/video_app_download', - 'ads/accounts/:account_id/cards/video_conversation', - 'ads/accounts/:account_id/cards/website', - 'ads/accounts/:account_id/tailored_audiences', - 'ads/accounts/:account_id/web_event_tags', - 'ads/sandbox/accounts/:account_id/app_lists', - 'ads/sandbox/accounts/:account_id/campaigns', - 'ads/sandbox/accounts/:account_id/cards/app_download', - 'ads/sandbox/accounts/:account_id/cards/image_app_download', - 'ads/sandbox/accounts/:account_id/cards/image_conversation', - 'ads/sandbox/accounts/:account_id/cards/lead_gen', - 'ads/sandbox/accounts/:account_id/cards/video_app_download', - 'ads/sandbox/accounts/:account_id/cards/video_conversation', - 'ads/sandbox/accounts/:account_id/cards/website', - 'ads/sandbox/accounts/:account_id/tailored_audiences', - 'ads/sandbox/accounts/:account_id/web_event_tags' - ], - 'permission_level' => [ - 'ads/accounts/:account_id/tailored_audiences/:id/permissions', - 'ads/sandbox/accounts/:account_id/tailored_audiences/:id/permissions' - ], - 'tailored_audience_id' => [ - 'ads/accounts/:account_id/tailored_audience_changes', - 'ads/sandbox/accounts/:account_id/tailored_audience_changes' - ], - 'targeting_value' => [ - 'ads/accounts/:account_id/targeting_criteria', - 'ads/sandbox/accounts/:account_id/targeting_criteria' - ], - 'tweet_ids' => [ - 'ads/accounts/:account_id/promoted_tweets', - 'ads/sandbox/accounts/:account_id/promoted_tweets' - ], - 'type' => [ - 'ads/sandbox/accounts/:account_id/features', - 'ads/sandbox/accounts/:account_id/funding_instruments' - ], - 'url' => [ - 'account_activity/webhooks' - ], - 'user_id' => [ - 'ads/accounts/:account_id/promoted_accounts', - 'ads/sandbox/accounts/:account_id/promoted_accounts' - ], - 'video_media_id' => [ - 'ads/accounts/:account_id/videos', - 'ads/sandbox/accounts/:account_id/videos' - ] - ], - 'PUT' => [ - 'name' => [ - 'ads/accounts/:account_id/cards/image_conversation/:card_id', - 'ads/accounts/:account_id/cards/video_conversation/:card_id', - 'ads/accounts/:account_id/cards/website/:card_id', - 'ads/sandbox/accounts/:account_id/cards/image_conversation/:card_id', - 'ads/sandbox/accounts/:account_id/cards/video_conversation/:card_id', - 'ads/sandbox/accounts/:account_id/cards/website/:card_id' - ] - ] - ]; - foreach ($httpmethods_by_param as $httpmethod => $methods_by_param) { - foreach ($methods_by_param as $param => $methods) { - if (in_array($method, $methods) && isset($params[$param])) { - return $httpmethod; - } - } - } - - // async media/upload calls may request a status by GET - if ($method === 'media/upload' - && isset($params['command']) - && $params['command'] === 'STATUS' - ) { - return 'GET'; - } - - // prefer POST and PUT if parameters are set - if (count($params) > 0) { - if (in_array($method, $apimethods['POST'])) { - return 'POST'; - } - if (in_array($method, $apimethods['PUT'])) { - return 'PUT'; - } - } - - foreach ($apimethods as $httpmethod => $methods) { - if (in_array($method, $methods)) { - return $httpmethod; - } - } - throw new \Exception('Can\'t find HTTP method to use for "' . $method . '".'); - } - - /** - * Detects if API call should use multipart/form-data - * - * @param string $method The API method to call - * - * @return bool Whether the method should be sent as multipart - */ - protected function _detectMultipart($method) - { - $multiparts = [ - // Tweets - 'media/upload', - - // Users - // no multipart for these, for now: - //'account/update_profile_image', - //'account/update_profile_banner' - ]; - return in_array($method, $multiparts); - } - - /** - * Merge multipart string from parameters array - * - * @param string $method_template The method template to call - * @param string $border The multipart border - * @param array $params The parameters to send along - * - * @return string request - * @throws \Exception - */ - protected function _getMultipartRequestFromParams($method_template, $border, $params) - { - $request = ''; - foreach ($params as $key => $value) { - // is it an array? - if (is_array($value)) { - throw new CodebirdMediaException('Using URL-encoded parameters is not supported for uploading media.'); - } - $request .= - '--' . $border . "\r\n" - . 'Content-Disposition: form-data; name="' . $key . '"'; - - // check for filenames - $data = $this->_checkForFiles($method_template, $key, $value); - if ($data !== false) { - $value = $data; - } - - $request .= "\r\n\r\n" . $value . "\r\n"; - } - - return $request; - } - - /** - * Check for files - * - * @param string $method_template The method template to call - * @param string $key The parameter name - * @param string $value The possible file name or URL - * - * @return mixed - */ - protected function _checkForFiles($method_template, $key, $value) { - if (!array_key_exists($method_template, self::$_possible_files) - || !in_array($key, self::$_possible_files[$method_template]) - ) { - return false; - } - $data = $this->_buildBinaryBody($value); - if ($data === $value) { - return false; - } - return $data; - } - - - /** - * Detect filenames in upload parameters, - * build multipart request from upload params - * - * @param string $method The API method to call - * @param array $params The parameters to send along - * - * @return null|string - */ - protected function _buildMultipart($method, $params) - { - // well, files will only work in multipart methods - if (! $this->_detectMultipart($method)) { - return; - } - - // only check specific parameters - // method might have files? - if (! in_array($method, array_keys(self::$_possible_files))) { - return; - } - - $multipart_border = '--------------------' . $this->_nonce(); - $multipart_request = - $this->_getMultipartRequestFromParams($method, $multipart_border, $params) - . '--' . $multipart_border . '--'; - - return $multipart_request; - } - - /** - * Detect filenames in upload parameters - * - * @param mixed $input The data or file name to parse - * - * @return null|string - */ - protected function _buildBinaryBody($input) - { - if (// is it a file, a readable one? - @file_exists($input) - && @is_readable($input) - ) { - // try to read the file - $data = @file_get_contents($input); - if ($data !== false && strlen($data) !== 0) { - return $data; - } - } elseif (// is it a remote file? - filter_var($input, FILTER_VALIDATE_URL) - && preg_match('/^https?:\/\//', $input) - ) { - $data = $this->_fetchRemoteFile($input); - if ($data !== false) { - return $data; - } - } - return $input; - } - - /** - * Fetches a remote file - * - * @param string $url The URL to download from - * - * @return mixed The file contents or FALSE - * @throws \Exception - */ - protected function _fetchRemoteFile($url) - { - // try to fetch the file - if ($this->_use_curl) { - $connection = $this->_getCurlInitialization($url); - $this->_curl_setopt($connection, CURLOPT_RETURNTRANSFER, 1); - $this->_curl_setopt($connection, CURLOPT_HEADER, 0); - // no SSL validation for downloading media - $this->_curl_setopt($connection, CURLOPT_SSL_VERIFYPEER, 1); - $this->_curl_setopt($connection, CURLOPT_SSL_VERIFYHOST, 2); - $this->_curl_setopt($connection, CURLOPT_TIMEOUT_MS, $this->_timeouts['remote']); - $this->_curl_setopt($connection, CURLOPT_CONNECTTIMEOUT_MS, $this->_timeouts['remote'] / 2); - // find files that have been redirected - $this->_curl_setopt($connection, CURLOPT_FOLLOWLOCATION, true); - // process compressed images - $this->_curl_setopt($connection, CURLOPT_ENCODING, 'gzip,deflate,sdch'); - $result = $this->_curl_exec($connection); - if ($result !== false - && $this->_curl_getinfo($connection, CURLINFO_HTTP_CODE) === 200 - ) { - return $result; - } - throw new CodebirdMediaException('Downloading a remote media file failed.'); - return false; - } - // no cURL - $contextOptions = [ - 'http' => [ - 'method' => 'GET', - 'protocol_version' => '1.1', - 'timeout' => $this->_timeouts['remote'] - ], - 'ssl' => [ - 'verify_peer' => false - ] - ]; - list($result, $headers) = $this->_getNoCurlInitialization($url, $contextOptions); - if ($result !== false - && preg_match('/^HTTP\/\d\.\d 200 OK$/', $headers[0]) - ) { - return $result; - } - throw new CodebirdMediaException('Downloading a remote media file failed.'); - return false; - } - - /** - * Detects if API call should use media endpoint - * - * @param string $method The API method to call - * - * @return bool Whether the method is defined in media API - */ - protected function _detectMedia($method) { - $medias = [ - 'media/metadata/create', - 'media/upload' - ]; - return in_array($method, $medias); - } - - /** - * Detects if API call should use JSON body - * - * @param string $method_template The API method to call - * - * @return bool Whether the method is defined as accepting JSON body - */ - protected function _detectJsonBody($method_template) { - $json_bodies = [ - 'ads/batch/accounts/:account_id/campaigns', - 'ads/batch/accounts/:account_id/line_items', - 'ads/batch/accounts/:account_id/targeting_criteria', - 'ads/sandbox/batch/accounts/:account_id/campaigns', - 'ads/sandbox/batch/accounts/:account_id/line_items', - 'ads/sandbox/batch/accounts/:account_id/targeting_criteria', - 'collections/entries/curate', - 'custom_profiles/new', - 'direct_messages/events/new', - 'direct_messages/indicate_typing', - 'direct_messages/mark_read', - 'direct_messages/welcome_messages/new', - 'direct_messages/welcome_messages/rules/new', - 'direct_messages/welcome_messages/update', - 'media/metadata/create', - 'tweets/search/30day/:env', - 'tweets/search/fullarchive/:env' - ]; - return in_array($method_template, $json_bodies); - } - - /** - * Detects if API call should use binary body - * - * @param string $method_template The API method to call - * - * @return bool Whether the method is defined as accepting binary body - */ - protected function _detectBinaryBody($method_template) { - $binary = [ - 'ton/bucket/:bucket', - 'ton/bucket/:bucket?resumable=true', - 'ton/bucket/:bucket/:file?resumable=true&resumeId=:resumeId' - ]; - return in_array($method_template, $binary); - } - - /** - * Detects if API call should use streaming endpoint, and if yes, which one - * - * @param string $method The API method to call - * - * @return string|false Variant of streaming API to be used - */ - protected function _detectStreaming($method) { - $streamings = [ - 'public' => [ - 'statuses/sample', - 'statuses/filter' - ] - ]; - foreach ($streamings as $key => $values) { - if (in_array($method, $values)) { - return $key; - } - } - - return false; - } - - /** - * Builds the complete API endpoint url - * - * @param string $method The API method to call - * @param string $method_template The API method to call - * - * @return string The URL to send the request to - */ - protected function _getEndpoint($method, $method_template) - { - $url = self::$_endpoints['rest'] . $method . '.json'; - if (substr($method_template, 0, 5) === 'oauth') { - $url = self::$_endpoints['oauth'] . $method; - } elseif ($this->_detectMedia($method_template)) { - $url = self::$_endpoints['media'] . $method . '.json'; - } elseif ($method_template === 'statuses/oembed') { - $url = self::$_endpoints['publish'] . 'oembed'; - } elseif ($variant = $this->_detectStreaming($method_template)) { - $url = self::$_endpoints['streaming'][$variant] . $method . '.json'; - } elseif ($this->_detectBinaryBody($method_template)) { - $url = self::$_endpoints['ton'] . $method; - } elseif (substr($method_template, 0, 12) === 'ads/sandbox/') { - $url = self::$_endpoints['ads']['sandbox'] . substr($method, 12); - } elseif (substr($method_template, 0, 4) === 'ads/') { - $url = self::$_endpoints['ads']['production'] . substr($method, 4); - } - return $url; - } - - /** - * Calls the API - * - * @param string $httpmethod The HTTP method to use for making the request - * @param string $method The API method to call - * @param string $method_template The API method template to call - * @param array optional $params The parameters to send along - * @param bool optional $multipart Whether to use multipart/form-data - * @param bool optional $app_only_auth Whether to use app-only bearer authentication - * - * @return string The API reply, encoded in the set return_format - * @throws \Exception - */ - - protected function _callApi($httpmethod, $method, $method_template, $params = [], $multipart = false, $app_only_auth = false) - { - if (! $app_only_auth - && $this->_oauth_token === null - && substr($method, 0, 5) !== 'oauth' - ) { - throw new CodebirdCredentialsException('To call this API, the OAuth access token must be set.'); - } - // use separate API access for streaming API - if ($this->_detectStreaming($method) !== false) { - return $this->_callApiStreaming($httpmethod, $method, $method_template, $params, $app_only_auth); - } - - if ($this->_use_curl) { - return $this->_callApiCurl($httpmethod, $method, $method_template, $params, $multipart, $app_only_auth); - } - return $this->_callApiNoCurl($httpmethod, $method, $method_template, $params, $multipart, $app_only_auth); - } - - /** - * Calls the API using cURL - * - * @param string $httpmethod The HTTP method to use for making the request - * @param string $method The API method to call - * @param string $method_template The API method template to call - * @param array optional $params The parameters to send along - * @param bool optional $multipart Whether to use multipart/form-data - * @param bool optional $app_only_auth Whether to use app-only bearer authentication - * - * @return string The API reply, encoded in the set return_format - * @throws \Exception - */ - - protected function _callApiCurl( - $httpmethod, $method, $method_template, $params = [], $multipart = false, $app_only_auth = false - ) - { - list ($authorization, $url, $params, $request_headers) - = $this->_callApiPreparations( - $httpmethod, $method, $method_template, $params, $multipart, $app_only_auth - ); - - $connection = $this->_getCurlInitialization($url); - $request_headers[] = 'Authorization: ' . $authorization; - $request_headers[] = 'Expect:'; - - if ($httpmethod !== 'GET') { - $this->_curl_setopt($connection, CURLOPT_POST, 1); - $this->_curl_setopt($connection, CURLOPT_POSTFIELDS, $params); - if (in_array($httpmethod, ['POST', 'PUT', 'DELETE'])) { - $this->_curl_setopt($connection, CURLOPT_CUSTOMREQUEST, $httpmethod); - } - } - - $this->_curl_setopt($connection, CURLOPT_HTTPHEADER, $request_headers); - $this->_curl_setopt($connection, CURLOPT_TIMEOUT_MS, $this->_timeouts['request']); - $this->_curl_setopt($connection, CURLOPT_CONNECTTIMEOUT_MS, $this->_timeouts['connect']); - - $result = $this->_curl_exec($connection); - - // catch request errors - if ($result === false) { - throw new \Exception('Request error for API call: ' . $this->_curl_error($connection)); - } - - // certificate validation results - $validation_result = $this->_curl_errno($connection); - $this->_validateSslCertificate($validation_result); - - $httpstatus = $this->_curl_getinfo($connection, CURLINFO_HTTP_CODE); - list($headers, $reply) = $this->_parseApiHeaders($result); - // TON API & redirects - $reply = $this->_parseApiReplyPrefillHeaders($headers, $reply); - $reply = $this->_parseApiReply($reply); - $rate = $this->_getRateLimitInfo($headers); - - $reply = $this->_appendHttpStatusAndRate($reply, $httpstatus, $rate); - return $reply; - } - - /** - * Calls the API without cURL - * - * @param string $httpmethod The HTTP method to use for making the request - * @param string $method The API method to call - * @param string $method_template The API method template to call - * @param array optional $params The parameters to send along - * @param bool optional $multipart Whether to use multipart/form-data - * @param bool optional $app_only_auth Whether to use app-only bearer authentication - * - * @return string The API reply, encoded in the set return_format - * @throws \Exception - */ - - protected function _callApiNoCurl( - $httpmethod, $method, $method_template, $params = [], $multipart = false, $app_only_auth = false - ) - { - list ($authorization, $url, $params, $request_headers) - = $this->_callApiPreparations( - $httpmethod, $method, $method_template, $params, $multipart, $app_only_auth - ); - - $hostname = parse_url($url, PHP_URL_HOST); - if ($hostname === false) { - throw new CodebirdEndpointException('Incorrect API endpoint host.'); - } - - $request_headers[] = 'Authorization: ' . $authorization; - $request_headers[] = 'Accept: */*'; - $request_headers[] = 'Connection: Close'; - if ($httpmethod !== 'GET' && ! $multipart) { - $request_headers[] = 'Content-Type: application/x-www-form-urlencoded'; - } - - $contextOptions = [ - 'http' => [ - 'method' => $httpmethod, - 'protocol_version' => '1.1', - 'header' => implode("\r\n", $request_headers), - 'timeout' => $this->_timeouts['request'] / 1000, - 'content' => in_array($httpmethod, ['POST', 'PUT']) ? $params : null, - 'ignore_errors' => true - ] - ]; - - list($reply, $headers) = $this->_getNoCurlInitialization($url, $contextOptions, $hostname); - $result = ''; - foreach ($headers as $header) { - $result .= $header . "\r\n"; - } - $result .= "\r\n" . $reply; - - // find HTTP status - $httpstatus = $this->_getHttpStatusFromHeaders($headers); - list($headers, $reply) = $this->_parseApiHeaders($result); - // TON API & redirects - $reply = $this->_parseApiReplyPrefillHeaders($headers, $reply); - $reply = $this->_parseApiReply($reply); - $rate = $this->_getRateLimitInfo($headers); - - $reply = $this->_appendHttpStatusAndRate($reply, $httpstatus, $rate); - return $reply; - } - - /** - * Do preparations to make the API GET call - * - * @param string $httpmethod The HTTP method to use for making the request - * @param string $url The URL to call - * @param array $params The parameters to send along - * @param bool $app_only_auth Whether to use app-only bearer authentication - * - * @return string[] (string authorization, string url) - */ - protected function _callApiPreparationsGet( - $httpmethod, $url, $params, $app_only_auth - ) { - return [ - $app_only_auth ? null : $this->_sign($httpmethod, $url, $params), - json_encode($params) === '[]' ? $url : $url . '?' . http_build_query($params) - ]; - } - - /** - * Do preparations to make the API POST call - * - * @param string $httpmethod The HTTP method to use for making the request - * @param string $url The URL to call - * @param string $method The API method to call - * @param string $method_template The API method template to call - * @param array $params The parameters to send along - * @param bool $multipart Whether to use multipart/form-data - * @param bool $app_only_auth Whether to use app-only bearer authentication - * - * @return array (string authorization, array params, array request_headers) - */ - protected function _callApiPreparationsPost( - $httpmethod, $url, $method, $method_template, $params, $multipart, $app_only_auth - ) { - $authorization = null; - $request_headers = []; - if ($multipart) { - if (! $app_only_auth) { - $authorization = $this->_sign($httpmethod, $url, []); - } - $params = $this->_buildMultipart($method, $params); - $first_newline = strpos($params, "\r\n"); - $multipart_boundary = substr($params, 2, $first_newline - 2); - $request_headers[] = 'Content-Type: multipart/form-data; boundary=' - . $multipart_boundary; - } elseif ($this->_detectJsonBody($method_template)) { - $authorization = $this->_sign($httpmethod, $url, []); - $params = json_encode($params); - $request_headers[] = 'Content-Type: application/json'; - } elseif ($this->_detectBinaryBody($method_template)) { - // transform parametric headers to real headers - foreach ([ - 'Content-Length', - 'Content-Range', - 'Content-Type', - 'X-TON-Content-Type', - 'X-TON-Content-Length', - 'X-TON-Expires' - ] as $key) { - if (isset($params[$key])) { - $request_headers[] = $key . ': ' . $params[$key]; - unset($params[$key]); - } - } - $sign_params = []; - parse_str(parse_url($method, PHP_URL_QUERY), $sign_params); - if ($sign_params === null) { - $sign_params = []; - } - $authorization = $this->_sign($httpmethod, $url, $sign_params); - if (isset($params['media'])) { - $params = $this->_buildBinaryBody($params['media']); - } else { - // resumable upload - $params = []; - } - } else { - // check for possible files in non-multipart methods - foreach ($params as $key => $value) { - $data = $this->_checkForFiles($method_template, $key, $value); - if ($data !== false) { - $params[$key] = base64_encode($data); - } - } - if (! $app_only_auth) { - $authorization = $this->_sign($httpmethod, $url, $params); - } - $params = http_build_query($params); - } - return [$authorization, $params, $request_headers]; - } - - /** - * Appends HTTP status and rate limiting info to the reply - * - * @param array|object|string $reply The reply to append to - * @param string $httpstatus The HTTP status code to append - * @param mixed $rate The rate limiting info to append - */ - protected function _appendHttpStatusAndRate($reply, $httpstatus, $rate) - { - switch ($this->_return_format) { - case CODEBIRD_RETURNFORMAT_ARRAY: - $reply['httpstatus'] = $httpstatus; - $reply['rate'] = $rate; - break; - case CODEBIRD_RETURNFORMAT_OBJECT: - $reply->httpstatus = $httpstatus; - $reply->rate = $rate; - break; - case CODEBIRD_RETURNFORMAT_JSON: - $reply = $this->_json_decode($reply); - $reply->httpstatus = $httpstatus; - $reply->rate = $rate; - $reply = json_encode($reply); - break; - } - return $reply; - } - - /** - * Get Bearer authorization string - * - * @return string authorization - * @throws \Exception - */ - protected function _getBearerAuthorization() - { - if (self::$_consumer_key === null - && self::$_bearer_token === null - ) { - throw new CodebirdCredentialsException('To make an app-only auth API request, consumer key or bearer token must be set.'); - } - // automatically fetch bearer token, if necessary - if (self::$_bearer_token === null) { - $this->oauth2_token(); - } - return 'Bearer ' . self::$_bearer_token; - } - - /** - * Do preparations to make the API call - * - * @param string $httpmethod The HTTP method to use for making the request - * @param string $method The API method to call - * @param string $method_template The API method template to call - * @param array $params The parameters to send along - * @param bool $multipart Whether to use multipart/form-data - * @param bool $app_only_auth Whether to use app-only bearer authentication - * - * @return array (string authorization, string url, array params, array request_headers) - */ - protected function _callApiPreparations( - $httpmethod, $method, $method_template, $params, $multipart, $app_only_auth - ) - { - $url = $this->_getEndpoint($method, $method_template); - $request_headers = []; - if ($httpmethod === 'GET') { - // GET - list ($authorization, $url) = - $this->_callApiPreparationsGet($httpmethod, $url, $params, $app_only_auth); - } else { - // POST - list ($authorization, $params, $request_headers) = - $this->_callApiPreparationsPost($httpmethod, $url, $method, $method_template, $params, $multipart, $app_only_auth); - } - if ($app_only_auth) { - $authorization = $this->_getBearerAuthorization(); - } - - return [ - $authorization, $url, $params, $request_headers - ]; - } - - /** - * Calls the streaming API - * - * @param string $httpmethod The HTTP method to use for making the request - * @param string $method The API method to call - * @param string $method_template The API method template to call - * @param array optional $params The parameters to send along - * @param bool optional $app_only_auth Whether to use app-only bearer authentication - * - * @return void - * @throws \Exception - */ - - protected function _callApiStreaming( - $httpmethod, $method, $method_template, $params = [], $app_only_auth = false - ) - { - if ($this->_streaming_callback === null) { - throw new \Exception('Set streaming callback before consuming a stream.'); - } - - $params['delimited'] = 'length'; - - list ($authorization, $url, $params, $request_headers) - = $this->_callApiPreparations( - $httpmethod, $method, $method_template, $params, false, $app_only_auth - ); - - $hostname = parse_url($url, PHP_URL_HOST); - $path = parse_url($url, PHP_URL_PATH); - $query = parse_url($url, PHP_URL_QUERY); - if ($hostname === false) { - throw new CodebirdEndpointException('Incorrect API endpoint host.'); - } - - $request_headers[] = 'Authorization: ' . $authorization; - $request_headers[] = 'Accept: */*'; - if ($httpmethod !== 'GET') { - $request_headers[] = 'Content-Type: application/x-www-form-urlencoded'; - $request_headers[] = 'Content-Length: ' . strlen($params); - } - - $errno = 0; - $errstr = ''; - $connection = stream_socket_client( - 'ssl://' . $hostname . ':443', - $errno, $errstr, - $this->_timeouts['connect'], - STREAM_CLIENT_CONNECT - ); - - // send request - $request = $httpmethod . ' ' - . $path . ($query ? '?' . $query : '') . " HTTP/1.1\r\n" - . 'Host: ' . $hostname . "\r\n" - . implode("\r\n", $request_headers) - . "\r\n\r\n"; - if ($httpmethod !== 'GET') { - $request .= $params; - } - fputs($connection, $request); - stream_set_blocking($connection, 0); - stream_set_timeout($connection, 0); - - // collect headers - do { - $result = stream_get_line($connection, 1048576, "\r\n\r\n"); - } while(!$result); - $headers = explode("\r\n", $result); - - // find HTTP status - $httpstatus = $this->_getHttpStatusFromHeaders($headers); - list($headers,) = $this->_parseApiHeaders($result); - $rate = $this->_getRateLimitInfo($headers); - - if ($httpstatus !== '200') { - $reply = [ - 'httpstatus' => $httpstatus, - 'rate' => $rate - ]; - switch ($this->_return_format) { - case CODEBIRD_RETURNFORMAT_ARRAY: - return $reply; - case CODEBIRD_RETURNFORMAT_OBJECT: - return (object) $reply; - case CODEBIRD_RETURNFORMAT_JSON: - return json_encode($reply); - } - } - - $signal_function = function_exists('pcntl_signal_dispatch'); - $data = ''; - $last_message = $this->_time(); - $message_length = 0; - - while (!feof($connection)) { - // call signal handlers, if any - if ($signal_function) { - pcntl_signal_dispatch(); - } - $connection_array = [$connection]; - $write = $except = null; - if (false === ($num_changed_streams = stream_select($connection_array, $write, $except, 0, 200000))) { - break; - } elseif ($num_changed_streams === 0) { - if ($this->_time() - $last_message >= 1) { - // deliver empty message, allow callback to cancel stream - $cancel_stream = $this->_deliverStreamingMessage(null); - if ($cancel_stream) { - break; - } - $last_message = $this->_time(); - } - continue; - } - $chunk_length = fgets($connection, 10); - if ($chunk_length === '' || !$chunk_length = hexdec($chunk_length)) { - continue; - } - - $chunk = ''; - do { - $chunk .= fread($connection, $chunk_length); - $chunk_length -= strlen($chunk); - } while($chunk_length > 0); - - if(0 === $message_length) { - $message_length = (int) strstr($chunk, "\r\n", true); - if ($message_length) { - $chunk = substr($chunk, strpos($chunk, "\r\n") + 2); - } else { - continue; - } - - $data = $chunk; - } else { - $data .= $chunk; - } - - if (strlen($data) < $message_length) { - continue; - } - - $reply = $this->_parseApiReply($data); - switch ($this->_return_format) { - case CODEBIRD_RETURNFORMAT_ARRAY: - $reply['httpstatus'] = $httpstatus; - $reply['rate'] = $rate; - break; - case CODEBIRD_RETURNFORMAT_OBJECT: - $reply->httpstatus = $httpstatus; - $reply->rate = $rate; - break; - } - - $cancel_stream = $this->_deliverStreamingMessage($reply); - if ($cancel_stream) { - fclose($connection); - break; - } - - $data = ''; - $message_length = 0; - $last_message = $this->_time(); - } - - return; - } - - /** - * Calls streaming callback with received message - * - * @param string|array|object message - * - * @return bool Whether to cancel streaming - */ - protected function _deliverStreamingMessage($message) - { - return call_user_func($this->_streaming_callback, $message); - } - - /** - * Parses the API reply to separate headers from the body - * - * @param string $reply The actual raw HTTP request reply - * - * @return array (headers, reply) - */ - protected function _parseApiHeaders($reply) { - // split headers and body - $headers = []; - $reply = explode("\r\n\r\n", $reply, 4); - - // check if using proxy - $proxy_tester = strtolower(substr($reply[0], 0, 35)); - if ($proxy_tester === 'http/1.0 200 connection established' - || $proxy_tester === 'http/1.1 200 connection established' - ) { - array_shift($reply); - } - - $headers_array = explode("\r\n", $reply[0]); - foreach ($headers_array as $header) { - $header_array = explode(': ', $header, 2); - $key = $header_array[0]; - $value = ''; - if (count($header_array) > 1) { - $value = $header_array[1]; - } - $headers[$key] = $value; - } - - if (count($reply) > 1) { - $reply = $reply[1]; - } else { - $reply = ''; - } - - return [$headers, $reply]; - } - - /** - * Parses the API headers to return Location and Ton API headers - * - * @param array $headers The headers list - * @param string $reply The actual HTTP body - * - * @return string $reply - */ - protected function _parseApiReplyPrefillHeaders($headers, $reply) - { - if ($reply === '' && (isset($headers['Location']) || isset($headers['location']))) { - $reply = [ - 'Location' => isset($headers['Location']) ? $headers['Location'] : $headers['location'] - ]; - if (isset($headers['X-TON-Min-Chunk-Size'])) { - $reply['X-TON-Min-Chunk-Size'] = $headers['X-TON-Min-Chunk-Size']; - } - if (isset($headers['X-TON-Max-Chunk-Size'])) { - $reply['X-TON-Max-Chunk-Size'] = $headers['X-TON-Max-Chunk-Size']; - } - if (isset($headers['Range'])) { - $reply['Range'] = $headers['Range']; - } - $reply = json_encode($reply); - } - return $reply; - } - - /** - * Parses the API reply to encode it in the set return_format - * - * @param string $reply The actual HTTP body, JSON-encoded or URL-encoded - * - * @return array|string|object The parsed reply - */ - protected function _parseApiReply($reply) - { - $need_array = $this->_return_format === CODEBIRD_RETURNFORMAT_ARRAY; - if ($reply === '[]') { - switch ($this->_return_format) { - case CODEBIRD_RETURNFORMAT_ARRAY: - return []; - case CODEBIRD_RETURNFORMAT_JSON: - return '{}'; - case CODEBIRD_RETURNFORMAT_OBJECT: - return new \stdClass; - } - } - if (! $parsed = $this->_json_decode($reply, $need_array)) { - if ($reply) { - // assume query format - $reply = explode('&', $reply); - foreach ($reply as $element) { - if (stristr($element, '=')) { - list($key, $value) = explode('=', $element, 2); - $parsed[$key] = $value; - } else { - $parsed['message'] = $element; - } - } - } - $reply = json_encode($parsed); - } - switch ($this->_return_format) { - case CODEBIRD_RETURNFORMAT_ARRAY: - return $parsed; - case CODEBIRD_RETURNFORMAT_JSON: - return $reply; - case CODEBIRD_RETURNFORMAT_OBJECT: - return (object) $parsed; - } - return $parsed; - } - -} - -/** - * Catch errors when authtoken is expired - */ -class CodebirdAuthException extends \Exception { - -} - - -/** - * Catch error when credentials are not set correclty - */ -class CodebirdCredentialsException extends \Exception { - -} - -/** - * Catch errors r elated to bad endpoi ts - */ -class CodebirdEndpointException extends \Exception { - -} - -/* - * Catch errors relatedto media - */ - -class CodebirdMediaException extends \Exception { - -} - diff --git a/twitter/vendor/jublonet/codebird-php/test/README b/twitter/vendor/jublonet/codebird-php/test/README deleted file mode 100644 index fd344c4ad..000000000 --- a/twitter/vendor/jublonet/codebird-php/test/README +++ /dev/null @@ -1,16 +0,0 @@ -The following methods are not covered by unit tests yet: - -_getMultipartRequestFromParams -_checkForFiles -_buildMultipart -_buildBinaryBody - -_callApi -_callApiCurl -_callApiNoCurl -_callApiPreparationsGet -_callApiPreparationsPost -_callApiPreparations - -_callApiStreaming -_deliverStreamingMessage diff --git a/twitter/vendor/jublonet/codebird-php/test/codebirdm.php b/twitter/vendor/jublonet/codebird-php/test/codebirdm.php deleted file mode 100644 index 6cbae4a58..000000000 --- a/twitter/vendor/jublonet/codebird-php/test/codebirdm.php +++ /dev/null @@ -1,204 +0,0 @@ - - * @copyright 2010-2016 Jublo Solutions - * @license https://opensource.org/licenses/GPL-3.0 GNU General Public License 3.0 - * @link https://github.com/jublonet/codebird-php - */ - -/** - * Codebird testing class with mock data source - * - * @package codebird-test - */ -class CodebirdM extends CodebirdT -{ - /** - * Stores the request data - */ - protected $_requests = []; - - /** - * Mock API replies - */ - protected static $_mock_replies = [ - 'default' => [ - 'httpstatus' => 404, - 'reply' => "HTTP/1.1 404 Not Found\r\ncontent-length: 68\r\ncontent-type: application/json;charset=utf-8\r\ndate: Sun, 06 Dec 2015 14:43:28 GMT\r\nserver: tsa_b\r\nset-cookie: guest_id=v1%3A144941300885288055; Domain=.twitter.com; Path=/; Expires=Tue, 05-Dec-2017 14:43:28 UTC\r\nstrict-transport-security: max-age=631138519\r\nx-connection-hash: 12218aef9e9757609afb08e661fa3b9b\r\nx-response-time: 2\r\n\r\n{\"errors\":[{\"message\":\"Sorry, that page does not exist\",\"code\":34}]}" - ], - 'proxy1' => [ - 'httpstatus' => 404, - 'reply' => "HTTP/1.1 200 Connection Established\r\n\r\nHTTP/1.1 404 Not Found\r\ncontent-length: 68\r\ncontent-type: application/json;charset=utf-8\r\ndate: Sun, 06 Dec 2015 14:43:28 GMT\r\nserver: tsa_b\r\nset-cookie: guest_id=v1%3A144941300885288055; Domain=.twitter.com; Path=/; Expires=Tue, 05-Dec-2017 14:43:28 UTC\r\nstrict-transport-security: max-age=631138519\r\nx-connection-hash: 12218aef9e9757609afb08e661fa3b9b\r\nx-response-time: 2\r\n\r\n{\"errors\":[{\"message\":\"Sorry, that page does not exist\",\"code\":34}]}" - ], - 'GET http://www.example.org/found.txt' => [ - 'httpstatus' => 200, - 'reply' => "HTTP/1.1 200 OK\r\nContent-Length: 12\r\n\r\nA test file." - ], - 'GET https://api.twitter.com/1.1/users/show.json?screen_name=TwitterAPI' => [ - 'httpstatus' => 200, - 'reply' => "HTTP/1.1 200 OK\r\ncache-control: no-cache, no-store, must-revalidate, pre-check=0, post-check=0\r\ncontent-disposition: attachment; filename=json.json\r\ncontent-length: 2801\r\ncontent-type: application/json;charset=utf-8\r\ndate: Sun, 06 Dec 2015 14:55:46 GMT\r\nexpires: Tue, 31 Mar 1981 05:00:00 GMT\r\nlast-modified: Sun, 06 Dec 2015 14:55:46 GMT\r\npragma: no-cache\r\nserver: tsa_b\r\nset-cookie: lang=en-gb; Path=/\r\nset-cookie: guest_id=v1%3A144941374684866365; Domain=.twitter.com; Path=/; Expires=Tue, 05-Dec-2017 14:55:46 UTC\r\nstatus: 200 OK\r\nstrict-transport-security: max-age=631138519\r\nx-access-level: read-write-directmessages\r\nx-connection-hash: 1906b689730b92318bccf65b496f74d0\r\nx-content-type-options: nosniff\r\nx-frame-options: SAMEORIGIN\r\nx-rate-limit-limit: 181\r\nx-rate-limit-remaining: 177\r\nx-rate-limit-reset: 1449414513\r\nx-response-time: 44\r\nx-transaction: 663cc05c64857ba0\r\nx-twitter-response-tags: BouncerCompliant\r\nx-xss-protection: 1; mode=block\r\n\r\n{\"id\":6253282,\"id_str\":\"6253282\",\"name\":\"Twitter API\",\"screen_name\":\"twitterapi\",\"location\":\"San Francisco, CA\",\"profile_location\":null,\"description\":\"The Real Twitter API. I tweet about API changes, service issues and happily answer questions about Twitter and our API. Don't get an answer? It's on my website.\",\"url\":\"http:\/\/t.co\/78pYTvWfJd\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"http:\/\/t.co\/78pYTvWfJd\",\"expanded_url\":\"http:\/\/dev.twitter.com\",\"display_url\":\"dev.twitter.com\",\"indices\":[0,22]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":4993679,\"friends_count\":48,\"listed_count\":13001,\"created_at\":\"Wed May 23 06:01:13 +0000 2007\",\"favourites_count\":27,\"utc_offset\":-28800,\"time_zone\":\"Pacific Time (US & Canada)\",\"geo_enabled\":true,\"verified\":true,\"statuses_count\":3553,\"lang\":\"en\",\"status\":{\"created_at\":\"Tue Nov 24 08:56:07 +0000 2015\",\"id\":669077021138493440,\"id_str\":\"669077021138493440\",\"text\":\"Additional 64-bit entity ID migration coming in Feb 2016 https:\/\/t.co\/eQIGvw1rsJ\",\"source\":\"\u003ca href=\\\"https:\/\/about.twitter.com\/products\/tweetdeck\\\" rel=\\\"nofollow\\\"\u003eTweetDeck\u003c\/a\u003e\",\"truncated\":false,\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweet_count\":67,\"favorite_count\":79,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\/\/t.co\/eQIGvw1rsJ\",\"expanded_url\":\"https:\/\/twittercommunity.com\/t\/migration-of-twitter-core-entities-to-64-bit-ids\/56881\",\"display_url\":\"twittercommunity.com\/t\/migration-of\u2026\",\"indices\":[57,80]}]},\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"en\"},\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\/\/pbs.twimg.com\/profile_background_images\/656927849\/miyt9dpjz77sc0w3d4vj.png\",\"profile_background_image_url_https\":\"https:\/\/pbs.twimg.com\/profile_background_images\/656927849\/miyt9dpjz77sc0w3d4vj.png\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\/\/pbs.twimg.com\/profile_images\/2284174872\/7df3h38zabcvjylnyfe3_normal.png\",\"profile_image_url_https\":\"https:\/\/pbs.twimg.com\/profile_images\/2284174872\/7df3h38zabcvjylnyfe3_normal.png\",\"profile_banner_url\":\"https:\/\/pbs.twimg.com\/profile_banners\/6253282\/1431474710\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":false,\"default_profile_image\":false,\"following\":true,\"follow_request_sent\":false,\"notifications\":false}" - ], - 'POST https://api.twitter.com/oauth2/token' => [ - 'httpstatus' => 200, - 'reply' => "HTTP/1.1 200 OK\r\ncache-control: no-cache, no-store, must-revalidate, pre-check=0, post-check=0\r\ncontent-disposition: attachment; filename=json.json\r\ncontent-length: 52\r\ncontent-type: application/json;charset=utf-8\r\ndate: Sun, 06 Dec 2015 15:53:02 GMT\r\nexpires: Tue, 31 Mar 1981 05:00:00 GMT\r\nlast-modified: Sun, 06 Dec 2015 15:53:01 GMT\r\nml: S\r\npragma: no-cache\r\nserver: tsa_b\r\nset-cookie: guest_id=v1%3A144941718194388038; Domain=.twitter.com; Path=/; Expires=Tue, 05-Dec-2017 15:53:02 UTC\r\nstatus: 200 OK\r\nstrict-transport-security: max-age=631138519\r\nx-connection-hash: 97f4d4e6a33433b477510d8c58a0b026\r\nx-content-type-options: nosniff\r\nx-frame-options: DENY\r\nx-response-time: 87\r\nx-transaction: 6a0e5e8144d7e6df\r\nx-tsa-request-body-time: 164\r\nx-twitter-response-tags: BouncerCompliant\r\nx-ua-compatible: IE=edge,chrome=1\r\nx-xss-protection: 1; mode=block\r\n\r\n{\"token_type\":\"bearer\",\"access_token\":\"VqiO0n2HrKE\"}" - ] - ]; - - /** - * Gets a mock cURL handle - * @param string $url the URL for the curl initialization - * @return string connection ID - */ - protected function _curl_init($url = null) - { - $request = [ - 'url' => $url, - CURLOPT_RETURNTRANSFER => false - ]; - $id = mt_rand(); - $this->_requests[$id] = $request; - - return $id; - } - - /** - * Sets mock cURL parameters - * @param string $id connection ID - * @param int $option cURL option to set - * @param mixed $value Value to set for the option - * @return bool - */ - protected function _curl_setopt($id, $option, $value) - { - if (!isset($this->_requests[$id])) { - return false; - } - - $this->_requests[$id][$option] = $value; - - return true; - } - - /** - * Executes mock cURL transfer - * @param string $id connection ID - * @return bool|string - */ - protected function _curl_exec($id) - { - if (!isset($this->_requests[$id])) { - return false; - } - - $request = $this->_requests[$id]; - $url = $this->_requests[$id]['url']; - $reply = self::$_mock_replies['default']; - - $httpmethod = 'GET'; - if (isset($request[CURLOPT_POST]) && $request[CURLOPT_POST]) { - $httpmethod = 'POST'; - } - if (isset($request[CURLOPT_CUSTOMREQUEST])) { - $httpmethod = $request[CURLOPT_CUSTOMREQUEST]; - } - - $index = $httpmethod . ' ' . $url; - - if (isset(self::$_mock_replies[$index])) { - $reply = self::$_mock_replies[$index]; - } - - $this->_requests[$id][CURLINFO_HTTP_CODE] = $reply['httpstatus']; - $this->_requests[$id]['reply'] = $reply['reply']; - - if (! $this->_requests[$id][CURLOPT_HEADER] - && stristr($reply['reply'], "\r\n\r\n") - ) { - $reply_parts = explode("\r\n\r\n", $reply['reply'], 2); - $reply['reply'] = $reply_parts[1]; - } - - if ($this->_requests[$id][CURLOPT_RETURNTRANSFER]) { - return $reply['reply']; - } - - return true; - } - - /** - * Gets cURL error - * @param string $id connection ID - * @return string - */ - protected function _curl_error($id) - { - return ''; - } - - /** - * Gets cURL error - * @param string $id connection ID - * @return int - */ - protected function _curl_errno($id) - { - return 0; - } - - /** - * Gets info about cURL connection - * @param string $id connection ID - * @param int $opt option to get - * @return mixed - */ - protected function _curl_getinfo($id, $opt = 0) - { - if (!isset($this->_requests[$id])) { - return false; - } - - $request = $this->_requests[$id]; - - if (!$opt) { - return [ - 'url' => $request['url'], - 'http_code' => $request[CURLINFO_HTTP_CODE] - ]; - } - - if (isset($request[$opt])) { - return $request[$opt]; - } - - return false; - } - - /** - * Gets fake time - * @return int Timestamp - */ - protected function _time() - { - return 1412345678; - } - - /** - * Gets fake time - * @param bool $get_as_float - * @return int Timestamp - */ - protected function _microtime($get_as_float = false) - { - if ($get_as_float) { - return 1412345678.777; - } - return '777 1412345678'; - } -} diff --git a/twitter/vendor/jublonet/codebird-php/test/codebirdt.php b/twitter/vendor/jublonet/codebird-php/test/codebirdt.php deleted file mode 100644 index dd54dfc4a..000000000 --- a/twitter/vendor/jublonet/codebird-php/test/codebirdt.php +++ /dev/null @@ -1,97 +0,0 @@ - - * @copyright 2010-2016 Jublo Solutions - * @license https://opensource.org/licenses/GPL-3.0 GNU General Public License 3.0 - * @link https://github.com/jublonet/codebird-php - */ - -/** - * Codebird testing class - * - * @package codebird-test - */ -class CodebirdT extends Codebird -{ - /** - * Returns properties - * - * @param string $property The property to get - * - * @return mixed Property - */ - public function get($property) - { - if (property_exists($this, $property)) { - return $this->$property; - } - throw new \Exception('Property ' . $property . ' is not defined.'); - } - - /** - * Returns static properties - * - * @param string $property The property to get - * - * @return mixed Property - */ - public function getStatic($property) - { - if (property_exists($this, $property)) { - return static::$$property; - } - throw new \Exception('Static property ' . $property . ' is not defined.'); - } - - /** - * Calls methods - * - * @param string $property The property to get - * - * @return mixed Property - */ - public function call($method, $params = [], &$params2 = null) - { - $methods_byref = [ - '_mapFnToApiMethod', - '_mapFnInlineParams', - '_detectMethod' - ]; - if (in_array($method, $methods_byref)) { - return $this->$method($params, $params2); - } - if (method_exists($this, $method)) { - return call_user_func_array([$this, $method], $params); - } - throw new \Exception('Method ' . $method . ' is not defined.'); - } - - /** - * Calls methods - * - * @param string $property The property to get - * - * @return mixed Property - */ - public function callStatic($method, $params = []) - { - if (function_exists([self, $method])) { - return call_user_func_array([self, $method], $params); - } - throw new \Exception('Static method ' . $method . ' is not defined.'); - } - - /** - * Streaming callback test - */ - public static function streamingCallbackTest() - { - } -} diff --git a/twitter/vendor/jublonet/codebird-php/test/constant_tests.php b/twitter/vendor/jublonet/codebird-php/test/constant_tests.php deleted file mode 100644 index 2017e1c6c..000000000 --- a/twitter/vendor/jublonet/codebird-php/test/constant_tests.php +++ /dev/null @@ -1,40 +0,0 @@ - - * @copyright 2010-2018 Jublo Limited - * @license https://opensource.org/licenses/GPL-3.0 GNU General Public License 3.0 - * @link https://github.com/jublonet/codebird-php - */ - -/** - * Constant tests - * - * @package codebird-test - */ -class Constant_Test extends \PHPUnit\Framework\TestCase -{ - /** - * Tests if constants defined - */ - public function testConstants() - { - $constants = [ - 'CODEBIRD_RETURNFORMAT_OBJECT', - 'CODEBIRD_RETURNFORMAT_ARRAY', - 'CODEBIRD_RETURNFORMAT_JSON' - ]; - foreach ($constants as $constant) { - $this->assertTrue( - defined($constant), - $constant - ); - } - } -} diff --git a/twitter/vendor/jublonet/codebird-php/test/curl_tests.php b/twitter/vendor/jublonet/codebird-php/test/curl_tests.php deleted file mode 100644 index 3f49661b2..000000000 --- a/twitter/vendor/jublonet/codebird-php/test/curl_tests.php +++ /dev/null @@ -1,57 +0,0 @@ - - * @copyright 2010-2018 Jublo Limited - * @license https://opensource.org/licenses/GPL-3.0 GNU General Public License 3.0 - * @link https://github.com/jublonet/codebird-php - */ - -/** - * cURL tests - * - * @package codebird-test - */ -class Curl_Test extends \PHPUnit\Framework\TestCase -{ - /** - * Initialise Codebird class - * - * @return \Codebird\Codebird The Codebird class - */ - protected function getCB() - { - $cb = new CodebirdM(); - - return $cb; - } - - /** - * Tests _getCurlInitialization - */ - public function testGetCurlInitialization() - { - $cb = $this->getCB(); - $id = $cb->call('_getCurlInitialization', ['https://test']); - $this->assertEquals( - [ - 'url' => 'https://test', - CURLOPT_RETURNTRANSFER => 1, - CURLOPT_FOLLOWLOCATION => 0, - CURLOPT_HEADER => 1, - CURLOPT_SSL_VERIFYPEER => 1, - CURLOPT_SSL_VERIFYHOST => 2, - CURLOPT_CAINFO => substr(__DIR__, 0, -strlen(basename(__DIR__))) . 'src/cacert.pem', - CURLOPT_USERAGENT => 'codebird-php/' . $cb->getStatic('_version') - . ' +https://github.com/jublonet/codebird-php' - ], - $cb->get('_requests')[$id] - ); - } -} diff --git a/twitter/vendor/jublonet/codebird-php/test/detection_tests.php b/twitter/vendor/jublonet/codebird-php/test/detection_tests.php deleted file mode 100644 index 9114a2d78..000000000 --- a/twitter/vendor/jublonet/codebird-php/test/detection_tests.php +++ /dev/null @@ -1,288 +0,0 @@ - - * @copyright 2010-2018 Jublo Limited - * @license https://opensource.org/licenses/GPL-3.0 GNU General Public License 3.0 - * @link https://github.com/jublonet/codebird-php - */ - -/** - * Detection tests - * - * @package codebird-test - */ -class Detection_Test extends \PHPUnit\Framework\TestCase -{ - /** - * Initialise Codebird class - * - * @return \Codebird\Codebird The Codebird class - */ - protected function getCB() - { - $cb = new CodebirdM(); - - return $cb; - } - - /** - * Tests _detectMethod - * @expectedException \Exception - * @expectedExceptionMessage Can't find HTTP method to use for "non-existent". - */ - public function testDetectMethod1() - { - $cb = $this->getCB(); - $params = []; - $cb->call('_detectMethod', 'non-existent', $params); - } - - /** - * Tests _detectMethod - */ - public function testDetectMethod2() - { - $cb = $this->getCB(); - - // forced httpmethod - $params = ['httpmethod' => 'DELETE']; - $this->assertEquals( - 'DELETE', - $cb->call('_detectMethod', 'doesnt-matter', $params) - ); - - // normal detection - $params = []; - $post = ['httpmethod' => 'POST']; - $this->assertEquals('GET', $cb->call('_detectMethod', 'search/tweets', $params)); - $this->assertEquals('POST', $cb->call('_detectMethod', 'statuses/update', $params)); - $this->assertEquals('POST', $cb->call('_detectMethod', 'ads/sandbox/accounts', $post)); - $this->assertEquals( - 'PUT', - $cb->call( - '_detectMethod', - 'ton/bucket/:bucket/:file?resumable=true&resumeId=:resumeId', - $params - ) - ); - - // parameter-based detection - $this->assertEquals('GET', $cb->call('_detectMethod', 'account/settings', $params)); - $params = ['test' => 12]; - $this->assertEquals('POST', $cb->call('_detectMethod', 'account/settings', $params)); - - $params = []; - $this->assertEquals('POST', $cb->call('_detectMethod', 'media/upload', $params)); - $params = ['command' => 'STATUS']; - $this->assertEquals('GET', $cb->call('_detectMethod', 'media/upload', $params)); - - $httpmethods_by_param = [ - 'POST' => [ - 'campaign_id' => [ - 'ads/accounts/:account_id/line_items', - 'ads/sandbox/accounts/:account_id/line_items' - ], - 'name' => [ - 'ads/accounts/:account_id/app_lists', - 'ads/accounts/:account_id/campaigns', - 'ads/accounts/:account_id/cards/app_download', - 'ads/accounts/:account_id/cards/image_app_download', - 'ads/accounts/:account_id/cards/image_conversation', - 'ads/accounts/:account_id/cards/lead_gen', - 'ads/accounts/:account_id/cards/video_app_download', - 'ads/accounts/:account_id/cards/video_conversation', - 'ads/accounts/:account_id/cards/website', - 'ads/accounts/:account_id/tailored_audiences', - 'ads/accounts/:account_id/web_event_tags', - 'ads/sandbox/accounts/:account_id/app_lists', - 'ads/sandbox/accounts/:account_id/campaigns', - 'ads/sandbox/accounts/:account_id/cards/app_download', - 'ads/sandbox/accounts/:account_id/cards/image_app_download', - 'ads/sandbox/accounts/:account_id/cards/image_conversation', - 'ads/sandbox/accounts/:account_id/cards/lead_gen', - 'ads/sandbox/accounts/:account_id/cards/video_app_download', - 'ads/sandbox/accounts/:account_id/cards/video_conversation', - 'ads/sandbox/accounts/:account_id/cards/website', - 'ads/sandbox/accounts/:account_id/tailored_audiences', - 'ads/sandbox/accounts/:account_id/web_event_tags' - ], - 'tailored_audience_id' => [ - 'ads/accounts/:account_id/tailored_audience_changes', - 'ads/sandbox/accounts/:account_id/tailored_audience_changes' - ], - 'targeting_value' => [ - 'ads/accounts/:account_id/targeting_criteria', - 'ads/sandbox/accounts/:account_id/targeting_criteria' - ], - 'tweet_ids' => [ - 'ads/accounts/:account_id/promoted_tweets', - 'ads/sandbox/accounts/:account_id/promoted_tweets' - ], - 'user_id' => [ - 'ads/accounts/:account_id/promoted_accounts', - 'ads/sandbox/accounts/:account_id/promoted_accounts' - ], - 'video_media_id' => [ - 'ads/accounts/:account_id/videos', - 'ads/sandbox/accounts/:account_id/videos' - ] - ], - 'PUT' => [ - 'name' => [ - 'ads/accounts/:account_id/cards/image_conversation/:card_id', - 'ads/accounts/:account_id/cards/video_conversation/:card_id', - 'ads/accounts/:account_id/cards/website/:card_id', - 'ads/sandbox/accounts/:account_id/cards/image_conversation/:card_id', - 'ads/sandbox/accounts/:account_id/cards/video_conversation/:card_id', - 'ads/sandbox/accounts/:account_id/cards/website/:card_id' - ] - ] - ]; - foreach ($httpmethods_by_param as $httpmethod => $methods_by_param) { - foreach ($methods_by_param as $param => $methods) { - foreach ($methods as $method) { - $params = []; - $this->assertEquals( - 'GET', - $cb->call('_detectMethod', $method, $params), - $method - ); - $params[$param] = '123'; - $this->assertEquals( - $httpmethod, - $cb->call('_detectMethod', $method, $params), - $method - ); - } - } - } - } - - /** - * Tests _detectMultipart - */ - public function testDetectMultipart() - { - $cb = $this->getCB(); - $this->assertFalse($cb->call('_detectMultipart', ['statuses/update'])); - $this->assertTrue($cb->call('_detectMultipart', ['media/upload'])); - } - - /** - * Tests _detectMedia - */ - public function testDetectMedia() - { - $cb = $this->getCB(); - $this->assertFalse($cb->call('_detectMedia', ['statuses/update'])); - $this->assertTrue($cb->call('_detectMedia', ['media/upload'])); - } - - /** - * Tests _detectJsonBody - */ - public function testDetectJsonBody() - { - $cb = $this->getCB(); - $this->assertFalse($cb->call('_detectJsonBody', ['statuses/update'])); - $this->assertTrue($cb->call('_detectJsonBody', ['collections/entries/curate'])); - $this->assertTrue($cb->call('_detectJsonBody', ['ads/batch/accounts/:account_id/targeting_criteria'])); - } - - /** - * Tests _detectBinaryBody - */ - public function testDetectBinaryBody() - { - $cb = $this->getCB(); - $this->assertFalse($cb->call('_detectBinaryBody', ['statuses/update'])); - $this->assertTrue($cb->call('_detectBinaryBody', ['ton/bucket/:bucket'])); - $this->assertTrue($cb->call('_detectBinaryBody', ['ton/bucket/:bucket?resumable=true'])); - $this->assertTrue($cb->call( - '_detectBinaryBody', - ['ton/bucket/:bucket/:file?resumable=true&resumeId=:resumeId'] - )); - } - - /** - * Tests _detectStreaming - */ - public function testDetectStreaming() - { - $cb = $this->getCB(); - $this->assertFalse($cb->call('_detectStreaming', ['statuses/update'])); - $this->assertEquals('public', $cb->call('_detectStreaming', ['statuses/sample'])); - $this->assertEquals('public', $cb->call('_detectStreaming', ['statuses/filter'])); - } - - /** - * Tests _getEndpoint - */ - public function testGetEndpoint() - { - $cb = $this->getCB(); - $this->assertEquals( - 'https://api.twitter.com/1.1/statuses/update.json', - $cb->call('_getEndpoint', ['statuses/update', 'statuses/update']), - 'statuses/update' - ); - $this->assertEquals( - 'https://api.twitter.com/oauth/authenticate', - $cb->call('_getEndpoint', ['oauth/authenticate', 'oauth/authenticate']), - 'oauth/authenticate' - ); - $this->assertEquals( - 'https://api.twitter.com/oauth2/token', - $cb->call('_getEndpoint', ['oauth2/token', 'oauth2/token']), - 'oauth2/token' - ); - $this->assertEquals( - 'https://upload.twitter.com/1.1/media/upload.json', - $cb->call('_getEndpoint', ['media/upload', 'media/upload']), - 'media/upload' - ); - $this->assertEquals( - 'https://upload.twitter.com/1.1/media/metadata/create.json', - $cb->call('_getEndpoint', ['media/metadata/create', 'media/metadata/create']), - 'media/metadata/create' - ); - $this->assertEquals( - 'https://publish.twitter.com/oembed', - $cb->call('_getEndpoint', ['statuses/oembed', 'statuses/oembed']), - 'statuses/oembed' - ); - $this->assertEquals( - 'https://stream.twitter.com/1.1/statuses/filter.json', - $cb->call('_getEndpoint', ['statuses/filter', 'statuses/filter']), - 'statuses/filter' - ); - $this->assertEquals( - 'https://ton.twitter.com/1.1/ton/bucket/ta_partner', - $cb->call('_getEndpoint', ['ton/bucket/ta_partner', 'ton/bucket/:bucket']), - 'ton/bucket/:bucket' - ); - $this->assertEquals( - 'https://ads-api.twitter.com/2/accounts/1234/campaigns', - $cb->call( - '_getEndpoint', - ['ads/accounts/1234/campaigns', 'ads/accounts/:account_id/campaigns'] - ), - 'ads/accounts/:account_id/campaigns' - ); - $this->assertEquals( - 'https://ads-api-sandbox.twitter.com/2/accounts/1234/campaigns', - $cb->call( - '_getEndpoint', - ['ads/sandbox/accounts/1234/campaigns', 'ads/sandbox/accounts/:account_id/campaigns'] - ), - 'ads/sandbox/accounts/:account_id/campaigns' - ); - } -} diff --git a/twitter/vendor/jublonet/codebird-php/test/environment_test.php b/twitter/vendor/jublonet/codebird-php/test/environment_test.php deleted file mode 100644 index b5d6d0437..000000000 --- a/twitter/vendor/jublonet/codebird-php/test/environment_test.php +++ /dev/null @@ -1,40 +0,0 @@ - - * @copyright 2010-2018 Jublo Limited - * @license https://opensource.org/licenses/GPL-3.0 GNU General Public License 3.0 - * @link https://github.com/jublonet/codebird-php - */ - -/** - * Environment tests - * - * @package codebird-test - */ -class Environment_Test extends \PHPUnit\Framework\TestCase -{ - /** - * Tests PHP version - */ - public function testPhpVersion() - { - $this->assertTrue( - version_compare('7.1', phpversion(), '<='), - 'Codebird requires PHP 7.1 or above' - ); - } - - /** - * Tests OpenSSL module availability - */ - public function testOpenssl() - { - $this->assertTrue(function_exists('openssl_open')); - } -} diff --git a/twitter/vendor/jublonet/codebird-php/test/media_tests.php b/twitter/vendor/jublonet/codebird-php/test/media_tests.php deleted file mode 100644 index f4ab92617..000000000 --- a/twitter/vendor/jublonet/codebird-php/test/media_tests.php +++ /dev/null @@ -1,56 +0,0 @@ - - * @copyright 2010-2018 Jublo Limited - * @license https://opensource.org/licenses/GPL-3.0 GNU General Public License 3.0 - * @link https://github.com/jublonet/codebird-php - */ - -/** - * Media tests - * - * @package codebird-test - */ -class Media_Test extends \PHPUnit\Framework\TestCase -{ - /** - * Initialise Codebird class - * - * @return \Codebird\Codebird The Codebird class - */ - protected function getCB() - { - Codebird::setConsumerKey('123', '456'); - $cb = new CodebirdM(); - - return $cb; - } - - /** - * Tests _fetchRemoteFile - */ - public function testFetchRemoteFile() - { - $cb = $this->getCB(); - $expected = $cb->call('_fetchRemoteFile', ['http://www.example.org/found.txt']); - $this->assertEquals($expected, 'A test file.'); - } - - /** - * Tests _fetchRemoteFile - * @expectedException \Exception - * @expectedExceptionMessage Downloading a remote media file failed. - */ - public function testFetchRemoteFile1() - { - $cb = $this->getCB(); - $reply = $cb->call('_fetchRemoteFile', ['http://www.example.org/not-found.jpg']); - } -} diff --git a/twitter/vendor/jublonet/codebird-php/test/oauth_tests.php b/twitter/vendor/jublonet/codebird-php/test/oauth_tests.php deleted file mode 100644 index 086dfa2e8..000000000 --- a/twitter/vendor/jublonet/codebird-php/test/oauth_tests.php +++ /dev/null @@ -1,130 +0,0 @@ - - * @copyright 2010-2018 Jublo Limited - * @license https://opensource.org/licenses/GPL-3.0 GNU General Public License 3.0 - * @link https://github.com/jublonet/codebird-php - */ - -/** - * OAuth tests - * - * @package codebird-test - */ -class Oauth_Test extends \PHPUnit\Framework\TestCase -{ - /** - * Initialise Codebird class - * - * @return \Codebird\Codebird The Codebird class - */ - protected function getCB() - { - Codebird::setConsumerKey('123', '456'); - $cb = new CodebirdM(); - - return $cb; - } - - /** - * Tests oauth_authenticate - */ - public function testOauthAuthenticate() - { - $cb = $this->getCB(); - $cb->setToken('123', '456'); - $this->assertEquals( - 'https://api.twitter.com/oauth/authenticate?oauth_token=123', - $cb->oauth_authenticate() - ); - $this->assertEquals( - 'https://api.twitter.com/oauth/authenticate?oauth_token=123&force_login=1', - $cb->oauth_authenticate($force_login = true) - ); - $this->assertEquals( - 'https://api.twitter.com/oauth/authenticate?' - . 'oauth_token=123&force_login=1&screen_name=TwitterAPI', - $cb->oauth_authenticate($force_login = true, $screen_name = 'TwitterAPI') - ); - $this->assertEquals( - 'https://api.twitter.com/oauth/authenticate?' - . 'oauth_token=123&screen_name=TwitterAPI', - $cb->oauth_authenticate($force_login = false, $screen_name = 'TwitterAPI') - ); - } - - /** - * Tests oauth_authorize - */ - public function testOauthAuthorize() - { - $cb = $this->getCB(); - $cb->setToken('123', '456'); - $this->assertEquals( - 'https://api.twitter.com/oauth/authorize?oauth_token=123', - $cb->oauth_authorize() - ); - $this->assertEquals( - 'https://api.twitter.com/oauth/authorize?oauth_token=123&force_login=1', - $cb->oauth_authorize($force_login = true) - ); - $this->assertEquals( - 'https://api.twitter.com/oauth/authorize?' - . 'oauth_token=123&force_login=1&screen_name=TwitterAPI', - $cb->oauth_authorize($force_login = true, $screen_name = 'TwitterAPI') - ); - $this->assertEquals( - 'https://api.twitter.com/oauth/authorize?' - . 'oauth_token=123&screen_name=TwitterAPI', - $cb->oauth_authorize($force_login = false, $screen_name = 'TwitterAPI') - ); - } - - /** - * Tests oauth2_token - */ - public function testOauth2Token() - { - $cb = $this->getCB(); - $expected = new \stdClass; - $expected->token_type = 'bearer'; - $expected->access_token = 'VqiO0n2HrKE'; - $expected->httpstatus = '200'; - $expected->rate = null; - $this->assertEquals($expected, $cb->oauth2_token()); - } - - /** - * Tests _getBearerAuthorization - * @expectedException \Exception - * @expectedExceptionMessage To make an app-only auth API request, consumer key or bearer token must be set. - */ - public function testGetBearerAuthorization1() - { - $cb = $this->getCB(); - Codebird::setConsumerKey(null, null); - $cb->setBearerToken(null); - $cb->call('_getBearerAuthorization', []); - } - - /** - * Tests _getBearerAuthorization - */ - public function testGetBearerAuthorization2() - { - $cb = $this->getCB(); - $cb->setBearerToken('12345678'); - $this->assertEquals('Bearer 12345678', $cb->call('_getBearerAuthorization', [])); - - // automatic fetching - $cb->setBearerToken(null); - $this->assertEquals('Bearer VqiO0n2HrKE', $cb->call('_getBearerAuthorization', [])); - } -} diff --git a/twitter/vendor/jublonet/codebird-php/test/replyparse_tests.php b/twitter/vendor/jublonet/codebird-php/test/replyparse_tests.php deleted file mode 100644 index f316cd16c..000000000 --- a/twitter/vendor/jublonet/codebird-php/test/replyparse_tests.php +++ /dev/null @@ -1,361 +0,0 @@ - - * @copyright 2010-2018 Jublo Limited - * @license https://opensource.org/licenses/GPL-3.0 GNU General Public License 3.0 - * @link https://github.com/jublonet/codebird-php - */ - -/** - * Reply parsing tests - * - * @package codebird-test - */ -class Replyparse_Test extends \PHPUnit\Framework\TestCase -{ - /** - * Initialise Codebird class - * - * @return \Codebird\Codebird The Codebird class - */ - protected function getCB() - { - Codebird::setConsumerKey('123', '456'); - $cb = new CodebirdM(); - - return $cb; - } - - /** - * Tests _getHttpStatusFromHeaders - */ - public function testGetHttpStatusFromHeaders() - { - $cb = $this->getCB(); - $this->assertEquals( - '500', - $cb->call('_getHttpStatusFromHeaders', [['']]) - ); - $this->assertEquals( - '200', - $cb->call('_getHttpStatusFromHeaders', [ - ['HTTP/1.1 200 OK'], - ['X-Some-Data: test'] - ]) - ); - $this->assertEquals( - '404', - $cb->call('_getHttpStatusFromHeaders', [ - ['HTTP/1.1 404 Not Found'], - ['X-Some-Data: test'] - ]) - ); - } - - /** - * Tests _parseBearerReply - */ - public function testParseBearerReply() - { - $cb = $this->getCB(); - $cb->setBearerToken(null); - // get raw reply from mock collection - $reply = $cb->getStatic('_mock_replies')['POST https://api.twitter.com/oauth2/token']; - // check that bearer token is not yet set - $this->assertNull($cb->getStatic('_bearer_token')); - // parse it as object - $result = $cb->call( - '_parseBearerReply', - [ - $reply['reply'], - $reply['httpstatus'] - ] - ); - $expected = new \stdClass; - $expected->token_type = 'bearer'; - $expected->access_token = 'VqiO0n2HrKE'; - $expected->httpstatus = 200; - $expected->rate = null; - $this->assertEquals($expected, $result); - // check that bearer token was actually set - $this->assertNotNull($cb->getStatic('_bearer_token')); - - // array - $cb->setReturnFormat(CODEBIRD_RETURNFORMAT_ARRAY); - $cb->setBearerToken(null); - $result = $cb->call( - '_parseBearerReply', - [ - $reply['reply'], - $reply['httpstatus'] - ] - ); - $expected = [ - 'token_type' => 'bearer', - 'access_token' => 'VqiO0n2HrKE', - 'httpstatus' => 200, - 'rate' => null - ]; - $this->assertEquals($expected, $result); - // check that bearer token was actually set - $this->assertNotNull($cb->getStatic('_bearer_token')); - - // JSON - $cb->setReturnFormat(CODEBIRD_RETURNFORMAT_JSON); - $cb->setBearerToken(null); - $result = $cb->call( - '_parseBearerReply', - [ - $reply['reply'], - $reply['httpstatus'] - ] - ); - $expected = '{"token_type":"bearer","access_token":"VqiO0n2HrKE"}'; - $this->assertEquals($expected, $result); - // check that bearer token was actually set - $this->assertNotNull($cb->getStatic('_bearer_token')); - } - - /** - * Tests _getRateLimitInfo - */ - public function testGetRateLimitInfo() - { - $cb = $this->getCB(); - $headers = [ - 'content-length' => 68, - 'content-type' => 'application/json;charset=utf-8', - 'date' => 'Sun, 06 Dec 2015 14:43:28 GMT' - ]; - $this->assertNull($cb->call('_getRateLimitInfo', [$headers])); - - // set rate-limit headers - $headers['x-rate-limit-limit'] = 180; - $headers['x-rate-limit-remaining'] = 123; - $headers['x-rate-limit-reset'] = time() + 234; - $rate = $cb->call('_getRateLimitInfo', [$headers]); - $expected = new \stdClass; - $expected->limit = $headers['x-rate-limit-limit']; - $expected->remaining = $headers['x-rate-limit-remaining']; - $expected->reset = $headers['x-rate-limit-reset']; - $this->assertEquals($expected, $rate); - - // array - $cb->setReturnFormat(CODEBIRD_RETURNFORMAT_ARRAY); - $rate = $cb->call('_getRateLimitInfo', [$headers]); - $expected = [ - 'limit' => $headers['x-rate-limit-limit'], - 'remaining' => $headers['x-rate-limit-remaining'], - 'reset' => $headers['x-rate-limit-reset'] - ]; - $this->assertEquals($expected, $rate); - } - - /** - * Tests _validateSslCertificate - */ - public function testValidateSslCertificate1() - { - $cb = $this->getCB(); - $cb->call('_validateSslCertificate', [0]); - } - - /** - * Tests _validateSslCertificate - * @expectedException \Exception - * @expectedExceptionMessage Error 58 while validating the Twitter API certificate. - */ - public function testValidateSslCertificate2() - { - $cb = $this->getCB(); - $cb->call('_validateSslCertificate', [CURLE_SSL_CERTPROBLEM]); - } - - /** - * Tests _appendHttpStatusAndRate - */ - public function testAppendHttpStatusAndRate() - { - $cb = $this->getCB(); - - // object - $reply = new \stdClass; - $reply->somedata = 123; - $reply->moredata = '456'; - $rate = new \stdClass; - $rate->field1 = 180; - $rate->field2 = 177; - $expected = new \stdClass; - $expected->somedata = 123; - $expected->moredata = '456'; - $expected->httpstatus = 409; - $expected->rate = new \stdClass; - $expected->rate->field1 = 180; - $expected->rate->field2 = 177; - $this->assertEquals( - $expected, - $cb->call('_appendHttpStatusAndRate', [$reply, 409, $rate]) - ); - - // array - $reply = (array) $reply; - $rate = (array) $rate; - $expected = (array) $expected; - $expected['rate'] = (array) $expected['rate']; - $cb->setReturnFormat(CODEBIRD_RETURNFORMAT_ARRAY); - $this->assertEquals( - $expected, - $cb->call('_appendHttpStatusAndRate', [$reply, 409, $rate]) - ); - - // JSON - $reply = '{"somedata":123,"moredata":"456"}'; - $expected = '{"somedata":123,"moredata":"456","httpstatus":409,' - . '"rate":{"field1":180,"field2":177}}'; - $cb->setReturnFormat(CODEBIRD_RETURNFORMAT_JSON); - $this->assertEquals( - $expected, - $cb->call('_appendHttpStatusAndRate', [$reply, 409, $rate]) - ); - } - - /** - * Tests _parseApiHeaders - */ - public function testParseApiHeaders() - { - $cb = $this->getCB(); - $data = $cb->getStatic('_mock_replies')['default']['reply']; - list($headers, $reply) = $cb->call('_parseApiHeaders', [$data]); - $expected_headers = [ - 'HTTP/1.1 404 Not Found' => '', - 'content-length' => '68', - 'content-type' => 'application/json;charset=utf-8', - 'date' => 'Sun, 06 Dec 2015 14:43:28 GMT', - 'server' => 'tsa_b', - 'set-cookie' => 'guest_id=v1%3A144941300885288055; Domain=.twitter.com' - . '; Path=/; Expires=Tue, 05-Dec-2017 14:43:28 UTC', - 'strict-transport-security' => 'max-age=631138519', - 'x-connection-hash' => '12218aef9e9757609afb08e661fa3b9b', - 'x-response-time' => '2' - ]; - $expected_reply = '{"errors":[{"message":"Sorry, that page does not exist","code":34}]}'; - $this->assertEquals($expected_headers, $headers); - $this->assertEquals($expected_reply, $reply); - - // proxy - $data = $cb->getStatic('_mock_replies')['proxy1']['reply']; - list($headers, $reply) = $cb->call('_parseApiHeaders', [$data]); - $this->assertEquals($expected_headers, $headers); - $this->assertEquals($expected_reply, $reply); - } - - /** - * Tests _parseApiReplyPrefillHeaders - */ - public function testParseApiReplyPrefillHeaders() - { - $cb = $this->getCB(); - $headers = [ - 'X-TON-Min-Chunk-Size' => '12345', - 'X-TON-Max-Chunk-Size' => '23456', - 'Range' => 'bytes 0-1234567/2345678' - ]; - - // non-empty reply: no touching - $this->assertEquals( - '123', - $cb->call('_parseApiReplyPrefillHeaders', [$headers, '123']) - ); - - // no location header: no touching - $this->assertEquals( - '', - $cb->call('_parseApiReplyPrefillHeaders', [$headers, '']) - ); - - $headers['Location'] = 'https://twitter.com'; - $this->assertEquals( - '{"Location":"https:\/\/twitter.com","X-TON-Min-Chunk-Size":"12345",' - . '"X-TON-Max-Chunk-Size":"23456","Range":"bytes 0-1234567\/2345678"}', - $cb->call('_parseApiReplyPrefillHeaders', [$headers, '']) - ); - } - - /** - * Tests _parseApiReply - */ - public function testParseApiReply1() - { - $cb = $this->getCB(); - - // object - $this->assertEquals(new \stdClass, $cb->call('_parseApiReply', ['[]'])); - - // array - $cb->setReturnFormat(CODEBIRD_RETURNFORMAT_ARRAY); - $this->assertEquals([], $cb->call('_parseApiReply', ['[]'])); - - // JSON - $cb->setReturnFormat(CODEBIRD_RETURNFORMAT_JSON); - $this->assertEquals('{}', $cb->call('_parseApiReply', ['[]'])); - } - - /** - * Tests _parseApiReply - */ - public function testParseApiReply2() - { - $cb = $this->getCB(); - $reply = '{"id_str":"6253282","profile_location":null,' - . '"status":{"created_at":"Tue Nov 24 08:56:07 +0000 2015","id":669077021138493440}}'; - - // object - $expected = new \stdClass; - $expected->id_str = '6253282'; - $expected->profile_location = null; - $expected->status = new \stdClass; - $expected->status->created_at = 'Tue Nov 24 08:56:07 +0000 2015'; - $expected->status->id = 669077021138493440; - $result = $cb->call('_parseApiReply', [$reply]); - $this->assertEquals($expected, $result); - $this->assertSame($expected->status->id, $result->status->id); - - // array - $cb->setReturnFormat(CODEBIRD_RETURNFORMAT_ARRAY); - $expected = (array) $expected; - $expected['status'] = (array) $expected['status']; - $this->assertEquals($expected, $cb->call('_parseApiReply', [$reply])); - - // JSON - $cb->setReturnFormat(CODEBIRD_RETURNFORMAT_JSON); - $this->assertEquals($reply, $cb->call('_parseApiReply', [$reply])); - - // query-string format - $cb->setReturnFormat(CODEBIRD_RETURNFORMAT_ARRAY); - $this->assertEquals( - [ - 'oauth_token' => 'ABC', - 'oauth_token_secret' => 'def', - 'oauth_callback_confirmed' => 'true' - ], - $cb->call( - '_parseApiReply', - ['oauth_token=ABC&oauth_token_secret=def&oauth_callback_confirmed=true'] - ) - ); - - // message - $this->assertEquals( - ['message' => 'This is just a message.'], - $cb->call('_parseApiReply', ['This is just a message.']) - ); - } -} diff --git a/twitter/vendor/jublonet/codebird-php/test/requestparse_tests.php b/twitter/vendor/jublonet/codebird-php/test/requestparse_tests.php deleted file mode 100644 index 1656f3d26..000000000 --- a/twitter/vendor/jublonet/codebird-php/test/requestparse_tests.php +++ /dev/null @@ -1,212 +0,0 @@ - - * @copyright 2010-2018 Jublo Limited - * @license https://opensource.org/licenses/GPL-3.0 GNU General Public License 3.0 - * @link https://github.com/jublonet/codebird-php - */ - -/** - * Request parsing tests - * - * @package codebird-test - */ -class Requestparse_Test extends \PHPUnit\Framework\TestCase -{ - /** - * Initialise Codebird class - * - * @return \Codebird\Codebird The Codebird class - */ - protected function getCB() - { - Codebird::setConsumerKey('123', '456'); - $cb = new CodebirdM(); - $cb->setToken('234', '567'); - - return $cb; - } - - /** - * Tests _parseApiParams - */ - public function testParseApiParams() - { - $cb = $this->getCB(); - // empty list - $this->assertEquals([], $cb->call('_parseApiParams', [[]])); - // arrays - $this->assertEquals(['test' => 1], $cb->call('_parseApiParams', [[['test' => 1]]])); - $this->assertEquals( - ['media[]' => '123'], - $cb->call('_parseApiParams', [[['media[]' => 123]]]) - ); - // urlencoded strings - $this->assertEquals(['testdata' => ''], $cb->call('_parseApiParams', [['testdata']])); - $this->assertEquals( - ['param1' => '12', 'param2' => 'ab'], - $cb->call('_parseApiParams', [['param1=12¶m2=ab']]) - ); - $this->assertEquals( - ['media' => ['123', '456']], - $cb->call('_parseApiParams', [['media[]=123&media[]=456']]) - ); - } - - /** - * Tests _stringifyNullBoolParams - */ - public function testStringifyNullBoolParams() - { - $cb = $this->getCB(); - $result = $cb->call( - '_stringifyNullBoolParams', - [['a' => 123, 'b' => null, 'c' => true, 'd' => false, 'e' => 'x']] - ); - $this->assertEquals('123', $result['a']); - $this->assertNull($result['b']); - $this->assertEquals('true', $result['c']); - $this->assertEquals('false', $result['d']); - } - - /** - * Tests _mapFnToApiMethod - */ - public function testMapFnToApiMethod() - { - $cb = $this->getCB(); - $apiparams = [ - 'test' => 1, - 'account_id' => '1234' - ]; - $result = $cb->call( - '_mapFnToApiMethod', - 'ads_accounts_ACCOUNT_ID_cards_appDownload', - $apiparams - ); - $this->assertEquals([ - 'ads/accounts/1234/cards/app_download', - 'ads/accounts/:account_id/cards/app_download' - ], $result); - // check that inline parameter was removed from array - $this->assertArrayNotHasKey('account_id', $apiparams); - } - - /** - * Tests _mapFnInsertSlashes - */ - public function testMapFnInsertSlashes() - { - $cb = $this->getCB(); - $result = $cb->call( - '_mapFnInsertSlashes', - ['ads_accounts_ACCOUNT_ID_cards_appDownload'] - ); - $this->assertEquals( - 'ads/accounts/ACCOUNT/ID/cards/appDownload', - $result - ); - } - - /** - * Tests _mapFnRestoreParamUnderscores - */ - public function testMapFnRestoreParamUnderscores() - { - $cb = $this->getCB(); - $params_underscore = [ - 'screen_name', 'place_id', - 'account_id', 'campaign_id', 'card_id', 'line_item_id', - 'tweet_id', 'web_event_tag_id' - ]; - $params_slash = []; - foreach ($params_underscore as $param) { - $params_slash[] = str_replace('_', '/', $param); - } - for ($i = 0; $i < count($params_underscore); $i++) { - $result = $cb->call( - '_mapFnRestoreParamUnderscores', - ['ads/accounts/' . strtoupper($params_slash[$i]) . '/cards/appDownload'] - ); - $this->assertEquals( - 'ads/accounts/' . strtoupper($params_underscore[$i]) . '/cards/appDownload', - $result - ); - } - } - - /** - * Tests _mapFnInlineParams - */ - public function testMapFnInlineParams() - { - $cb = $this->getCB(); - // normal parameters - $apiparams = [ - 'test' => 1, - 'account_id' => '1234' - ]; - $result = $cb->call( - '_mapFnInlineParams', - 'ads/accounts/ACCOUNT_ID/cards/app_download', - $apiparams - ); - $this->assertEquals([ - 'ads/accounts/1234/cards/app_download', - 'ads/accounts/:account_id/cards/app_download' - ], - $result - ); - // check that inline parameter was removed from array - $this->assertArrayNotHasKey('account_id', $apiparams); - - // special parameters (TON API) - $apiparams = [ - 'test' => 1, - 'bucket' => 'ta_partner', - 'file' => 'test_Ab.mp4', - 'resumeId' => '56789' - ]; - $result = $cb->call( - '_mapFnInlineParams', - 'ton/bucket/BUCKET/FILE?resumable=true&resumeId=RESUMEID', - $apiparams - ); - $this->assertEquals([ - 'ton/bucket/ta_partner/test_Ab.mp4?resumable=true&resumeId=56789', - 'ton/bucket/:bucket/:file?resumable=true&resumeId=:resumeId' - ], - $result - ); - $this->assertArrayNotHasKey('bucket', $apiparams); - $this->assertArrayNotHasKey('file', $apiparams); - $this->assertArrayNotHasKey('resumeId', $apiparams); - $this->assertEquals(['test' => 1], $apiparams); - } - - /** - * Tests _json_decode - */ - public function testJsonDecode() - { - $json = '{"id": 123456789123456789, "id_str": "123456789123456789"}'; - $array = [ - 'id' => 123456789123456789, - 'id_str' => '123456789123456789' - ]; - $object = (object) $array; - - $cb = $this->getCB(); - $result = $cb->call('_json_decode', [$json]); - $this->assertEquals($object, $result); - $result = $cb->call('_json_decode', [$json, true]); - $this->assertEquals($array, $result); - } -} diff --git a/twitter/vendor/jublonet/codebird-php/test/returnformat_tests.php b/twitter/vendor/jublonet/codebird-php/test/returnformat_tests.php deleted file mode 100644 index 321c2ee30..000000000 --- a/twitter/vendor/jublonet/codebird-php/test/returnformat_tests.php +++ /dev/null @@ -1,70 +0,0 @@ - - * @copyright 2010-2018 Jublo Limited - * @license https://opensource.org/licenses/GPL-3.0 GNU General Public License 3.0 - * @link https://github.com/jublonet/codebird-php - */ - -/** - * Return format tests - * - * @package codebird-test - */ -class Returnformat_Test extends \PHPUnit\Framework\TestCase -{ - /** - * Initialise Codebird class - * - * @return \Codebird\Codebird The Codebird class - */ - protected function getCB() - { - Codebird::setConsumerKey('123', '456'); - $cb = new CodebirdM(); - $cb->setToken('234', '567'); - - return $cb; - } - - /** - * Tests array return format - */ - public function testArrayFormat() - { - $cb = $this->getCB(); - $cb->setReturnFormat(CODEBIRD_RETURNFORMAT_ARRAY); - $reply = $cb->users_show(['screen_name' => 'TwitterAPI']); - $this->assertTrue(is_array($reply)); - } - - /** - * Tests object return format - */ - public function testObjectFormat() - { - $cb = $this->getCB(); - $cb->setReturnFormat(CODEBIRD_RETURNFORMAT_OBJECT); - $reply = $cb->users_show(['screen_name' => 'TwitterAPI']); - $this->assertInstanceOf('stdClass', $reply); - } - - /** - * Tests JSON return format - */ - public function testJsonFormat() - { - $cb = $this->getCB(); - $cb->setReturnFormat(CODEBIRD_RETURNFORMAT_JSON); - $reply = $cb->users_show(['screen_name' => 'TwitterAPI']); - $data = json_decode($reply); - $this->assertNotFalse($data); - } -} diff --git a/twitter/vendor/jublonet/codebird-php/test/setter_tests.php b/twitter/vendor/jublonet/codebird-php/test/setter_tests.php deleted file mode 100644 index 4c2cd0940..000000000 --- a/twitter/vendor/jublonet/codebird-php/test/setter_tests.php +++ /dev/null @@ -1,253 +0,0 @@ - - * @copyright 2010-2018 Jublo Limited - * @license https://opensource.org/licenses/GPL-3.0 GNU General Public License 3.0 - * @link https://github.com/jublonet/codebird-php - */ - -/** - * Setter function tests - * - * @package codebird-test - */ -class Setter_Test extends \PHPUnit\Framework\TestCase -{ - /** - * Tests setConsumerKey - */ - public function testSetConsumerKey() - { - $cb = new CodebirdT(); - $cb->setConsumerKey('123', '456'); - $this->assertEquals('123', $cb->getStatic('_consumer_key')); - $this->assertEquals('456', $cb->getStatic('_consumer_secret')); - } - - /** - * Tests setBearerToken - */ - public function testSetBearerToken() - { - $cb = new CodebirdT(); - $cb->setBearerToken('789'); - $this->assertEquals('789', $cb->getStatic('_bearer_token')); - } - - /** - * Tests getVersion - */ - public function testGetVersion() - { - $cb = new CodebirdT(); - $version = $cb->getVersion(); - $this->assertEquals($version, $cb->getStatic('_version')); - $this->assertRegexp('/^[1-9]\d*\.\d+\.\d+(-([a-z]+\.[1-9]\d*|dev))?$/', $version); - } - - /** - * Tests setToken - */ - public function testSetToken() - { - $cb = new CodebirdT(); - $cb->setToken('123', '456'); - $this->assertEquals('123', $cb->get('_oauth_token')); - $this->assertEquals('456', $cb->get('_oauth_token_secret')); - } - - /** - * Tests logout - */ - public function testLogout() - { - $cb = new CodebirdT(); - $cb->setToken('123', '456'); - $cb->logout(); - $this->assertNull($cb->get('_oauth_token')); - $this->assertNull($cb->get('_oauth_token_secret')); - } - - /** - * Tests setUseCurl - */ - public function testSetUseCurl() - { - $cb = new CodebirdT(); - $cb->setUseCurl(true); - $this->assertTrue($cb->get('_use_curl')); - $cb->setUseCurl(false); - $this->assertFalse($cb->get('_use_curl')); - $cb->setUseCurl('123'); - $this->assertTrue($cb->get('_use_curl')); - } - - /** - * Tests setTimeout - */ - public function testSetTimeout() - { - $cb = new CodebirdT(); - $cb->setTimeout(123); - $this->assertEquals(123, $cb->get('_timeouts')['request']); - $cb->setTimeout(0); - $this->assertEquals(0, $cb->get('_timeouts')['request']); - $cb->setTimeout(-123); - $this->assertEquals(0, $cb->get('_timeouts')['request']); - } - - /** - * Tests setConnectionTimeout - */ - public function testSetConnectionTimeout() - { - $cb = new CodebirdT(); - $cb->setConnectionTimeout(123); - $this->assertEquals(123, $cb->get('_timeouts')['connect']); - $cb->setConnectionTimeout(0); - $this->assertEquals(0, $cb->get('_timeouts')['connect']); - $cb->setConnectionTimeout(-123); - $this->assertEquals(0, $cb->get('_timeouts')['connect']); - } - - /** - * Tests setConnectionTimeout - */ - public function testSetRemoteDownloadTimeout() - { - $cb = new CodebirdT(); - $cb->setRemoteDownloadTimeout(123); - $this->assertEquals(123, $cb->get('_timeouts')['remote']); - $cb->setRemoteDownloadTimeout(0); - $this->assertEquals(0, $cb->get('_timeouts')['remote']); - $cb->setRemoteDownloadTimeout(-123); - $this->assertEquals(0, $cb->get('_timeouts')['remote']); - } - - /** - * Tests setReturnFormat - */ - public function testSetReturnFormat() - { - $cb = new CodebirdT(); - $cb->setReturnFormat(CODEBIRD_RETURNFORMAT_JSON); - $this->assertEquals($cb->get('_return_format'), CODEBIRD_RETURNFORMAT_JSON); - } - - /** - * Tests setProxy - */ - public function testSetProxy() - { - $cb = new CodebirdT(); - $cb->setProxy('127.0.0.1', '8888'); - $this->assertEquals('127.0.0.1', $cb->get('_proxy')['host']); - $this->assertEquals('8888', $cb->get('_proxy')['port']); - $this->assertEquals(CURLPROXY_HTTP, $cb->get('_proxy')['type']); - - $cb->setProxy('127.0.0.1', '8888', CURLPROXY_SOCKS5); - $this->assertEquals('127.0.0.1', $cb->get('_proxy')['host']); - $this->assertEquals('8888', $cb->get('_proxy')['port']); - $this->assertEquals(CURLPROXY_SOCKS5, $cb->get('_proxy')['type']); - } - - /** - * Tests setProxy - * @expectedException \Exception - * @expectedExceptionMessage Invalid proxy type specified. - */ - public function testSetProxy2() - { - $cb = new CodebirdT(); - $cb->setProxy('127.0.0.1', '8888', 1); - } - - /** - * Tests setProxyAuthentication - */ - public function testSetProxyAuthentication() - { - $cb = new CodebirdT(); - $cb->setProxyAuthentication('ABCDEF'); - $this->assertEquals('ABCDEF', $cb->get('_proxy')['authentication']); - } - - /** - * Tests setStreamingCallback - */ - public function testSetStreamingCallback1() - { - $callback = ['\Codebird\CodebirdT', 'streamingCallbackTest']; - $cb = new CodebirdT(); - $cb->setStreamingCallback($callback); - $this->assertSame( - array_diff($callback, $cb->get('_streaming_callback')), - array_diff($cb->get('_streaming_callback'), $callback) - ); - } - - /** - * Tests setStreamingCallback - * @expectedException \Exception - * @expectedExceptionMessage This is not a proper callback. - */ - public function testSetStreamingCallback2() - { - $cb = new CodebirdT(); - $cb->setStreamingCallback(['\Codebird\CodebirdTX', 'somewhere']); - } - - /** - * Tests getApiMethods - */ - public function testGetApiMethods() - { - $cb = new CodebirdT(); - $methods = $cb->getApiMethods(); - $this->assertArrayHasKey('GET', $cb->getStatic('_api_methods')); - $this->assertArrayHasKey('POST', $cb->getStatic('_api_methods')); - $this->assertArrayHasKey('PUT', $cb->getStatic('_api_methods')); - $this->assertArrayHasKey('DELETE', $cb->getStatic('_api_methods')); - $this->assertEquals($methods, $cb->getStatic('_api_methods')); - } - - /** - * Tests hasProxy - */ - public function testHasProxy() - { - $cb = new CodebirdT(); - $this->assertFalse($cb->call('_hasProxy')); - $cb->setProxy('127.0.0.1', '8888'); - $this->assertTrue($cb->call('_hasProxy')); - } - - /** - * Tests getProxyHost - */ - public function testGetProxyHost() - { - $cb = new CodebirdT(); - $this->assertNull($cb->call('_getProxyHost')); - $cb->setProxy('127.0.0.1', '8888'); - $this->assertEquals('127.0.0.1', $cb->call('_getProxyHost')); - } - - /** - * Tests getProxyPort - */ - public function testGetProxyPort() - { - $cb = new CodebirdT(); - $this->assertNull($cb->call('_getProxyPort')); - $cb->setProxy('127.0.0.1', '8888'); - $this->assertEquals('8888', $cb->call('_getProxyPort')); - } -} diff --git a/twitter/vendor/jublonet/codebird-php/test/signing_tests.php b/twitter/vendor/jublonet/codebird-php/test/signing_tests.php deleted file mode 100644 index 3a4f5fb34..000000000 --- a/twitter/vendor/jublonet/codebird-php/test/signing_tests.php +++ /dev/null @@ -1,166 +0,0 @@ - - * @copyright 2010-2018 Jublo Limited - * @license https://opensource.org/licenses/GPL-3.0 GNU General Public License 3.0 - * @link https://github.com/jublonet/codebird-php - */ - -/** - * OAuth signing tests - * - * @package codebird-test - */ -class Signing_Test extends \PHPUnit\Framework\TestCase -{ - /** - * Initialise Codebird class - * - * @return \Codebird\Codebird The Codebird class - */ - protected function getCB() - { - Codebird::setConsumerKey('123', '456'); - $cb = new CodebirdM(); - - return $cb; - } - - /** - * Tests _url - */ - public function testUrl() - { - $cb = $this->getCB(); - // string - $this->assertEquals( - 'q%20%2B%20b%21%22%C2%A7%24%25%26%2F%28%29%3D%3F%23%2A13%2C3%C3%A4.', - $cb->call('_url', ['q + b!"§$%&/()=?#*13,3ä.']) - ); - // array - $this->assertEquals( - [ - 'q%20%2B%20b%21%22%C2%A7%24%25%26%2F%28%29%3D%3F%23%2A13%2C3%C3%A4.', - 'test123' - ], - $cb->call('_url', [[ - 'q + b!"§$%&/()=?#*13,3ä.', - 'test123' - ]]) - ); - } - - /** - * Tests _sha1 - */ - public function testSha1() - { - $cb = $this->getCB(); - $this->assertEquals( - 'ydAlpYjrGHU7psDQ9HPgHTcwEuw=', - $cb->call('_sha1', ['q + b!"§$%&/()=?#*13,3ä.']) - ); - - // with access token secret - $cb->setToken('678', '789'); - $this->assertEquals( - 'CtivZhAHiX49ZMUuHXtKabLAuo0=', - $cb->call('_sha1', ['q + b!"§$%&/()=?#*13,3ä.']) - ); - } - - /** - * Tests _nonce - */ - public function testNonce1() - { - $cb = $this->getCB(); - // default length - $this->assertEquals( - '4247c524', - $cb->call('_nonce', []) - ); - // custom length - $this->assertEquals( - '4247c5248da', - $cb->call('_nonce', [11]) - ); - } - - /** - * Tests _nonce - * @expectedException \Exception - * @expectedExceptionMessage Invalid nonce length. - */ - public function testNonce2() - { - $cb = $this->getCB(); - // invalid length - $cb->call('_nonce', [0]); - } - - /** - * Tests _getSignature - */ - public function testGetSignature() - { - $cb = $this->getCB(); - $base_params = [ - 'oauth_consumer_key' => '123', - 'oauth_nonce' => '12345678', - 'oauth_signature_method' => 'HMAC-SHA1', - 'oauth_timestamp' => '1400000000', - 'oauth_token' => '567', - 'oauth_version' => '1.0', - 'q' => 'Test search.' - ]; - $this->assertEquals( - 'ZON/m9bHvciPdtyK9BlokjeiW4M=', - $cb->call('_getSignature', ['GET', 'search/tweets', $base_params]) - ); - } - - /** - * Tests _sign - * @expectedException \Exception - * @expectedExceptionMessage To generate a signature, the consumer key must be set. - */ - public function testSign1() - { - $cb = $this->getCB(); - $cb->setConsumerKey(null, null); - $params = ['q' => 'Test search.']; - $cb->call('_sign', ['GET', 'search/tweets', $params]); - } - - /** - * Tests _sign - */ - public function testSign2() - { - $cb = $this->getCB(); - $params = ['q' => 'Test search.']; - $this->assertEquals( - 'OAuth oauth_consumer_key="123", oauth_nonce="4247c524", oauth_signature' - . '="lOLNd5l6cGB9kWACxWLNKJwSD%2FI%3D", oauth_signature_method="HMAC-SHA' - . '1", oauth_timestamp="1412345678", oauth_version="1.0"', - $cb->call('_sign', ['GET', 'search/tweets', $params]) - ); - - // with oauth token - $cb->setToken('678', '789'); - $this->assertEquals( - 'OAuth oauth_consumer_key="123", oauth_nonce="4247c524", oauth_signature' - . '="XzegzFKEqs2PpUMym5T%2BwhEmTz4%3D", oauth_signature_method="HMAC-SHA' - . '1", oauth_timestamp="1412345678", oauth_token="678", oauth_version="1.0"', - $cb->call('_sign', ['GET', 'search/tweets', $params]) - ); - } -} diff --git a/twitter/vendor/jublonet/codebird-php/test/singleton_tests.php b/twitter/vendor/jublonet/codebird-php/test/singleton_tests.php deleted file mode 100644 index b47da416e..000000000 --- a/twitter/vendor/jublonet/codebird-php/test/singleton_tests.php +++ /dev/null @@ -1,31 +0,0 @@ - - * @copyright 2010-2018 Jublo Limited - * @license https://opensource.org/licenses/GPL-3.0 GNU General Public License 3.0 - * @link https://github.com/jublonet/codebird-php - */ - -/** - * Singleton tests - * - * @package codebird-test - */ -class Singleton_Test extends \PHPUnit\Framework\TestCase -{ - /** - * Tests getInstance - */ - public function testGetInstance() - { - $cb = CodebirdT::getInstance(); - $this->assertInstanceOf('\Codebird\Codebird', $cb); - } -} From 34f0fa7dc8df13edb592e3eff454a47c6eb38839 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 9 Aug 2023 20:07:29 +0000 Subject: [PATCH 013/388] License readded --- twitter/LICENSE | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 twitter/LICENSE diff --git a/twitter/LICENSE b/twitter/LICENSE new file mode 100644 index 000000000..274b71550 --- /dev/null +++ b/twitter/LICENSE @@ -0,0 +1,25 @@ + +Copyright (c) 2011-2018 Tobias Diekershoff, Michael Vogel, Hypolite Petovan +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + * Neither the name of the nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file From c0eac366fe051da5ce7989beb0cc955be74f4f22 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 9 Aug 2023 20:08:32 +0000 Subject: [PATCH 014/388] Fix newlines --- twitter/LICENSE | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/twitter/LICENSE b/twitter/LICENSE index 274b71550..496cce20d 100644 --- a/twitter/LICENSE +++ b/twitter/LICENSE @@ -1,4 +1,3 @@ - Copyright (c) 2011-2018 Tobias Diekershoff, Michael Vogel, Hypolite Petovan All rights reserved. @@ -22,4 +21,4 @@ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. From e004e20352491260d09c3e52fa6ed2da93da9f60 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 9 Aug 2023 23:13:37 +0000 Subject: [PATCH 015/388] Transmit the media type --- twitter/twitter.php | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/twitter/twitter.php b/twitter/twitter.php index d0f9b5bfe..696412183 100644 --- a/twitter/twitter.php +++ b/twitter/twitter.php @@ -46,6 +46,7 @@ use Friendica\Model\Item; use Friendica\Model\Post; use Friendica\Core\Config\Util\ConfigFileManager; use Friendica\Model\Photo; +use Friendica\Util\Images; use GuzzleHttp\Client; use GuzzleHttp\HandlerStack; use GuzzleHttp\Subscriber\Oauth\Oauth1; @@ -219,7 +220,7 @@ function twitter_post_hook(array &$b) } catch (\Throwable $th) { Logger::warning('Error while uploading image', ['image' => $image, 'code' => $th->getCode(), 'message' => $th->getMessage()]); Worker::defer(); - break; + return; } } } @@ -265,13 +266,17 @@ function twitter_upload_image(int $uid, array $image) $photo = Photo::createPhotoForExternalResource($image['url']); } + $picturedata = Photo::getImageForPhoto($photo); + + $mimetype = $photo['type'] ?: Images::getMimeTypeByData($picturedata); + $parameters = [ 'name' => 'media_data', - 'contents' => base64_encode(Photo::getImageForPhoto($photo)) + 'contents' => base64_encode($picturedata) ]; - Logger::info('Uploading', ['uid' => $uid, 'image' => $image]); - $media = twitter_post($uid, 'https://upload.twitter.com/1.1/media/upload.json', 'multipart', [$parameters]); + Logger::info('Uploading', ['uid' => $uid, 'size' => strlen($parameters['contents']), 'image' => $image]); + $media = twitter_post($uid, 'https://upload.twitter.com/1.1/media/upload.json?' . http_build_query(['media_type' => $mimetype]), 'multipart', [$parameters]); if (isset($media->media_id_string)) { $media_id = $media->media_id_string; @@ -287,7 +292,7 @@ function twitter_upload_image(int $uid, array $image) Logger::info('Metadata create', ['uid' => $uid, 'data' => $data, 'return' => $ret]); } } else { - Logger::error('Failed upload', ['uid' => $uid, 'image' => $image['url'], 'return' => $media]); + Logger::error('Failed upload', ['uid' => $uid, 'size' => strlen($parameters['contents']), 'image' => $image['url'], 'return' => $media]); throw new Exception('Failed upload of ' . $image['url']); } From 603c8defb1bf216355f62936744d2a822a817d05 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 10 Aug 2023 06:46:17 +0000 Subject: [PATCH 016/388] Avoid upload problems by reducing the picture size --- twitter/twitter.php | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/twitter/twitter.php b/twitter/twitter.php index 696412183..41105ced0 100644 --- a/twitter/twitter.php +++ b/twitter/twitter.php @@ -219,7 +219,8 @@ function twitter_post_hook(array &$b) $media_ids[] = twitter_upload_image($b['uid'], $image, $b); } catch (\Throwable $th) { Logger::warning('Error while uploading image', ['image' => $image, 'code' => $th->getCode(), 'message' => $th->getMessage()]); - Worker::defer(); + // Currently don't defer to avoid a loop. + //Worker::defer(); return; } } @@ -261,22 +262,16 @@ function twitter_post_status(int $uid, string $status, array $media_ids = [], st function twitter_upload_image(int $uid, array $image) { if (!empty($image['id'])) { - $photo = Photo::selectFirst([], ['id' => $image['id']]); + $photo = Photo::selectFirst(['resource-id'], ['id' => $image['id']]); + $photo = Photo::selectFirst([], ["`resource-id` = ? AND `scale` > ?", $photo['resource-id'], 0], ['order' => ['scale']]); } else { $photo = Photo::createPhotoForExternalResource($image['url']); } $picturedata = Photo::getImageForPhoto($photo); - $mimetype = $photo['type'] ?: Images::getMimeTypeByData($picturedata); - - $parameters = [ - 'name' => 'media_data', - 'contents' => base64_encode($picturedata) - ]; - - Logger::info('Uploading', ['uid' => $uid, 'size' => strlen($parameters['contents']), 'image' => $image]); - $media = twitter_post($uid, 'https://upload.twitter.com/1.1/media/upload.json?' . http_build_query(['media_type' => $mimetype]), 'multipart', [$parameters]); + Logger::info('Uploading', ['uid' => $uid, 'size' => strlen($picturedata), 'image' => $image]); + $media = twitter_post($uid, 'https://upload.twitter.com/1.1/media/upload.json', 'form_params', ['media' => base64_encode($picturedata)]); if (isset($media->media_id_string)) { $media_id = $media->media_id_string; @@ -292,7 +287,7 @@ function twitter_upload_image(int $uid, array $image) Logger::info('Metadata create', ['uid' => $uid, 'data' => $data, 'return' => $ret]); } } else { - Logger::error('Failed upload', ['uid' => $uid, 'size' => strlen($parameters['contents']), 'image' => $image['url'], 'return' => $media]); + Logger::error('Failed upload', ['uid' => $uid, 'size' => strlen($picturedata), 'image' => $image['url'], 'return' => $media]); throw new Exception('Failed upload of ' . $image['url']); } From 21006aec74ff73ab528fffc658ac2ae4a5f372e2 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 10 Aug 2023 21:26:10 +0000 Subject: [PATCH 017/388] Resize picture before uploading --- twitter/twitter.php | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/twitter/twitter.php b/twitter/twitter.php index 41105ced0..a644aec4c 100644 --- a/twitter/twitter.php +++ b/twitter/twitter.php @@ -46,11 +46,14 @@ use Friendica\Model\Item; use Friendica\Model\Post; use Friendica\Core\Config\Util\ConfigFileManager; use Friendica\Model\Photo; +use Friendica\Object\Image; use Friendica\Util\Images; use GuzzleHttp\Client; use GuzzleHttp\HandlerStack; use GuzzleHttp\Subscriber\Oauth\Oauth1; +const TWITTER_MAX_IMAGE_SIZE = 500000; + function twitter_install() { Hook::register('load_config' , __FILE__, 'twitter_load_config'); @@ -262,15 +265,20 @@ function twitter_post_status(int $uid, string $status, array $media_ids = [], st function twitter_upload_image(int $uid, array $image) { if (!empty($image['id'])) { - $photo = Photo::selectFirst(['resource-id'], ['id' => $image['id']]); - $photo = Photo::selectFirst([], ["`resource-id` = ? AND `scale` > ?", $photo['resource-id'], 0], ['order' => ['scale']]); + $photo = Photo::selectFirst([], ['id' => $image['id']]); } else { $photo = Photo::createPhotoForExternalResource($image['url']); } $picturedata = Photo::getImageForPhoto($photo); - Logger::info('Uploading', ['uid' => $uid, 'size' => strlen($picturedata), 'image' => $image]); + $type = Images::getMimeTypeByData($picturedata, $photo['filename'], $photo['type']); + + $picture = Photo::resizeToFileSize(new Image($picturedata, $type), TWITTER_MAX_IMAGE_SIZE); + + $picturedata = $picture->asString(); + + Logger::info('Uploading', ['uid' => $uid, 'size' => strlen($picturedata), 'type' => @getimagesizefromstring($picturedata), 'photo' => $photo]); $media = twitter_post($uid, 'https://upload.twitter.com/1.1/media/upload.json', 'form_params', ['media' => base64_encode($picturedata)]); if (isset($media->media_id_string)) { From 15ea39d8307a15d43f720bb71fc6bf90643f121b Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 10 Aug 2023 21:36:09 +0000 Subject: [PATCH 018/388] Reformatted code --- twitter/twitter.php | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/twitter/twitter.php b/twitter/twitter.php index a644aec4c..4343e801b 100644 --- a/twitter/twitter.php +++ b/twitter/twitter.php @@ -56,13 +56,13 @@ const TWITTER_MAX_IMAGE_SIZE = 500000; function twitter_install() { - Hook::register('load_config' , __FILE__, 'twitter_load_config'); - Hook::register('connector_settings' , __FILE__, 'twitter_settings'); + Hook::register('load_config', __FILE__, 'twitter_load_config'); + Hook::register('connector_settings', __FILE__, 'twitter_settings'); Hook::register('connector_settings_post', __FILE__, 'twitter_settings_post'); - Hook::register('hook_fork' , __FILE__, 'twitter_hook_fork'); - Hook::register('post_local' , __FILE__, 'twitter_post_local'); - Hook::register('notifier_normal' , __FILE__, 'twitter_post_hook'); - Hook::register('jot_networks' , __FILE__, 'twitter_jot_nets'); + Hook::register('hook_fork', __FILE__, 'twitter_hook_fork'); + Hook::register('post_local', __FILE__, 'twitter_post_local'); + Hook::register('notifier_normal', __FILE__, 'twitter_post_hook'); + Hook::register('jot_networks', __FILE__, 'twitter_jot_nets'); } function twitter_load_config(ConfigFileManager $loader) @@ -124,7 +124,7 @@ function twitter_settings(array &$data) '$api_secret' => ['twitter-api-secret', DI::l10n()->t('API Secret'), $api_secret], '$access_token' => ['twitter-access-token', DI::l10n()->t('Access Token'), $access_token], '$access_secret' => ['twitter-access-secret', DI::l10n()->t('Access Secret'), $access_secret], - '$help' => DI::l10n()->t('Each user needs to register their own app to be able to post to Twitter. Please visit https://developer.twitter.com/en/portal/projects-and-apps to register a project. Inside the project you then have to register an app. You will find the needed data for the connector on the page "Keys and token" in the app settings.'), + '$help' => DI::l10n()->t('Each user needs to register their own app to be able to post to Twitter. Please visit https://developer.twitter.com/en/portal/projects-and-apps to register a project. Inside the project you then have to register an app. You will find the needed data for the connector on the page "Keys and token" in the app settings.'), ]); $data = [ @@ -146,8 +146,10 @@ function twitter_hook_fork(array &$b) $post = $b['data']; - if ($post['deleted'] || $post['private'] || ($post['created'] !== $post['edited']) || - !strstr($post['postopts'], 'twitter') || ($post['gravity'] != Item::GRAVITY_PARENT)) { + if ( + $post['deleted'] || $post['private'] || ($post['created'] !== $post['edited']) || + !strstr($post['postopts'], 'twitter') || ($post['gravity'] != Item::GRAVITY_PARENT) + ) { $b['execute'] = false; return; } @@ -223,9 +225,9 @@ function twitter_post_hook(array &$b) } catch (\Throwable $th) { Logger::warning('Error while uploading image', ['image' => $image, 'code' => $th->getCode(), 'message' => $th->getMessage()]); // Currently don't defer to avoid a loop. - //Worker::defer(); - return; - } + //Worker::defer(); + return; + } } } @@ -305,7 +307,7 @@ function twitter_upload_image(int $uid, array $image) function twitter_post(int $uid, string $url, string $type, array $data): stdClass { $stack = HandlerStack::create(); - + $middleware = new Oauth1([ 'consumer_key' => DI::pConfig()->get($uid, 'twitter', 'api_key'), 'consumer_secret' => DI::pConfig()->get($uid, 'twitter', 'api_secret'), @@ -314,7 +316,7 @@ function twitter_post(int $uid, string $url, string $type, array $data): stdClas ]); $stack->push($middleware); - + $client = new Client([ 'handler' => $stack ]); From 8b66b3a1946cdafa6efe0bbeee858de7eaccae5d Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 15 Aug 2023 20:25:17 +0000 Subject: [PATCH 019/388] Nluesky/Twitter: Resize picture before uploading --- bluesky/bluesky.php | 43 +++++++++++++--- twitter/templates/connector_settings.tpl | 3 +- twitter/twitter.php | 65 ++++++++++++++++++------ 3 files changed, 89 insertions(+), 22 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index 252becc12..5ca9c9517 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -43,6 +43,7 @@ use Friendica\Model\Photo; use Friendica\Model\Post; use Friendica\Network\HTTPClient\Client\HttpClientAccept; use Friendica\Network\HTTPClient\Client\HttpClientOptions; +use Friendica\Object\Image; use Friendica\Protocol\Activity; use Friendica\Protocol\Relay; use Friendica\Util\DateTimeFormat; @@ -50,6 +51,7 @@ use Friendica\Util\Strings; const BLUESKY_DEFAULT_POLL_INTERVAL = 10; // given in minutes const BLUESKY_HOST = 'https://bsky.app'; // Hard wired until Bluesky will run on multiple systems +const BLUESKY_IMAGE_SIZE = [1000000, 500000, 100000, 50000]; function bluesky_install() { @@ -634,6 +636,12 @@ function bluesky_create_post(array $item, stdClass $root = null, stdClass $paren if ($key == count($msg['parts']) - 1) { $record = bluesky_add_embed($uid, $msg, $record); + if (empty($record)) { + if (Worker::getRetrial() < 3) { + Worker::defer(); + } + return; + } } $post = [ @@ -644,6 +652,9 @@ function bluesky_create_post(array $item, stdClass $root = null, stdClass $paren $parent = bluesky_xrpc_post($uid, 'com.atproto.repo.createRecord', $post); if (empty($parent)) { + if ($part == 0) { + Worker::defer(); + } return; } Logger::debug('Posting done', ['return' => $parent]); @@ -663,6 +674,7 @@ function bluesky_get_urls(string $body): array // Remove all hashtag and mention links $body = preg_replace("/([#@!])\[url\=(.*?)\](.*?)\[\/url\]/ism", '$1$3', $body); + $body = BBCode::expandVideoLinks($body); $urls = []; // Search for pure links @@ -746,12 +758,15 @@ function bluesky_add_embed(int $uid, array $msg, array $record): array if (($msg['type'] != 'link') && !empty($msg['images'])) { $images = []; foreach ($msg['images'] as $image) { - $photo = Photo::selectFirst(['resource-id'], ['id' => $image['id']]); - $photo = Photo::selectFirst([], ["`resource-id` = ? AND `scale` > ?", $photo['resource-id'], 0], ['order' => ['scale']]); - $blob = bluesky_upload_blob($uid, $photo); - if (!empty($blob) && count($images) < 4) { - $images[] = ['alt' => $image['description'] ?? '', 'image' => $blob]; + if (count($images) == 4) { + continue; } + $photo = Photo::selectFirst([], ['id' => $image['id']]); + $blob = bluesky_upload_blob($uid, $photo); + if (empty($blob)) { + return []; + } + $images[] = ['alt' => $image['description'] ?? '', 'image' => $blob]; } if (!empty($images)) { $record['embed'] = ['$type' => 'app.bsky.embed.images', 'images' => $images]; @@ -778,13 +793,29 @@ function bluesky_add_embed(int $uid, array $msg, array $record): array function bluesky_upload_blob(int $uid, array $photo): ?stdClass { + $retrial = Worker::getRetrial(); $content = Photo::getImageForPhoto($photo); + + $picture = new Image($content, $photo['type']); + $height = $picture->getHeight(); + $width = $picture->getWidth(); + $size = strlen($content); + + $picture = Photo::resizeToFileSize($picture, BLUESKY_IMAGE_SIZE[$retrial]); + $new_height = $picture->getHeight(); + $new_width = $picture->getWidth(); + $content = $picture->asString(); + $new_size = strlen($content); + + Logger::info('Uploading', ['uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size]); + $data = bluesky_post($uid, '/xrpc/com.atproto.repo.uploadBlob', $content, ['Content-type' => $photo['type'], 'Authorization' => ['Bearer ' . bluesky_get_token($uid)]]); if (empty($data)) { + Logger::info('Uploading failed', ['uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size]); return null; } - Logger::debug('Uploaded blob', ['return' => $data]); + Logger::debug('Uploaded blob', ['return' => $data, 'uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size]); return $data->blob; } diff --git a/twitter/templates/connector_settings.tpl b/twitter/templates/connector_settings.tpl index bdb59891d..534f39dcf 100644 --- a/twitter/templates/connector_settings.tpl +++ b/twitter/templates/connector_settings.tpl @@ -4,4 +4,5 @@ {{include file="field_input.tpl" field=$api_key}} {{include file="field_input.tpl" field=$api_secret}} {{include file="field_input.tpl" field=$access_token}} -{{include file="field_input.tpl" field=$access_secret}} \ No newline at end of file +{{include file="field_input.tpl" field=$access_secret}} +{{include file="field_textarea.tpl" field=$status}} \ No newline at end of file diff --git a/twitter/twitter.php b/twitter/twitter.php index 4343e801b..7b2e424c2 100644 --- a/twitter/twitter.php +++ b/twitter/twitter.php @@ -47,12 +47,12 @@ use Friendica\Model\Post; use Friendica\Core\Config\Util\ConfigFileManager; use Friendica\Model\Photo; use Friendica\Object\Image; -use Friendica\Util\Images; use GuzzleHttp\Client; +use GuzzleHttp\Exception\RequestException; use GuzzleHttp\HandlerStack; use GuzzleHttp\Subscriber\Oauth\Oauth1; -const TWITTER_MAX_IMAGE_SIZE = 500000; +const TWITTER_IMAGE_SIZE = [2000000, 1000000, 500000, 100000, 50000]; function twitter_install() { @@ -115,6 +115,15 @@ function twitter_settings(array &$data) $api_secret = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'twitter', 'api_secret'); $access_token = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'twitter', 'access_token'); $access_secret = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'twitter', 'access_secret'); + + $last_status = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'twitter', 'last_status'); + if (empty($last_status)) { + $status = DI::l10n()->t('No status.'); + } elseif (!empty($last_status['code'])) { + $status = print_r($last_status, true); + } else { + $status = print_r($last_status, true); + } $t = Renderer::getMarkupTemplate('connector_settings.tpl', 'addon/twitter/'); $html = Renderer::replaceMacros($t, [ @@ -125,6 +134,7 @@ function twitter_settings(array &$data) '$access_token' => ['twitter-access-token', DI::l10n()->t('Access Token'), $access_token], '$access_secret' => ['twitter-access-secret', DI::l10n()->t('Access Secret'), $access_secret], '$help' => DI::l10n()->t('Each user needs to register their own app to be able to post to Twitter. Please visit https://developer.twitter.com/en/portal/projects-and-apps to register a project. Inside the project you then have to register an app. You will find the needed data for the connector on the page "Keys and token" in the app settings.'), + '$status' => ['twitter-status', DI::l10n()->t('Last Status'), $status, '', '', 'readonly'], ]); $data = [ @@ -216,16 +226,19 @@ function twitter_post_hook(array &$b) if (!empty($msgarr['images']) || !empty($msgarr['remote_images'])) { Logger::info('Got images', ['id' => $b['id'], 'images' => $msgarr['images'] ?? []]); + $retrial = Worker::getRetrial(); + if ($retrial > 4) { + return; + } foreach ($msgarr['images'] ?? [] as $image) { if (count($media_ids) == 4) { continue; } try { - $media_ids[] = twitter_upload_image($b['uid'], $image, $b); - } catch (\Throwable $th) { - Logger::warning('Error while uploading image', ['image' => $image, 'code' => $th->getCode(), 'message' => $th->getMessage()]); - // Currently don't defer to avoid a loop. - //Worker::defer(); + $media_ids[] = twitter_upload_image($b['uid'], $image, $retrial); + } catch (RequestException $exception) { + Logger::warning('Error while uploading image', ['image' => $image, 'code' => $exception->getCode(), 'message' => $exception->getMessage()]); + Worker::defer(); return; } } @@ -238,9 +251,17 @@ function twitter_post_hook(array &$b) try { $id = twitter_post_status($b['uid'], $part, $media_ids, $in_reply_to_tweet_id); Logger::info('twitter_post send', ['part' => $key, 'id' => $b['id'], 'result' => $id]); - } catch (\Throwable $th) { - Logger::warning('Error while posting message', ['part' => $key, 'id' => $b['id'], 'code' => $th->getCode(), 'message' => $th->getMessage()]); - Worker::defer(); + } catch (RequestException $exception) { + Logger::warning('Error while posting message', ['part' => $key, 'id' => $b['id'], 'code' => $exception->getCode(), 'message' => $exception->getMessage()]); + $status = [ + 'code' => $exception->getCode(), + 'reason' => $exception->getResponse()->getReasonPhrase(), + 'content' => $exception->getMessage() + ]; + DI::pConfig()->set($b['uid'], 'twitter', 'last_status', $status); + if ($key == 0) { + Worker::defer(); + } break; } @@ -264,7 +285,7 @@ function twitter_post_status(int $uid, string $status, array $media_ids = [], st return $response->data->id; } -function twitter_upload_image(int $uid, array $image) +function twitter_upload_image(int $uid, array $image, int $retrial) { if (!empty($image['id'])) { $photo = Photo::selectFirst([], ['id' => $image['id']]); @@ -274,14 +295,20 @@ function twitter_upload_image(int $uid, array $image) $picturedata = Photo::getImageForPhoto($photo); - $type = Images::getMimeTypeByData($picturedata, $photo['filename'], $photo['type']); - - $picture = Photo::resizeToFileSize(new Image($picturedata, $type), TWITTER_MAX_IMAGE_SIZE); + $picture = new Image($picturedata, $photo['type']); + $height = $picture->getHeight(); + $width = $picture->getWidth(); + $size = strlen($picturedata); + $picture = Photo::resizeToFileSize($picture, TWITTER_IMAGE_SIZE[$retrial]); + $new_height = $picture->getHeight(); + $new_width = $picture->getWidth(); $picturedata = $picture->asString(); + $new_size = strlen($picturedata); - Logger::info('Uploading', ['uid' => $uid, 'size' => strlen($picturedata), 'type' => @getimagesizefromstring($picturedata), 'photo' => $photo]); + Logger::info('Uploading', ['uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size, 'image' => $image]); $media = twitter_post($uid, 'https://upload.twitter.com/1.1/media/upload.json', 'form_params', ['media' => base64_encode($picturedata)]); + Logger::info('Uploading done', ['uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size, 'image' => $image]); if (isset($media->media_id_string)) { $media_id = $media->media_id_string; @@ -323,6 +350,14 @@ function twitter_post(int $uid, string $url, string $type, array $data): stdClas $response = $client->post($url, ['auth' => 'oauth', $type => $data]); + $status = [ + 'code' => $response->getStatusCode(), + 'reason' => $response->getReasonPhrase(), + 'content' => $response->getBody()->getContents() + ]; + + DI::pConfig()->set($uid, 'twitter', 'last_status', $status); + $content = json_decode($response->getBody()->getContents()) ?? new stdClass; Logger::debug('Success', ['content' => $content]); return $content; From 3d6748eaf7e6a42e2e993a19bd8c8f37f7fc9967 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 15 Aug 2023 20:43:32 +0000 Subject: [PATCH 020/388] Simplified status display --- twitter/twitter.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/twitter/twitter.php b/twitter/twitter.php index 7b2e424c2..c033fa936 100644 --- a/twitter/twitter.php +++ b/twitter/twitter.php @@ -117,12 +117,10 @@ function twitter_settings(array &$data) $access_secret = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'twitter', 'access_secret'); $last_status = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'twitter', 'last_status'); - if (empty($last_status)) { - $status = DI::l10n()->t('No status.'); - } elseif (!empty($last_status['code'])) { + if (!empty($last_status['code'])) { $status = print_r($last_status, true); } else { - $status = print_r($last_status, true); + $status = DI::l10n()->t('No status.'); } $t = Renderer::getMarkupTemplate('connector_settings.tpl', 'addon/twitter/'); From a3e24a55ec5ac3b25e3a442026e78ef4dacca452 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 16 Aug 2023 03:28:54 +0000 Subject: [PATCH 021/388] Last status is split for better readability --- twitter/lang/C/messages.po | 34 ++++++++++++++++-------- twitter/templates/connector_settings.tpl | 1 + twitter/twitter.php | 10 ++++--- 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/twitter/lang/C/messages.po b/twitter/lang/C/messages.po index 4bcc4efa5..366d6c8fe 100644 --- a/twitter/lang/C/messages.po +++ b/twitter/lang/C/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-08-09 19:59+0000\n" +"POT-Creation-Date: 2023-08-16 03:27+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,42 +17,46 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: twitter.php:80 +#: twitter.php:84 msgid "Post to Twitter" msgstr "" -#: twitter.php:117 +#: twitter.php:123 +msgid "No status." +msgstr "" + +#: twitter.php:129 msgid "Allow posting to Twitter" msgstr "" -#: twitter.php:117 +#: twitter.php:129 msgid "" "If enabled all your public postings can be posted to the " "associated Twitter account. You can choose to do so by default (here) or for " "every posting separately in the posting options when writing the entry." msgstr "" -#: twitter.php:118 +#: twitter.php:130 msgid "Send public postings to Twitter by default" msgstr "" -#: twitter.php:119 +#: twitter.php:131 msgid "API Key" msgstr "" -#: twitter.php:120 +#: twitter.php:132 msgid "API Secret" msgstr "" -#: twitter.php:121 +#: twitter.php:133 msgid "Access Token" msgstr "" -#: twitter.php:122 +#: twitter.php:134 msgid "Access Secret" msgstr "" -#: twitter.php:123 +#: twitter.php:135 msgid "" "Each user needs to register their own app to be able to post to Twitter. " "Please visit https://developer.twitter.com/en/portal/projects-and-apps to " @@ -61,6 +65,14 @@ msgid "" "in the app settings." msgstr "" -#: twitter.php:128 +#: twitter.php:136 +msgid "Last Status Summary" +msgstr "" + +#: twitter.php:137 +msgid "Last Status Content" +msgstr "" + +#: twitter.php:142 msgid "Twitter Export" msgstr "" diff --git a/twitter/templates/connector_settings.tpl b/twitter/templates/connector_settings.tpl index 534f39dcf..251093dea 100644 --- a/twitter/templates/connector_settings.tpl +++ b/twitter/templates/connector_settings.tpl @@ -5,4 +5,5 @@ {{include file="field_input.tpl" field=$api_secret}} {{include file="field_input.tpl" field=$access_token}} {{include file="field_input.tpl" field=$access_secret}} +{{include file="field_input.tpl" field=$status_title}} {{include file="field_textarea.tpl" field=$status}} \ No newline at end of file diff --git a/twitter/twitter.php b/twitter/twitter.php index c033fa936..d52da4f7a 100644 --- a/twitter/twitter.php +++ b/twitter/twitter.php @@ -117,11 +117,12 @@ function twitter_settings(array &$data) $access_secret = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'twitter', 'access_secret'); $last_status = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'twitter', 'last_status'); - if (!empty($last_status['code'])) { - $status = print_r($last_status, true); + if (!empty($last_status['code']) && !empty($last_status['reason'])) { + $status_title = sprintf('%d - %s', $last_status['code'], $last_status['reason']); } else { - $status = DI::l10n()->t('No status.'); + $status_title = DI::l10n()->t('No status.'); } + $status_content = $last_status['content'] ?? ''; $t = Renderer::getMarkupTemplate('connector_settings.tpl', 'addon/twitter/'); $html = Renderer::replaceMacros($t, [ @@ -132,7 +133,8 @@ function twitter_settings(array &$data) '$access_token' => ['twitter-access-token', DI::l10n()->t('Access Token'), $access_token], '$access_secret' => ['twitter-access-secret', DI::l10n()->t('Access Secret'), $access_secret], '$help' => DI::l10n()->t('Each user needs to register their own app to be able to post to Twitter. Please visit https://developer.twitter.com/en/portal/projects-and-apps to register a project. Inside the project you then have to register an app. You will find the needed data for the connector on the page "Keys and token" in the app settings.'), - '$status' => ['twitter-status', DI::l10n()->t('Last Status'), $status, '', '', 'readonly'], + '$status_title' => ['twitter-status-title', DI::l10n()->t('Last Status Summary'), $status_title, '', '', 'readonly'], + '$status' => ['twitter-status', DI::l10n()->t('Last Status Content'), $status_content, '', '', 'readonly'], ]); $data = [ From 339c88353b4d152218e56f91bf9879658980aa93 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 16 Aug 2023 06:17:18 +0000 Subject: [PATCH 022/388] Test the connection when API credential changed --- twitter/twitter.php | 48 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/twitter/twitter.php b/twitter/twitter.php index d52da4f7a..7b46508e4 100644 --- a/twitter/twitter.php +++ b/twitter/twitter.php @@ -94,12 +94,23 @@ function twitter_settings_post() return; } + $api_key = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'twitter', 'api_key'); + $api_secret = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'twitter', 'api_secret'); + $access_token = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'twitter', 'access_token'); + $access_secret = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'twitter', 'access_secret'); + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'twitter', 'post', (bool)$_POST['twitter-enable']); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'twitter', 'post_by_default', (bool)$_POST['twitter-default']); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'twitter', 'api_key', $_POST['twitter-api-key']); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'twitter', 'api_secret', $_POST['twitter-api-secret']); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'twitter', 'access_token', $_POST['twitter-access-token']); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'twitter', 'access_secret', $_POST['twitter-access-secret']); + + if (empty(DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'twitter', 'last_status')) || + ($api_key != $_POST['twitter-api-key']) || ($api_secret != $_POST['twitter-api-secret']) || + ($access_token != $_POST['twitter-access-token']) || ($access_secret != $_POST['twitter-access-secret'])) { + twitter_test_connection(DI::userSession()->getLocalUserId()); + } } function twitter_settings(array &$data) @@ -362,3 +373,40 @@ function twitter_post(int $uid, string $url, string $type, array $data): stdClas Logger::debug('Success', ['content' => $content]); return $content; } + +function twitter_test_connection(int $uid) +{ + $stack = HandlerStack::create(); + + $middleware = new Oauth1([ + 'consumer_key' => DI::pConfig()->get($uid, 'twitter', 'api_key'), + 'consumer_secret' => DI::pConfig()->get($uid, 'twitter', 'api_secret'), + 'token' => DI::pConfig()->get($uid, 'twitter', 'access_token'), + 'token_secret' => DI::pConfig()->get($uid, 'twitter', 'access_secret'), + ]); + + $stack->push($middleware); + + $client = new Client([ + 'handler' => $stack + ]); + + try { + $response = $client->get('https://api.twitter.com/2/users/me', ['auth' => 'oauth']); + $status = [ + 'code' => $response->getStatusCode(), + 'reason' => $response->getReasonPhrase(), + 'content' => $response->getBody()->getContents() + ]; + DI::pConfig()->set(1, 'twitter', 'last_status', $status); + Logger::info('Test successful', ['uid' => $uid]); + } catch (RequestException $exception) { + $status = [ + 'code' => $exception->getCode(), + 'reason' => $exception->getResponse()->getReasonPhrase(), + 'content' => $exception->getMessage() + ]; + DI::pConfig()->set(1, 'twitter', 'last_status', $status); + Logger::info('Test failed', ['uid' => $uid]); + } +} \ No newline at end of file From 340f3f41d7d61bace2a3f2f776b109ab116edcc3 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 16 Aug 2023 14:20:32 +0000 Subject: [PATCH 023/388] Twitter: Fix posting --- twitter/twitter.php | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/twitter/twitter.php b/twitter/twitter.php index 7b46508e4..b01345b74 100644 --- a/twitter/twitter.php +++ b/twitter/twitter.php @@ -106,9 +106,11 @@ function twitter_settings_post() DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'twitter', 'access_token', $_POST['twitter-access-token']); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'twitter', 'access_secret', $_POST['twitter-access-secret']); - if (empty(DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'twitter', 'last_status')) || + if ( + empty(DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'twitter', 'last_status')) || ($api_key != $_POST['twitter-api-key']) || ($api_secret != $_POST['twitter-api-secret']) || - ($access_token != $_POST['twitter-access-token']) || ($access_secret != $_POST['twitter-access-secret'])) { + ($access_token != $_POST['twitter-access-token']) || ($access_secret != $_POST['twitter-access-secret']) + ) { twitter_test_connection(DI::userSession()->getLocalUserId()); } } @@ -126,7 +128,7 @@ function twitter_settings(array &$data) $api_secret = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'twitter', 'api_secret'); $access_token = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'twitter', 'access_token'); $access_secret = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'twitter', 'access_secret'); - + $last_status = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'twitter', 'last_status'); if (!empty($last_status['code']) && !empty($last_status['reason'])) { $status_title = sprintf('%d - %s', $last_status['code'], $last_status['reason']); @@ -308,12 +310,12 @@ function twitter_upload_image(int $uid, array $image, int $retrial) $picture = new Image($picturedata, $photo['type']); $height = $picture->getHeight(); - $width = $picture->getWidth(); + $width = $picture->getWidth(); $size = strlen($picturedata); $picture = Photo::resizeToFileSize($picture, TWITTER_IMAGE_SIZE[$retrial]); $new_height = $picture->getHeight(); - $new_width = $picture->getWidth(); + $new_width = $picture->getWidth(); $picturedata = $picture->asString(); $new_size = strlen($picturedata); @@ -360,16 +362,17 @@ function twitter_post(int $uid, string $url, string $type, array $data): stdClas ]); $response = $client->post($url, ['auth' => 'oauth', $type => $data]); + $body = $response->getBody()->getContents(); $status = [ - 'code' => $response->getStatusCode(), - 'reason' => $response->getReasonPhrase(), - 'content' => $response->getBody()->getContents() + 'code' => $response->getStatusCode(), + 'reason' => $response->getReasonPhrase(), + 'content' => $body ]; DI::pConfig()->set($uid, 'twitter', 'last_status', $status); - $content = json_decode($response->getBody()->getContents()) ?? new stdClass; + $content = json_decode($body) ?? new stdClass; Logger::debug('Success', ['content' => $content]); return $content; } @@ -390,7 +393,7 @@ function twitter_test_connection(int $uid) $client = new Client([ 'handler' => $stack ]); - + try { $response = $client->get('https://api.twitter.com/2/users/me', ['auth' => 'oauth']); $status = [ @@ -402,11 +405,11 @@ function twitter_test_connection(int $uid) Logger::info('Test successful', ['uid' => $uid]); } catch (RequestException $exception) { $status = [ - 'code' => $exception->getCode(), - 'reason' => $exception->getResponse()->getReasonPhrase(), + 'code' => $exception->getCode(), + 'reason' => $exception->getResponse()->getReasonPhrase(), 'content' => $exception->getMessage() ]; DI::pConfig()->set(1, 'twitter', 'last_status', $status); Logger::info('Test failed', ['uid' => $uid]); } -} \ No newline at end of file +} From effa19c467fda5138b601196b53d26a48ed963b1 Mon Sep 17 00:00:00 2001 From: loma-one Date: Tue, 20 Jun 2023 17:26:03 +0200 Subject: [PATCH 024/388] Audon Audio Chat based on the WebRTC Addon This Addon based on webrtc. Audon is a service of realtime audio chat. With small changes, the WebRTC addon could be adapted to Audon so that it can be loaded into an iframe. In the ifram, the Friendica handle can be connected and a room opened. Audio conversations between Friendica users are possible. https://github.com/friendica/friendica-addons/pull/1357 --- audon/README.md | 6 +++++ audon/admin.tpl | 2 ++ audon/audon.php | 68 +++++++++++++++++++++++++++++++++++++++++++++++ audon/messages.po | 53 ++++++++++++++++++++++++++++++++++++ 4 files changed, 129 insertions(+) create mode 100644 audon/README.md create mode 100644 audon/admin.tpl create mode 100644 audon/audon.php create mode 100644 audon/messages.po diff --git a/audon/README.md b/audon/README.md new file mode 100644 index 000000000..beb89a1e0 --- /dev/null +++ b/audon/README.md @@ -0,0 +1,6 @@ +Audon Addon +============= + +This is a quick and dirty addon to add a [Audon][1] website as an app. This Addon based on webrtc. Audon is a service of realtime audio chat + +[1]: https://codeberg.org/nmkj/audon diff --git a/audon/admin.tpl b/audon/admin.tpl new file mode 100644 index 000000000..917ebd679 --- /dev/null +++ b/audon/admin.tpl @@ -0,0 +1,2 @@ +{{include file="field_input.tpl" field=$audonurl}} +

diff --git a/audon/audon.php b/audon/audon.php new file mode 100644 index 000000000..10eeb5141 --- /dev/null +++ b/audon/audon.php @@ -0,0 +1,68 @@ +< + * Author: Tobias Diekershoff + * Author: Matthias Ebers + */ + +use Friendica\Core\Hook; +use Friendica\Core\Renderer; +use Friendica\DI; + +function audon_install() +{ + Hook::register('app_menu', __FILE__, 'audon_app_menu'); +} + +function audon_app_menu(array &$b) +{ + $b['app_menu'][] = ''; +} + +function audon_addon_admin(string &$o) +{ + $t = Renderer::getMarkupTemplate('admin.tpl', 'addon/audon/'); + $o = Renderer::replaceMacros($t, [ + '$submit' => DI::l10n()->t('Save Settings'), + '$audonurl' => [ + 'audonurl', + DI::l10n()->t('audon Base URL'), + DI::config()->get('audon','audonurl'), + DI::l10n()->t('Page your users will create a audon Audio chat room on. For example you could use https://audon.space.'), + ], + ]); +} + +function audon_addon_admin_post() +{ + DI::config()->set('audon', 'audonurl', trim($_POST['audonurl'] ?? '')); +} + +/** + * This is a statement rather than an actual function definition. The simple + * existence of this method is checked to figure out if the addon offers a + * module. + */ +function audon_module() {} + +function audon_content(): string +{ + $o = ''; + + /* landingpage to create chatrooms */ + $audonurl = DI::config()->get('audon','audonurl'); + + /* embedd the landing page in an iframe */ + $o .= '

' . DI::l10n()->t('Audio Chat') . '

'; + $o .= '

' . DI::l10n()->t('Audon is an audio conferencing tool. Connect your account to Audon and create a room. Share the generated link to talk to other participants.') . '

'; + if ($audonurl == '') { + $o .= '

' . DI::l10n()->t('Please contact your friendica administrator to remind them to configure the Audon addon.') . '

'; + } else { + $o .= ''; + } + + return $o; +} diff --git a/audon/messages.po b/audon/messages.po new file mode 100644 index 000000000..ad233014d --- /dev/null +++ b/audon/messages.po @@ -0,0 +1,53 @@ +# ADDON webrtc +# Copyright (C) +# This file is distributed under the same license as the Friendica webrtc addon package. +# +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-04-29 15:56+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: webrtc.php:18 +msgid "WebRTC Videochat" +msgstr "" + +#: webrtc.php:24 +msgid "Save Settings" +msgstr "" + +#: webrtc.php:25 +msgid "WebRTC Base URL" +msgstr "" + +#: webrtc.php:25 +msgid "" +"Page your users will create a WebRTC chat room on. For example you could use " +"https://live.mayfirst.org ." +msgstr "" + +#: webrtc.php:44 +msgid "Video Chat" +msgstr "" + +#: webrtc.php:45 +msgid "" +"WebRTC is a video and audio conferencing tool that works in all modern " +"browsers. Just create a new chat room and send the link to someone you want " +"to chat with." +msgstr "" + +#: webrtc.php:47 +msgid "" +"Please contact your friendica admin and send a reminder to configure the " +"WebRTC addon." +msgstr "" From 630f4ab9914efdd4b863b642925b5c8348b23f95 Mon Sep 17 00:00:00 2001 From: loma-one Date: Tue, 20 Jun 2023 17:26:57 +0200 Subject: [PATCH 025/388] =?UTF-8?q?=E2=80=9Eaudon/messages.po=E2=80=9C=20l?= =?UTF-8?q?=C3=B6schen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- audon/messages.po | 53 ----------------------------------------------- 1 file changed, 53 deletions(-) delete mode 100644 audon/messages.po diff --git a/audon/messages.po b/audon/messages.po deleted file mode 100644 index ad233014d..000000000 --- a/audon/messages.po +++ /dev/null @@ -1,53 +0,0 @@ -# ADDON webrtc -# Copyright (C) -# This file is distributed under the same license as the Friendica webrtc addon package. -# -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: \n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-04-29 15:56+0200\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME \n" -"Language-Team: LANGUAGE \n" -"Language: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" - -#: webrtc.php:18 -msgid "WebRTC Videochat" -msgstr "" - -#: webrtc.php:24 -msgid "Save Settings" -msgstr "" - -#: webrtc.php:25 -msgid "WebRTC Base URL" -msgstr "" - -#: webrtc.php:25 -msgid "" -"Page your users will create a WebRTC chat room on. For example you could use " -"https://live.mayfirst.org ." -msgstr "" - -#: webrtc.php:44 -msgid "Video Chat" -msgstr "" - -#: webrtc.php:45 -msgid "" -"WebRTC is a video and audio conferencing tool that works in all modern " -"browsers. Just create a new chat room and send the link to someone you want " -"to chat with." -msgstr "" - -#: webrtc.php:47 -msgid "" -"Please contact your friendica admin and send a reminder to configure the " -"WebRTC addon." -msgstr "" From 4e17f3c9dbc68dea0b0bca6ae73b4e44e403d7c3 Mon Sep 17 00:00:00 2001 From: loma-one Date: Tue, 20 Jun 2023 17:27:07 +0200 Subject: [PATCH 026/388] =?UTF-8?q?=E2=80=9Eaudon/admin.tpl=E2=80=9C=20l?= =?UTF-8?q?=C3=B6schen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- audon/admin.tpl | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 audon/admin.tpl diff --git a/audon/admin.tpl b/audon/admin.tpl deleted file mode 100644 index 917ebd679..000000000 --- a/audon/admin.tpl +++ /dev/null @@ -1,2 +0,0 @@ -{{include file="field_input.tpl" field=$audonurl}} -
From 9035144e5bff9dfb3cec233aa10de6c10fb52981 Mon Sep 17 00:00:00 2001 From: loma-one Date: Tue, 20 Jun 2023 17:27:41 +0200 Subject: [PATCH 027/388] =?UTF-8?q?Dateien=20hochladen=20nach=20=E2=80=9Ea?= =?UTF-8?q?udon/templates=E2=80=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- audon/templates/admin.tpl | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 audon/templates/admin.tpl diff --git a/audon/templates/admin.tpl b/audon/templates/admin.tpl new file mode 100644 index 000000000..917ebd679 --- /dev/null +++ b/audon/templates/admin.tpl @@ -0,0 +1,2 @@ +{{include file="field_input.tpl" field=$audonurl}} +
From a3dc032a51af30e87a659116b9bc5c6c6ab6d6b3 Mon Sep 17 00:00:00 2001 From: loma-one Date: Tue, 20 Jun 2023 17:28:39 +0200 Subject: [PATCH 028/388] =?UTF-8?q?=E2=80=9Eaudon/lang/C=E2=80=9C=20hinzuf?= =?UTF-8?q?=C3=BCgen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- audon/lang/C | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 audon/lang/C diff --git a/audon/lang/C b/audon/lang/C new file mode 100644 index 000000000..ad233014d --- /dev/null +++ b/audon/lang/C @@ -0,0 +1,53 @@ +# ADDON webrtc +# Copyright (C) +# This file is distributed under the same license as the Friendica webrtc addon package. +# +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-04-29 15:56+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: webrtc.php:18 +msgid "WebRTC Videochat" +msgstr "" + +#: webrtc.php:24 +msgid "Save Settings" +msgstr "" + +#: webrtc.php:25 +msgid "WebRTC Base URL" +msgstr "" + +#: webrtc.php:25 +msgid "" +"Page your users will create a WebRTC chat room on. For example you could use " +"https://live.mayfirst.org ." +msgstr "" + +#: webrtc.php:44 +msgid "Video Chat" +msgstr "" + +#: webrtc.php:45 +msgid "" +"WebRTC is a video and audio conferencing tool that works in all modern " +"browsers. Just create a new chat room and send the link to someone you want " +"to chat with." +msgstr "" + +#: webrtc.php:47 +msgid "" +"Please contact your friendica admin and send a reminder to configure the " +"WebRTC addon." +msgstr "" From e391a65695770375b368f900fbe3c9f239cbc6d9 Mon Sep 17 00:00:00 2001 From: loma-one Date: Tue, 20 Jun 2023 17:47:55 +0200 Subject: [PATCH 029/388] =?UTF-8?q?=E2=80=9Eaudon/audon.php=E2=80=9C=20?= =?UTF-8?q?=C3=A4ndern?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- audon/audon.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/audon/audon.php b/audon/audon.php index 10eeb5141..d09302272 100644 --- a/audon/audon.php +++ b/audon/audon.php @@ -1,4 +1,4 @@ -< Date: Fri, 18 Aug 2023 16:17:47 +0200 Subject: [PATCH 030/388] audon/audon.php aktualisiert --- audon/audon.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/audon/audon.php b/audon/audon.php index d09302272..59a79ea31 100644 --- a/audon/audon.php +++ b/audon/audon.php @@ -1,6 +1,6 @@ @@ -26,13 +26,13 @@ function audon_addon_admin(string &$o) { $t = Renderer::getMarkupTemplate('admin.tpl', 'addon/audon/'); $o = Renderer::replaceMacros($t, [ - '$submit' => DI::l10n()->t('Save Settings'), + '$submit' => DI::l10n()->t('Save Settings'), '$audonurl' => [ - 'audonurl', - DI::l10n()->t('audon Base URL'), - DI::config()->get('audon','audonurl'), + 'audonurl', + DI::l10n()->t('audon Base URL'), + DI::config()->get('audon','audonurl'), DI::l10n()->t('Page your users will create a audon Audio chat room on. For example you could use https://audon.space.'), - ], + ], ]); } From 38460a4cff68b24075300c5c7c493c03bd387ee4 Mon Sep 17 00:00:00 2001 From: loma-one Date: Fri, 18 Aug 2023 16:18:33 +0200 Subject: [PATCH 031/388] audon/audon.php aktualisiert --- audon/audon.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/audon/audon.php b/audon/audon.php index 59a79ea31..bf0211b38 100644 --- a/audon/audon.php +++ b/audon/audon.php @@ -31,7 +31,7 @@ function audon_addon_admin(string &$o) 'audonurl', DI::l10n()->t('audon Base URL'), DI::config()->get('audon','audonurl'), - DI::l10n()->t('Page your users will create a audon Audio chat room on. For example you could use https://audon.space.'), + DI::l10n()->t('Page your users will create a audon Audio chat room on. For example you could use https://audon.space.'), ], ]); } From 65d8e467fe5b674a1622712af7b44d25c0a3a92d Mon Sep 17 00:00:00 2001 From: loma-one Date: Fri, 18 Aug 2023 16:24:04 +0200 Subject: [PATCH 032/388] audon/templates/admin.tpl aktualisiert --- audon/templates/admin.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/audon/templates/admin.tpl b/audon/templates/admin.tpl index 917ebd679..e27585833 100644 --- a/audon/templates/admin.tpl +++ b/audon/templates/admin.tpl @@ -1,2 +1,2 @@ {{include file="field_input.tpl" field=$audonurl}} -
+ From c93e6840fa68cc10bdf183c07d1e96142c28b03b Mon Sep 17 00:00:00 2001 From: loma-one Date: Fri, 18 Aug 2023 16:48:13 +0200 Subject: [PATCH 033/388] audon/audon.php aktualisiert --- audon/audon.php | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/audon/audon.php b/audon/audon.php index bf0211b38..5d41fec73 100644 --- a/audon/audon.php +++ b/audon/audon.php @@ -1,7 +1,7 @@ * Author: Tobias Diekershoff @@ -19,7 +19,7 @@ function audon_install() function audon_app_menu(array &$b) { - $b['app_menu'][] = ''; + $b['app_menu'][] = ''; } function audon_addon_admin(string &$o) @@ -29,9 +29,9 @@ function audon_addon_admin(string &$o) '$submit' => DI::l10n()->t('Save Settings'), '$audonurl' => [ 'audonurl', - DI::l10n()->t('audon Base URL'), + DI::l10n()->t('Audon Base URL'), DI::config()->get('audon','audonurl'), - DI::l10n()->t('Page your users will create a audon Audio chat room on. For example you could use https://audon.space.'), + DI::l10n()->t('Page your users will create an Audon audio chat room on. For example you could use https://audon.space.'), ], ]); } @@ -53,13 +53,14 @@ function audon_content(): string $o = ''; /* landingpage to create chatrooms */ - $audonurl = DI::config()->get('audon','audonurl'); + $audonurl = DI::config()->get('audon', 'audonurl'); + /* embedd the landing page in an iframe */ $o .= '

' . DI::l10n()->t('Audio Chat') . '

'; $o .= '

' . DI::l10n()->t('Audon is an audio conferencing tool. Connect your account to Audon and create a room. Share the generated link to talk to other participants.') . '

'; if ($audonurl == '') { - $o .= '

' . DI::l10n()->t('Please contact your friendica administrator to remind them to configure the Audon addon.') . '

'; + $o .= '

' . DI::l10n()->t('Please contact your Friendica administrator to remind them to configure the Audon addon.') . '

'; } else { $o .= ''; } From 8ef6fafdaa91b273bc10dc6d5a74ab3efd72babf Mon Sep 17 00:00:00 2001 From: loma-one Date: Fri, 18 Aug 2023 16:51:29 +0200 Subject: [PATCH 034/388] audon/audon.php aktualisiert --- audon/audon.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/audon/audon.php b/audon/audon.php index 5d41fec73..553e7f5c5 100644 --- a/audon/audon.php +++ b/audon/audon.php @@ -1,7 +1,7 @@ * Author: Tobias Diekershoff From a26c2c975825051bd86907c2d96d157ccdd72239 Mon Sep 17 00:00:00 2001 From: loma-one Date: Fri, 18 Aug 2023 17:19:03 +0200 Subject: [PATCH 035/388] audon/lang/C aktualisiert --- audon/lang/C | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/audon/lang/C b/audon/lang/C index ad233014d..3e7df9770 100644 --- a/audon/lang/C +++ b/audon/lang/C @@ -1,6 +1,6 @@ -# ADDON webrtc +# ADDON Audon # Copyright (C) -# This file is distributed under the same license as the Friendica webrtc addon package. +# This file is distributed under the same license as the Friendica Audon addon package. # # #, fuzzy @@ -17,37 +17,37 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: webrtc.php:18 -msgid "WebRTC Videochat" +#: audon.php:19 +msgid "Audon audio conferencing" msgstr "" -#: webrtc.php:24 +#: audon.php:25 msgid "Save Settings" msgstr "" -#: webrtc.php:25 -msgid "WebRTC Base URL" +#: audon.php:26 +msgid "Audon Base URL" msgstr "" -#: webrtc.php:25 +#: audon.php:26 msgid "" -"Page your users will create a WebRTC chat room on. For example you could use " -"https://live.mayfirst.org ." +"Page your users will create a Audon audio conferencing on. For example you could use " +"https://audon.space ." msgstr "" -#: webrtc.php:44 -msgid "Video Chat" +#: audon.php:44 +msgid "Audio Chat" msgstr "" -#: webrtc.php:45 +#: audon.php:45 msgid "" -"WebRTC is a video and audio conferencing tool that works in all modern " -"browsers. Just create a new chat room and send the link to someone you want " -"to chat with." +"Audon is a audio conferencing tool that works in all modern " +"browsers. Just create a new Audio room and send the link to someone you want " +"to talk with." msgstr "" -#: webrtc.php:47 +#: audon.php:47 msgid "" "Please contact your friendica admin and send a reminder to configure the " -"WebRTC addon." +"Audon addon." msgstr "" From 9786b605b62abcfa4add190f98346150d1846229 Mon Sep 17 00:00:00 2001 From: loma-one Date: Fri, 18 Aug 2023 18:26:01 +0200 Subject: [PATCH 036/388] audon/lang/C aktualisiert now :) --- audon/lang/C | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/audon/lang/C b/audon/lang/C index 3e7df9770..c8fd38af0 100644 --- a/audon/lang/C +++ b/audon/lang/C @@ -1,6 +1,6 @@ -# ADDON Audon +# ADDON audon # Copyright (C) -# This file is distributed under the same license as the Friendica Audon addon package. +# This file is distributed under the same license as the Friendica audon addon package. # # #, fuzzy @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-04-29 15:56+0200\n" +"POT-Creation-Date: 2023-08-18 18:23+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,37 +17,36 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: audon.php:19 -msgid "Audon audio conferencing" +#: audon.php:22 +msgid "Audon Audiochat" msgstr "" -#: audon.php:25 +#: audon.php:29 msgid "Save Settings" msgstr "" -#: audon.php:26 +#: audon.php:32 msgid "Audon Base URL" msgstr "" -#: audon.php:26 +#: audon.php:34 msgid "" -"Page your users will create a Audon audio conferencing on. For example you could use " -"https://audon.space ." +"Page your users will create an Audon audio chat room on. For example you " +"could use https://audon.space." msgstr "" -#: audon.php:44 +#: audon.php:60 msgid "Audio Chat" msgstr "" -#: audon.php:45 +#: audon.php:61 msgid "" -"Audon is a audio conferencing tool that works in all modern " -"browsers. Just create a new Audio room and send the link to someone you want " -"to talk with." +"Audon is an audio conferencing tool. Connect your account to Audon and " +"create a room. Share the generated link to talk to other participants." msgstr "" -#: audon.php:47 +#: audon.php:63 msgid "" -"Please contact your friendica admin and send a reminder to configure the " +"Please contact your Friendica administrator to remind them to configure the " "Audon addon." msgstr "" From 476fdd1bb7a7d74efb4f903c0a7e307e31c7e83e Mon Sep 17 00:00:00 2001 From: loma-one Date: Fri, 18 Aug 2023 18:35:33 +0200 Subject: [PATCH 037/388] =?UTF-8?q?audon/lang/C=20gel=C3=B6scht?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: loma-one --- audon/lang/C | 52 ---------------------------------------------------- 1 file changed, 52 deletions(-) delete mode 100644 audon/lang/C diff --git a/audon/lang/C b/audon/lang/C deleted file mode 100644 index c8fd38af0..000000000 --- a/audon/lang/C +++ /dev/null @@ -1,52 +0,0 @@ -# ADDON audon -# Copyright (C) -# This file is distributed under the same license as the Friendica audon addon package. -# -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: \n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-08-18 18:23+0200\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME \n" -"Language-Team: LANGUAGE \n" -"Language: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" - -#: audon.php:22 -msgid "Audon Audiochat" -msgstr "" - -#: audon.php:29 -msgid "Save Settings" -msgstr "" - -#: audon.php:32 -msgid "Audon Base URL" -msgstr "" - -#: audon.php:34 -msgid "" -"Page your users will create an Audon audio chat room on. For example you " -"could use https://audon.space." -msgstr "" - -#: audon.php:60 -msgid "Audio Chat" -msgstr "" - -#: audon.php:61 -msgid "" -"Audon is an audio conferencing tool. Connect your account to Audon and " -"create a room. Share the generated link to talk to other participants." -msgstr "" - -#: audon.php:63 -msgid "" -"Please contact your Friendica administrator to remind them to configure the " -"Audon addon." -msgstr "" From 7ef59da623fcd3813b8f7a695edafd1b203107a7 Mon Sep 17 00:00:00 2001 From: loma-one Date: Fri, 18 Aug 2023 18:36:03 +0200 Subject: [PATCH 038/388] =?UTF-8?q?audon/C/messages.po=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- audon/C/messages.po | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 audon/C/messages.po diff --git a/audon/C/messages.po b/audon/C/messages.po new file mode 100644 index 000000000..e69de29bb From 2fa030aa65244c6037030ff60377a677cfc40488 Mon Sep 17 00:00:00 2001 From: loma-one Date: Fri, 18 Aug 2023 18:36:32 +0200 Subject: [PATCH 039/388] audon/C/messages.po aktualisiert --- audon/C/messages.po | 52 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/audon/C/messages.po b/audon/C/messages.po index e69de29bb..c8fd38af0 100644 --- a/audon/C/messages.po +++ b/audon/C/messages.po @@ -0,0 +1,52 @@ +# ADDON audon +# Copyright (C) +# This file is distributed under the same license as the Friendica audon addon package. +# +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-08-18 18:23+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: audon.php:22 +msgid "Audon Audiochat" +msgstr "" + +#: audon.php:29 +msgid "Save Settings" +msgstr "" + +#: audon.php:32 +msgid "Audon Base URL" +msgstr "" + +#: audon.php:34 +msgid "" +"Page your users will create an Audon audio chat room on. For example you " +"could use https://audon.space." +msgstr "" + +#: audon.php:60 +msgid "Audio Chat" +msgstr "" + +#: audon.php:61 +msgid "" +"Audon is an audio conferencing tool. Connect your account to Audon and " +"create a room. Share the generated link to talk to other participants." +msgstr "" + +#: audon.php:63 +msgid "" +"Please contact your Friendica administrator to remind them to configure the " +"Audon addon." +msgstr "" From 983d334ef5d82d63eab4de56d0c74342324f257c Mon Sep 17 00:00:00 2001 From: loma-one Date: Fri, 18 Aug 2023 18:37:37 +0200 Subject: [PATCH 040/388] =?UTF-8?q?audon/C/messages.po=20gel=C3=B6scht?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- audon/C/messages.po | 52 --------------------------------------------- 1 file changed, 52 deletions(-) delete mode 100644 audon/C/messages.po diff --git a/audon/C/messages.po b/audon/C/messages.po deleted file mode 100644 index c8fd38af0..000000000 --- a/audon/C/messages.po +++ /dev/null @@ -1,52 +0,0 @@ -# ADDON audon -# Copyright (C) -# This file is distributed under the same license as the Friendica audon addon package. -# -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: \n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-08-18 18:23+0200\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME \n" -"Language-Team: LANGUAGE \n" -"Language: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" - -#: audon.php:22 -msgid "Audon Audiochat" -msgstr "" - -#: audon.php:29 -msgid "Save Settings" -msgstr "" - -#: audon.php:32 -msgid "Audon Base URL" -msgstr "" - -#: audon.php:34 -msgid "" -"Page your users will create an Audon audio chat room on. For example you " -"could use https://audon.space." -msgstr "" - -#: audon.php:60 -msgid "Audio Chat" -msgstr "" - -#: audon.php:61 -msgid "" -"Audon is an audio conferencing tool. Connect your account to Audon and " -"create a room. Share the generated link to talk to other participants." -msgstr "" - -#: audon.php:63 -msgid "" -"Please contact your Friendica administrator to remind them to configure the " -"Audon addon." -msgstr "" From dfbf8d4acf5ef674ed87147b63188afb1e72b83e Mon Sep 17 00:00:00 2001 From: loma-one Date: Fri, 18 Aug 2023 18:38:06 +0200 Subject: [PATCH 041/388] =?UTF-8?q?audon/lang/C/messages.po=20hinzugef?= =?UTF-8?q?=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- audon/lang/C/messages.po | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 audon/lang/C/messages.po diff --git a/audon/lang/C/messages.po b/audon/lang/C/messages.po new file mode 100644 index 000000000..e69de29bb From 94a4c93368bf90dd074f010d05918f3a170e5672 Mon Sep 17 00:00:00 2001 From: loma-one Date: Fri, 18 Aug 2023 18:38:30 +0200 Subject: [PATCH 042/388] audon/lang/C/messages.po aktualisiert --- audon/lang/C/messages.po | 52 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/audon/lang/C/messages.po b/audon/lang/C/messages.po index e69de29bb..c8fd38af0 100644 --- a/audon/lang/C/messages.po +++ b/audon/lang/C/messages.po @@ -0,0 +1,52 @@ +# ADDON audon +# Copyright (C) +# This file is distributed under the same license as the Friendica audon addon package. +# +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-08-18 18:23+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: audon.php:22 +msgid "Audon Audiochat" +msgstr "" + +#: audon.php:29 +msgid "Save Settings" +msgstr "" + +#: audon.php:32 +msgid "Audon Base URL" +msgstr "" + +#: audon.php:34 +msgid "" +"Page your users will create an Audon audio chat room on. For example you " +"could use https://audon.space." +msgstr "" + +#: audon.php:60 +msgid "Audio Chat" +msgstr "" + +#: audon.php:61 +msgid "" +"Audon is an audio conferencing tool. Connect your account to Audon and " +"create a room. Share the generated link to talk to other participants." +msgstr "" + +#: audon.php:63 +msgid "" +"Please contact your Friendica administrator to remind them to configure the " +"Audon addon." +msgstr "" From c89abdb74ce1dc1782393e02a65478edd5716f87 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Tue, 22 Aug 2023 09:01:12 -0400 Subject: [PATCH 043/388] [bluesky] Fix double dollar sign in bluesky_fetch_notifications --- bluesky/bluesky.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index 5ca9c9517..c96658721 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -798,12 +798,12 @@ function bluesky_upload_blob(int $uid, array $photo): ?stdClass $picture = new Image($content, $photo['type']); $height = $picture->getHeight(); - $width = $picture->getWidth(); + $width = $picture->getWidth(); $size = strlen($content); $picture = Photo::resizeToFileSize($picture, BLUESKY_IMAGE_SIZE[$retrial]); $new_height = $picture->getHeight(); - $new_width = $picture->getWidth(); + $new_width = $picture->getWidth(); $content = $picture->asString(); $new_size = strlen($content); @@ -917,7 +917,7 @@ function bluesky_fetch_notifications(int $uid) $data = Item::insert($item); Logger::debug('Got like', ['uid' => $uid, 'result' => $data, 'uri' => $uri]); } else { - Logger::info('Thread parent not found', ['uid' => $uid, 'parent' => $$item['thr-parent'], 'uri' => $uri]); + Logger::info('Thread parent not found', ['uid' => $uid, 'parent' => $item['thr-parent'], 'uri' => $uri]); } break; @@ -1274,7 +1274,7 @@ function bluesky_fetch_missing_post(string $uri, int $uid, int $causer, int $lev if (++$level > 100) { Logger::info('Recursion level too deep', ['level' => $level, 'uid' => $uid, 'uri' => $uri, 'fallback' => $fallback]); // When the level is too deep we will fallback to the parent uri. - // Allthough the threading won't be correct, we at least had stored all posts and won't try again + // Allthough the threading won't be correct, we at least had stored all posts and won't try again return $fallback; } @@ -1287,8 +1287,8 @@ function bluesky_fetch_missing_post(string $uri, int $uid, int $causer, int $lev Logger::info('Thread was not fetched', ['level' => $level, 'uid' => $uid, 'uri' => $uri, 'fallback' => $fallback]); return $fallback; } - - Logger::debug('Reply count', ['replies' => $data->thread->post->replyCount, 'level' => $level, 'uid' => $uid, 'uri' => $uri]); + + Logger::debug('Reply count', ['replies' => $data->thread->post->replyCount, 'level' => $level, 'uid' => $uid, 'uri' => $uri]); if ($causer != 0) { $cdata = Contact::getPublicAndUserContactID($causer, $uid); @@ -1587,4 +1587,4 @@ function bluesky_get(int $uid, string $url, string $accept_content = HttpClientA } return json_decode($curlResult->getBody()); -} \ No newline at end of file +} From af31a988aaf0b0c970d8f67323dbb66faa657b3b Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 28 Aug 2023 04:50:15 +0000 Subject: [PATCH 044/388] Tumblr/Bluesky: Store the subscribed feed/tag --- bluesky/bluesky.php | 25 ++++++++++++++++++++----- tumblr/tumblr.php | 3 +++ 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index c96658721..aa7f317b2 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -931,7 +931,7 @@ function bluesky_fetch_notifications(int $uid) $data = Item::insert($item); Logger::debug('Got repost', ['uid' => $uid, 'result' => $data, 'uri' => $uri]); } else { - Logger::info('Thread parent not found', ['uid' => $uid, 'parent' => $$item['thr-parent'], 'uri' => $uri]); + Logger::info('Thread parent not found', ['uid' => $uid, 'parent' => $item['thr-parent'], 'uri' => $uri]); } break; @@ -973,12 +973,26 @@ function bluesky_fetch_feed(int $uid, string $feed) return; } + $feeddata = bluesky_xrpc_get($uid, 'app.bsky.feed.getFeedGenerator', ['feed' => $feed]); + if (!empty($feeddata)) { + $feedurl = $feeddata->view->uri; + $feedname = $feeddata->view->displayName; + } else { + $feedurl = $feed; + $feedname = $feed; + } + foreach (array_reverse($data->feed) as $entry) { if (!Relay::isWantedLanguage($entry->post->record->text)) { Logger::debug('Unwanted language detected', ['text' => $entry->post->record->text]); continue; } - bluesky_process_post($entry->post, $uid, Item::PR_TAG, 0); + $id = bluesky_process_post($entry->post, $uid, Item::PR_TAG, 0); + if (!empty($id)) { + $post = Post::selectFirst(['uri-id'], ['id' => $id]); + $stored = Post\Category::storeFileByURIId($post['uri-id'], $uid, Post\Category::SUBCRIPTION, $feedname, $feedurl); + Logger::debug('Stored tag subscription for user', ['uri-id' => $post['uri-id'], 'uid' => $uid, 'name' => $feedname, 'url' => $feedurl, 'stored' => $stored]); + } if (!empty($entry->reason)) { bluesky_process_reason($entry->reason, bluesky_get_uri($entry->post), $uid); } @@ -989,8 +1003,8 @@ function bluesky_process_post(stdClass $post, int $uid, int $post_reason, $level { $uri = bluesky_get_uri($post); - if (Post::exists(['uri' => $uri, 'uid' => $uid]) || Post::exists(['extid' => $uri, 'uid' => $uid])) { - return 0; + if ($id = Post::selectFirst(['id'], ['uri' => $uri, 'uid' => $uid]) || $id = Post::selectFirst(['id'], ['extid' => $uri, 'uid' => $uid])) { + return $id; } Logger::debug('Importing post', ['uid' => $uid, 'indexedAt' => $post->indexedAt, 'uri' => $post->uri, 'cid' => $post->cid, 'root' => $post->record->reply->root ?? '']); @@ -1032,6 +1046,7 @@ function bluesky_get_header(stdClass $post, string $uri, int $uid, int $fetch_ui 'author-link' => $contact['url'], 'author-avatar' => $contact['avatar'], 'plink' => $contact['alias'] . '/post/' . $parts->rkey, + 'source' => json_encode($post), ]; $item['uri-id'] = ItemURI::getIdByURI($uri); @@ -1201,7 +1216,7 @@ function bluesky_add_media(stdClass $embed, array $item, int $fetch_uid, int $le } if (!empty($embed->media)) { - bluesky_add_media($embed->media, $item, $fetch_uid, $level); + $item = bluesky_add_media($embed->media, $item, $fetch_uid, $level); } break; diff --git a/tumblr/tumblr.php b/tumblr/tumblr.php index 78c7d3849..a7a0db4c0 100644 --- a/tumblr/tumblr.php +++ b/tumblr/tumblr.php @@ -734,6 +734,9 @@ function tumblr_fetch_tags(int $uid) $id = tumblr_process_post($post, $uid, Item::PR_TAG); if (!empty($id)) { Logger::debug('Tag post imported', ['tag' => $tag, 'id' => $id]); + $post = Post::selectFirst(['uri-id'], ['id' => $id]); + $stored = Post\Category::storeFileByURIId($post['uri-id'], $uid, Post\Category::SUBCRIPTION, $tag); + Logger::debug('Stored tag subscription for user', ['uri-id' => $post['uri-id'], 'uid' => $uid, 'tag' => $tag, 'stored' => $stored]); } } } From 16d99dbdfcdfad929cad786a84124ee569d62c98 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 1 Oct 2023 04:37:11 +0000 Subject: [PATCH 045/388] Bluesky: Fix some issues when fetching posts --- bluesky/bluesky.php | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index aa7f317b2..6e6ad6092 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -990,8 +990,12 @@ function bluesky_fetch_feed(int $uid, string $feed) $id = bluesky_process_post($entry->post, $uid, Item::PR_TAG, 0); if (!empty($id)) { $post = Post::selectFirst(['uri-id'], ['id' => $id]); - $stored = Post\Category::storeFileByURIId($post['uri-id'], $uid, Post\Category::SUBCRIPTION, $feedname, $feedurl); - Logger::debug('Stored tag subscription for user', ['uri-id' => $post['uri-id'], 'uid' => $uid, 'name' => $feedname, 'url' => $feedurl, 'stored' => $stored]); + if (!empty($post['uri-id'])) { + $stored = Post\Category::storeFileByURIId($post['uri-id'], $uid, Post\Category::SUBCRIPTION, $feedname, $feedurl); + Logger::debug('Stored tag subscription for user', ['uri-id' => $post['uri-id'], 'uid' => $uid, 'name' => $feedname, 'url' => $feedurl, 'stored' => $stored]); + } else { + Logger::notice('Post not found', ['id' => $id, 'entry' => $entry]); + } } if (!empty($entry->reason)) { bluesky_process_reason($entry->reason, bluesky_get_uri($entry->post), $uid); @@ -1003,8 +1007,12 @@ function bluesky_process_post(stdClass $post, int $uid, int $post_reason, $level { $uri = bluesky_get_uri($post); - if ($id = Post::selectFirst(['id'], ['uri' => $uri, 'uid' => $uid]) || $id = Post::selectFirst(['id'], ['extid' => $uri, 'uid' => $uid])) { - return $id; + if ($id = Post::selectFirst(['id'], ['uri' => $uri, 'uid' => $uid])) { + return $id['id']; + } + + if ($id = Post::selectFirst(['id'], ['extid' => $uri, 'uid' => $uid])) { + return $id['id']; } Logger::debug('Importing post', ['uid' => $uid, 'indexedAt' => $post->indexedAt, 'uri' => $post->uri, 'cid' => $post->cid, 'root' => $post->record->reply->root ?? '']); @@ -1092,7 +1100,7 @@ function bluesky_get_content(array $item, stdClass $record, string $uri, int $ui function bluesky_get_text(stdClass $record): string { - $text = $record->text; + $text = $record->text ?? ''; if (empty($record->facets)) { return $text; @@ -1185,11 +1193,10 @@ function bluesky_add_media(stdClass $embed, array $item, int $fetch_uid, int $le $shared = bluesky_add_media($single, $shared, $fetch_uid, $level); } } - $id = Item::insert($shared); - $shared = Post::selectFirst(['uri-id'], ['id' => $id]); + Item::insert($shared); } } - if (!empty($shared)) { + if (!empty($shared['uri-id'])) { $item['quote-uri-id'] = $shared['uri-id']; } break; @@ -1206,12 +1213,10 @@ function bluesky_add_media(stdClass $embed, array $item, int $fetch_uid, int $le $shared = bluesky_add_media($single, $shared, $fetch_uid, $level); } } - - $id = Item::insert($shared); - $shared = Post::selectFirst(['uri-id'], ['id' => $id]); + Item::insert($shared); } } - if (!empty($shared)) { + if (!empty($shared['uri-id'])) { $item['quote-uri-id'] = $shared['uri-id']; } @@ -1331,7 +1336,12 @@ function bluesky_fetch_post(string $uri, int $uid): string function bluesky_process_thread(stdClass $thread, int $uid, array $cdata, int $level): string { + if (empty($thread->post)) { + Logger::info('Invalid post', ['post' => $thread, 'callstack' => System::callstack(10, 0, true)]); + return ''; + } $uri = bluesky_get_uri($thread->post); + $fetched_uri = bluesky_fetch_post($uri, $uid); if (empty($fetched_uri)) { Logger::debug('Process missing post', ['uri' => $uri]); From 30b9f73f5e2392d553909bc914990cbb4871bd48 Mon Sep 17 00:00:00 2001 From: Philipp Date: Thu, 5 Oct 2023 21:57:17 +0200 Subject: [PATCH 046/388] [CI/CD] Kick CI again --- .woodpecker/.phpunit.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.woodpecker/.phpunit.yml b/.woodpecker/.phpunit.yml index 893d433af..5450f0e7d 100644 --- a/.woodpecker/.phpunit.yml +++ b/.woodpecker/.phpunit.yml @@ -113,3 +113,4 @@ services: redis: image: redis + From 7a8f8fcbd2c4a916511a6d421a81b83b5ba84a6a Mon Sep 17 00:00:00 2001 From: Philipp Date: Thu, 5 Oct 2023 21:58:35 +0200 Subject: [PATCH 047/388] [CI/CD] Kick CI again --- .woodpecker/.phpunit.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.woodpecker/.phpunit.yml b/.woodpecker/.phpunit.yml index 5450f0e7d..893d433af 100644 --- a/.woodpecker/.phpunit.yml +++ b/.woodpecker/.phpunit.yml @@ -113,4 +113,3 @@ services: redis: image: redis - From 981e6821d0a21c4889b11530fdc1ac59b5d0cbdb Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 30 Sep 2023 15:56:50 +0000 Subject: [PATCH 048/388] CLD: New plugin for language detection via CLD2 --- cld/README.md | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++ cld/cld.php | 75 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 166 insertions(+) create mode 100644 cld/README.md create mode 100644 cld/cld.php diff --git a/cld/README.md b/cld/README.md new file mode 100644 index 000000000..6709facb2 --- /dev/null +++ b/cld/README.md @@ -0,0 +1,91 @@ +Compact Language Detector +=== +CLD2 is an advanced language dectection library with a high reliability. + +This addon depends on the CLD PHP module which is not included in any Linux distribution. +It needs to be built and installed by hand, which is not totally straightforward. + +Prerequisite +--- +To be able to build the extension, you need the CLD module and the files for the PHP module development. +On Debian you install the packages php-dev, libcld2-dev and libcld2-0. +Make sure to have installed the correct PHP version. +Means: When you have got both PHP 8.0 and 8.2 on your system, you have to install php8.0-dev as well. + +Installation +--- +The original PHP extension is https://github.com/fntlnz/cld2-php-ext. +However, it doesn't support PHP8. +So https://github.com/hiteule/cld2-php-ext/tree/support-php8 has to be used. + +Download the source code: +``` +wget https://github.com/hiteule/cld2-php-ext/archive/refs/heads/support-php8.zip +``` + +Unzip it: +``` +unzip support-php8.zip +``` + +Change into the folder: +``` +cd cld2-php-ext-support-php8/ +``` + +Configure for the PHP Api version: +``` +phpize +``` +(if you have got several PHP versions on your system, execute the command with the version that you run Friendica with, e.g. `phpize8.0`) + +Create the Makefile: +``` +./configure --with-cld2=/usr/include/cld2 +``` + +Have a look at the line `checking for PHP includes`. +When the output (for example `/usr/include/php/20220829` doesn't match the API version that you got from `phpize`, then you have to change all the version codes in your `Makefile` afterwards) + +Create the module: +``` +make -j +``` + +Install it: +``` +sudo make install +``` + +Change to the folder with the available modules. When you use PHP 8.0 on Debian it is: +``` +cd /etc/php/8.0/mods-available +``` + +Create the file `cld.ini` with this content: +``` +; configuration for php cld2 module +; priority=20 +extension=cld2.so +``` + +Change to the folder `conf.d` in the folder of your `php.ini`. +``` +cd /etc/php/8.0/cgi/conf.d +``` +This depends on the way you installed the PHP support for your webserver. Instead of `cgi` it could also be `apache2` or `fpm`. + +Create a symbolic link to install the module: +``` +ln -s /etc/php/8.0/mods-available/cld.ini +``` + +Then restart the apache or fpm (or whatever you use) to load the changed configuration. + +Call `/admin/phpinfo` on your webserver. +You then see the PHP Info. +Search for "cld2". +The module is installed, when you find it here. +**Only proceed when the module is installed** + +Now you can enable the addon. \ No newline at end of file diff --git a/cld/cld.php b/cld/cld.php new file mode 100644 index 000000000..4c54b2d0c --- /dev/null +++ b/cld/cld.php @@ -0,0 +1,75 @@ + + */ + +use Friendica\Core\Hook; +use Friendica\Core\Logger; +use Friendica\DI; + +function cld_install() +{ + Hook::register('get_language', 'addon/cld/cld.php', 'cld_get_language'); +} + +function cld_get_language(array &$data) +{ + if (!in_array('cld2', get_loaded_extensions())) { + Logger::warning('CLD2 is not installed.'); + return; + } + + $cld2 = new \CLD2Detector(); + + $cld2->setEncodingHint(CLD2Encoding::UTF8); // optional, hints about text encoding + + $result = $cld2->detect($data['text']); + + if ($data['detected']) { + $original = array_key_first($data['detected']); + } else { + $original = ''; + } + + $detected = $result['language_code']; + if ($detected == 'pt') { + $detected = 'pt-PT'; + } elseif ($detected == 'el') { + $detected = 'el-monoton'; + } elseif ($detected == 'no') { + $detected = 'nb'; + } elseif ($detected == 'zh') { + $detected = 'zh-Hans'; + } elseif ($detected == 'zh-Hant') { + $detected = 'zh-hant'; + } + + if (!$result['is_reliable']) { + Logger::debug('Unreliable detection', ['original' => $original, 'detected' => $detected, 'name' => $result['language_name'], 'probability' => $result['language_probability'], 'text' => $data['text']]); + return; + } + + if ($original == $detected) { +// return; + } + + // Nur aus Testgründen + if (in_array($detected, ['xx-Qaai', 'ht', 'ga'])) { + return; + } + + $available = array_keys(DI::l10n()->convertForLanguageDetection(DI::l10n()->getAvailableLanguages(true))); + + if (!in_array($detected, $available)) { + Logger::debug('Unsupported language', ['original' => $original, 'detected' => $detected, 'name' => $result['language_name'], 'probability' => $result['language_probability'], 'text' => $data['text']]); + return; + } + + Logger::debug('Detected', ['original' => $original, 'detected' => $detected, 'name' => $result['language_name'], 'probability' => $result['language_probability'], 'text' => $data['text']]); + +// Logger::debug('Detected different language', ['original' => $original, 'detected' => $detected, 'name' => $result['language_name'], 'probability' => $result['language_probability'], 'text' => $data['text']]); + $data['detected'] = [$detected => $result['language_probability'] / 100]; +} From 0eda161e04af171e43897ca0d780c1c20ff1ce21 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 30 Sep 2023 16:00:26 +0000 Subject: [PATCH 049/388] Cleaned up code --- cld/cld.php | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/cld/cld.php b/cld/cld.php index 4c54b2d0c..56bca64f7 100644 --- a/cld/cld.php +++ b/cld/cld.php @@ -53,11 +53,6 @@ function cld_get_language(array &$data) } if ($original == $detected) { -// return; - } - - // Nur aus Testgründen - if (in_array($detected, ['xx-Qaai', 'ht', 'ga'])) { return; } @@ -68,8 +63,6 @@ function cld_get_language(array &$data) return; } - Logger::debug('Detected', ['original' => $original, 'detected' => $detected, 'name' => $result['language_name'], 'probability' => $result['language_probability'], 'text' => $data['text']]); - -// Logger::debug('Detected different language', ['original' => $original, 'detected' => $detected, 'name' => $result['language_name'], 'probability' => $result['language_probability'], 'text' => $data['text']]); + Logger::debug('Detected different language', ['original' => $original, 'detected' => $detected, 'name' => $result['language_name'], 'probability' => $result['language_probability'], 'text' => $data['text']]); $data['detected'] = [$detected => $result['language_probability'] / 100]; } From 80ce8551892ab7cbe7a16f40c1a019a05815353f Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 1 Oct 2023 04:14:10 +0000 Subject: [PATCH 050/388] Renamed hook --- cld/cld.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cld/cld.php b/cld/cld.php index 56bca64f7..54e7a73e4 100644 --- a/cld/cld.php +++ b/cld/cld.php @@ -12,10 +12,10 @@ use Friendica\DI; function cld_install() { - Hook::register('get_language', 'addon/cld/cld.php', 'cld_get_language'); + Hook::register('detect_languages', 'addon/cld/cld.php', 'cld_detect_languages'); } -function cld_get_language(array &$data) +function cld_detect_languages(array &$data) { if (!in_array('cld2', get_loaded_extensions())) { Logger::warning('CLD2 is not installed.'); From 18266ea6ef1ba98ffd7023fb8537b90dc413fa4a Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 6 Oct 2023 03:54:45 +0000 Subject: [PATCH 051/388] Changed hook parameter / more languages added --- cld/cld.php | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/cld/cld.php b/cld/cld.php index 54e7a73e4..fc8fa8145 100644 --- a/cld/cld.php +++ b/cld/cld.php @@ -12,7 +12,7 @@ use Friendica\DI; function cld_install() { - Hook::register('detect_languages', 'addon/cld/cld.php', 'cld_detect_languages'); + Hook::register('detect_languages', __FILE__, 'cld_detect_languages'); } function cld_detect_languages(array &$data) @@ -25,6 +25,7 @@ function cld_detect_languages(array &$data) $cld2 = new \CLD2Detector(); $cld2->setEncodingHint(CLD2Encoding::UTF8); // optional, hints about text encoding + $cld2->setPlainText(true); $result = $cld2->detect($data['text']); @@ -37,18 +38,37 @@ function cld_detect_languages(array &$data) $detected = $result['language_code']; if ($detected == 'pt') { $detected = 'pt-PT'; + } elseif ($detected == 'az') { + $detected = 'az-Latn'; + } elseif ($detected == 'bs') { + $detected = 'bs-Latn'; } elseif ($detected == 'el') { $detected = 'el-monoton'; + } elseif ($detected == 'ht') { + $detected = 'fr'; + } elseif ($detected == 'iw') { + $detected = 'he'; + } elseif ($detected == 'jw') { + $detected = 'jv'; + } elseif ($detected == 'ms') { + $detected = 'ms-Latn'; } elseif ($detected == 'no') { $detected = 'nb'; + } elseif ($detected == 'sr') { + $detected = 'sr-Cyrl'; } elseif ($detected == 'zh') { $detected = 'zh-Hans'; } elseif ($detected == 'zh-Hant') { $detected = 'zh-hant'; } + // languages that aren't supported via the base language detection + if (in_array($detected, ['ceb', 'hmn', 'ht', 'kk', 'ky', 'mg', 'mk', 'ml', 'ny', 'or', 'pa', 'rw', 'su', 'st', 'tg', 'ts', 'xx-Qaai'])) { + return; + } + if (!$result['is_reliable']) { - Logger::debug('Unreliable detection', ['original' => $original, 'detected' => $detected, 'name' => $result['language_name'], 'probability' => $result['language_probability'], 'text' => $data['text']]); + Logger::debug('Unreliable detection', ['uri-id' => $data['uri-id'], 'original' => $original, 'detected' => $detected, 'name' => $result['language_name'], 'probability' => $result['language_probability'], 'text' => $data['text']]); return; } @@ -59,10 +79,10 @@ function cld_detect_languages(array &$data) $available = array_keys(DI::l10n()->convertForLanguageDetection(DI::l10n()->getAvailableLanguages(true))); if (!in_array($detected, $available)) { - Logger::debug('Unsupported language', ['original' => $original, 'detected' => $detected, 'name' => $result['language_name'], 'probability' => $result['language_probability'], 'text' => $data['text']]); + Logger::debug('Unsupported language', ['uri-id' => $data['uri-id'], 'original' => $original, 'detected' => $detected, 'name' => $result['language_name'], 'probability' => $result['language_probability'], 'text' => $data['text']]); return; } - Logger::debug('Detected different language', ['original' => $original, 'detected' => $detected, 'name' => $result['language_name'], 'probability' => $result['language_probability'], 'text' => $data['text']]); + Logger::debug('Detected different language', ['uri-id' => $data['uri-id'], 'original' => $original, 'detected' => $detected, 'name' => $result['language_name'], 'probability' => $result['language_probability'], 'text' => $data['text']]); $data['detected'] = [$detected => $result['language_probability'] / 100]; } From 92251f4a6c8fa409b0a6ddef53dd6304390a9168 Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 6 Oct 2023 04:09:46 +0000 Subject: [PATCH 052/388] Updated CLD installation description --- cld/README.md | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/cld/README.md b/cld/README.md index 6709facb2..933dbceee 100644 --- a/cld/README.md +++ b/cld/README.md @@ -57,27 +57,21 @@ Install it: sudo make install ``` -Change to the folder with the available modules. When you use PHP 8.0 on Debian it is: +Change to the folder with the available modules. When you use PHP 8.2 on Debian it is: ``` -cd /etc/php/8.0/mods-available +cd /etc/php/8.2/mods-available ``` -Create the file `cld.ini` with this content: +Create the file `cld2.ini` with this content: ``` ; configuration for php cld2 module ; priority=20 extension=cld2.so ``` -Change to the folder `conf.d` in the folder of your `php.ini`. +Enable the module for all versions and all sapi: ``` -cd /etc/php/8.0/cgi/conf.d -``` -This depends on the way you installed the PHP support for your webserver. Instead of `cgi` it could also be `apache2` or `fpm`. - -Create a symbolic link to install the module: -``` -ln -s /etc/php/8.0/mods-available/cld.ini +phpenmod -v ALL -s ALL cld2 ``` Then restart the apache or fpm (or whatever you use) to load the changed configuration. From 73c6a0ff0cc516335c601b5ce1bec74f65c68848 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 11 Oct 2023 18:49:42 +0000 Subject: [PATCH 053/388] CLD: Keep the original detected language array --- cld/cld.php | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/cld/cld.php b/cld/cld.php index fc8fa8145..ab81447dd 100644 --- a/cld/cld.php +++ b/cld/cld.php @@ -28,7 +28,7 @@ function cld_detect_languages(array &$data) $cld2->setPlainText(true); $result = $cld2->detect($data['text']); - + if ($data['detected']) { $original = array_key_first($data['detected']); } else { @@ -69,10 +69,9 @@ function cld_detect_languages(array &$data) if (!$result['is_reliable']) { Logger::debug('Unreliable detection', ['uri-id' => $data['uri-id'], 'original' => $original, 'detected' => $detected, 'name' => $result['language_name'], 'probability' => $result['language_probability'], 'text' => $data['text']]); - return; - } - - if ($original == $detected) { + if (($original == $detected) && ($data['detected'][$original] < $result['language_probability'] / 100)) { + $data['detected'][$original] = $result['language_probability'] / 100; + } return; } @@ -83,6 +82,15 @@ function cld_detect_languages(array &$data) return; } - Logger::debug('Detected different language', ['uri-id' => $data['uri-id'], 'original' => $original, 'detected' => $detected, 'name' => $result['language_name'], 'probability' => $result['language_probability'], 'text' => $data['text']]); - $data['detected'] = [$detected => $result['language_probability'] / 100]; + if ($original != $detected) { + Logger::debug('Detected different language', ['uri-id' => $data['uri-id'], 'original' => $original, 'detected' => $detected, 'name' => $result['language_name'], 'probability' => $result['language_probability'], 'text' => $data['text']]); + } + + $length = count($data['detected']); + if ($length > 0) { + unset($data['detected'][$detected]); + $data['detected'] = array_merge([$detected => $result['language_probability'] / 100], array_slice($data['detected'], 0, $length - 1)); + } else { + $data['detected'] = [$detected => $result['language_probability'] / 100]; + } } From 9bdaa8092efa79575b4cec818f4b453cabe9be28 Mon Sep 17 00:00:00 2001 From: Philipp Date: Thu, 12 Oct 2023 21:33:03 +0200 Subject: [PATCH 054/388] Upgrade phpunit version in PHP-CI --- .woodpecker/.phpunit.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.woodpecker/.phpunit.yml b/.woodpecker/.phpunit.yml index 893d433af..f198ba2af 100644 --- a/.woodpecker/.phpunit.yml +++ b/.woodpecker/.phpunit.yml @@ -5,11 +5,11 @@ matrix: - PHP_MAJOR_VERSION: 7.4 PHP_VERSION: 7.4.33 - PHP_MAJOR_VERSION: 8.0 - PHP_VERSION: 8.0.29 + PHP_VERSION: 8.0.30 - PHP_MAJOR_VERSION: 8.1 - PHP_VERSION: 8.1.21 + PHP_VERSION: 8.1.23 - PHP_MAJOR_VERSION: 8.2 - PHP_VERSION: 8.2.8 + PHP_VERSION: 8.2.11 # This forces PHP Unit executions at the "opensocial" labeled location (because of much more power...) labels: From 6948a15f1c5563928e5e2a108621038ce4bdb76a Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 18 Oct 2023 20:16:59 +0000 Subject: [PATCH 055/388] Langfilter: Use two letter code for the language / Bluesky: Remove callstack --- bluesky/bluesky.php | 5 ++--- langfilter/langfilter.php | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index 6e6ad6092..2d497e8c2 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -32,7 +32,6 @@ use Friendica\Core\Hook; use Friendica\Core\Logger; use Friendica\Core\Protocol; use Friendica\Core\Renderer; -use Friendica\Core\System; use Friendica\Core\Worker; use Friendica\Database\DBA; use Friendica\DI; @@ -1235,7 +1234,7 @@ function bluesky_add_media(stdClass $embed, array $item, int $fetch_uid, int $le function bluesky_get_uri(stdClass $post): string { if (empty($post->cid)) { - Logger::info('Invalid URI', ['post' => $post, 'callstack' => System::callstack(10, 0, true)]); + Logger::info('Invalid URI', ['post' => $post]); return ''; } return $post->uri . ':' . $post->cid; @@ -1337,7 +1336,7 @@ function bluesky_fetch_post(string $uri, int $uid): string function bluesky_process_thread(stdClass $thread, int $uid, array $cdata, int $level): string { if (empty($thread->post)) { - Logger::info('Invalid post', ['post' => $thread, 'callstack' => System::callstack(10, 0, true)]); + Logger::info('Invalid post', ['post' => $thread]); return ''; } $uri = bluesky_get_uri($thread->post); diff --git a/langfilter/langfilter.php b/langfilter/langfilter.php index 9cb57a6ce..e5efa8fbc 100644 --- a/langfilter/langfilter.php +++ b/langfilter/langfilter.php @@ -163,7 +163,7 @@ function langfilter_prepare_body_content_filter(&$hook_data) return; } - $lang = $iso639->languageByCode1($iso2); + $lang = $iso639->languageByCode1(substr($iso2, 0, 2)); } else { $opts = $hook_data['item']['postopts']; if (!$opts) { From 43c46ae6d975f386421fe60b802411dec93e228a Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Fri, 20 Oct 2023 17:50:31 +0200 Subject: [PATCH 056/388] [smileybutton] Add explicit conversion from float to int Address part of https://github.com/friendica/friendica/issues/13157#issuecomment-1771572442 --- smileybutton/smileybutton.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/smileybutton/smileybutton.php b/smileybutton/smileybutton.php index fc20888f1..1df717b72 100644 --- a/smileybutton/smileybutton.php +++ b/smileybutton/smileybutton.php @@ -90,7 +90,7 @@ function smileybutton_jot_tool(string &$body) for ($x = 0; $x < count($params['texts']); $x++) { $icon = $params['icons'][$x]; $s .= '' . $icon . ''; - if (($x + 1) % (sqrt(count($params['texts'])) + 1) == 0) { + if (($x + 1) % (floor(sqrt(count($params['texts']))) + 1) == 0) { $s .= ''; } } From 77765ff6ed21d30c6ef3945eeea53c2144ee6465 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 29 Oct 2023 11:39:45 +0000 Subject: [PATCH 057/388] Bluesky: Fix warnings --- bluesky/bluesky.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index 2d497e8c2..d5ab6e425 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -1307,7 +1307,7 @@ function bluesky_fetch_missing_post(string $uri, int $uid, int $causer, int $lev return $fallback; } - Logger::debug('Reply count', ['replies' => $data->thread->post->replyCount, 'level' => $level, 'uid' => $uid, 'uri' => $uri]); + Logger::debug('Reply count', ['level' => $level, 'uid' => $uid, 'uri' => $uri]); if ($causer != 0) { $cdata = Contact::getPublicAndUserContactID($causer, $uid); From 2a782b512e7b038c450318abaa464bcaab7eb823 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 2 Nov 2023 22:54:19 +0000 Subject: [PATCH 058/388] CLD2: Use ISO-639-1 for the language detection --- cld/cld.php | 35 +++++------------------------------ 1 file changed, 5 insertions(+), 30 deletions(-) diff --git a/cld/cld.php b/cld/cld.php index ab81447dd..5ca4c932b 100644 --- a/cld/cld.php +++ b/cld/cld.php @@ -35,35 +35,10 @@ function cld_detect_languages(array &$data) $original = ''; } - $detected = $result['language_code']; - if ($detected == 'pt') { - $detected = 'pt-PT'; - } elseif ($detected == 'az') { - $detected = 'az-Latn'; - } elseif ($detected == 'bs') { - $detected = 'bs-Latn'; - } elseif ($detected == 'el') { - $detected = 'el-monoton'; - } elseif ($detected == 'ht') { - $detected = 'fr'; - } elseif ($detected == 'iw') { - $detected = 'he'; - } elseif ($detected == 'jw') { - $detected = 'jv'; - } elseif ($detected == 'ms') { - $detected = 'ms-Latn'; - } elseif ($detected == 'no') { - $detected = 'nb'; - } elseif ($detected == 'sr') { - $detected = 'sr-Cyrl'; - } elseif ($detected == 'zh') { - $detected = 'zh-Hans'; - } elseif ($detected == 'zh-Hant') { - $detected = 'zh-hant'; - } + $detected = DI::l10n()->toISO6391($result['language_code']); - // languages that aren't supported via the base language detection - if (in_array($detected, ['ceb', 'hmn', 'ht', 'kk', 'ky', 'mg', 'mk', 'ml', 'ny', 'or', 'pa', 'rw', 'su', 'st', 'tg', 'ts', 'xx-Qaai'])) { + // languages that aren't supported via the base language detection or tend to false detections + if ((strlen($detected) == 3) || in_array($detected, ['ht', 'kk', 'ku', 'ky', 'lg', 'mg', 'mk', 'mt', 'ny', 'rw', 'st', 'su', 'tg', 'ts', 'xx'])) { return; } @@ -75,8 +50,8 @@ function cld_detect_languages(array &$data) return; } - $available = array_keys(DI::l10n()->convertForLanguageDetection(DI::l10n()->getAvailableLanguages(true))); - + $available = array_keys(DI::l10n()->getLanguageCodes()); + if (!in_array($detected, $available)) { Logger::debug('Unsupported language', ['uri-id' => $data['uri-id'], 'original' => $original, 'detected' => $detected, 'name' => $result['language_name'], 'probability' => $result['language_probability'], 'text' => $data['text']]); return; From 66fdd31915482c7c03b82555b999e11d9d936406 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 11 Nov 2023 05:30:07 +0000 Subject: [PATCH 059/388] Bluesky: Support for transmitted languages --- bluesky/bluesky.php | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index d5ab6e425..82501594f 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -610,6 +610,13 @@ function bluesky_create_post(array $item, stdClass $root = null, stdClass $paren return; } + // Try to fetch the language from the post itself + if (!empty($item['language'])) { + $language = array_key_first(json_decode($item['language'], true)); + } else { + $language = ''; + } + $did = DI::pConfig()->get($uid, 'bluesky', 'did'); $urls = bluesky_get_urls(Post\Media::removeFromBody($item['body'])); $item['body'] = $urls['body']; @@ -621,10 +628,14 @@ function bluesky_create_post(array $item, stdClass $root = null, stdClass $paren $record = [ 'text' => $facets['body'], + '$type' => 'app.bsky.feed.post', 'createdAt' => DateTimeFormat::utcNow(DateTimeFormat::ATOM), - '$type' => 'app.bsky.feed.post' ]; + if (!empty($language)) { + $record['langs'] = [$language]; + } + if (!empty($facets['facets'])) { $record['facets'] = $facets['facets']; } @@ -982,7 +993,10 @@ function bluesky_fetch_feed(int $uid, string $feed) } foreach (array_reverse($data->feed) as $entry) { - if (!Relay::isWantedLanguage($entry->post->record->text)) { + $contact = bluesky_get_contact($entry->post->author, 0, $uid); + $languages = $entry->post->record->langs ?? []; + + if (!Relay::isWantedLanguage($entry->post->record->text, 0, $contact['id'] ?? 0, $languages)) { Logger::debug('Unwanted language detected', ['text' => $entry->post->record->text]); continue; } @@ -1094,6 +1108,7 @@ function bluesky_get_content(array $item, stdClass $record, string $uri, int $ui $item['body'] = bluesky_get_text($record); $item['created'] = DateTimeFormat::utc($record->createdAt, DateTimeFormat::MYSQL); + $item['transmitted-languages'] = $record->langs ?? []; return $item; } From 6a46d05bca98a9fce3d5a4c7c833106ff3f105f7 Mon Sep 17 00:00:00 2001 From: Benjamin Lorteau Date: Tue, 14 Nov 2023 16:25:06 -0500 Subject: [PATCH 060/388] [advancedcontentfilter] Fix obsolete reference to Repository\PostMedia->splitAttachments --- advancedcontentfilter/advancedcontentfilter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/advancedcontentfilter/advancedcontentfilter.php b/advancedcontentfilter/advancedcontentfilter.php index 2254e587b..f2927f574 100644 --- a/advancedcontentfilter/advancedcontentfilter.php +++ b/advancedcontentfilter/advancedcontentfilter.php @@ -455,7 +455,7 @@ function advancedcontentfilter_prepare_item_row(array $item_row): array $item_row['tags'] = $tags['tags']; $item_row['hashtags'] = $tags['hashtags']; $item_row['mentions'] = $tags['mentions']; - $item_row['attachments'] = Post\Media::splitAttachments($item_row['uri-id']); + $item_row['attachments'] = DI::postMediaRepository()->splitAttachments($item_row['uri-id']); return $item_row; } From 00e30b5c2bbfffec48b174877518f1df7d4c43d1 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 19 Nov 2023 18:55:05 +0000 Subject: [PATCH 061/388] Bluesky: Support personal data servers --- bluesky/bluesky.php | 85 ++++++++++++++++++------ bluesky/lang/C/messages.po | 38 ++++++----- bluesky/templates/connector_settings.tpl | 2 +- 3 files changed, 86 insertions(+), 39 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index 82501594f..3b2ce7e09 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -36,6 +36,7 @@ use Friendica\Core\Worker; use Friendica\Database\DBA; use Friendica\DI; use Friendica\Model\Contact; +use Friendica\Model\GServer; use Friendica\Model\Item; use Friendica\Model\ItemURI; use Friendica\Model\Photo; @@ -49,9 +50,15 @@ use Friendica\Util\DateTimeFormat; use Friendica\Util\Strings; const BLUESKY_DEFAULT_POLL_INTERVAL = 10; // given in minutes -const BLUESKY_HOST = 'https://bsky.app'; // Hard wired until Bluesky will run on multiple systems const BLUESKY_IMAGE_SIZE = [1000000, 500000, 100000, 50000]; +/* + * (Currently) hard wired paths for Bluesky services + */ +const BLUESKY_DIRECTORY = 'https://plc.directory'; // Path to the directory server service to fetch the PDS of a given DID +const BLUESKY_PDS = 'https://bsky.social'; // Path to the personal data server service (PDS) to fetch the DID for a given handle +const BLUESKY_WEB = 'https://bsky.app'; // Path to the web interface with the user profile and posts + function bluesky_install() { Hook::register('load_config', __FILE__, 'bluesky_load_config'); @@ -106,8 +113,8 @@ function bluesky_probe_detect(array &$hookData) if (parse_url($hookData['uri'], PHP_URL_SCHEME) == 'did') { $did = $hookData['uri']; - } elseif (preg_match('#^' . BLUESKY_HOST . '/profile/(.+)#', $hookData['uri'], $matches)) { - $did = bluesky_get_did($pconfig['uid'], $matches[1]); + } elseif (preg_match('#^' . BLUESKY_WEB . '/profile/(.+)#', $hookData['uri'], $matches)) { + $did = bluesky_get_did($matches[1]); if (empty($did)) { return; } @@ -127,6 +134,8 @@ function bluesky_probe_detect(array &$hookData) $hookData['result'] = bluesky_get_contact_fields($data, 0, false); + $hookData['result']['baseurl'] = bluesky_get_pds($did); + // Preparing probe data. This differs slightly from the contact array $hookData['result']['about'] = HTML::toBBCode($data->description ?? ''); $hookData['result']['photo'] = $data->avatar ?? ''; @@ -152,11 +161,11 @@ function bluesky_item_by_link(array &$hookData) return; } - if (!preg_match('#^' . BLUESKY_HOST . '/profile/(.+)/post/(.+)#', $hookData['uri'], $matches)) { + if (!preg_match('#^' . BLUESKY_WEB . '/profile/(.+)/post/(.+)#', $hookData['uri'], $matches)) { return; } - $did = bluesky_get_did($hookData['uid'], $matches[1]); + $did = bluesky_get_did($matches[1]); if (empty($did)) { return; } @@ -306,7 +315,7 @@ function bluesky_settings(array &$data) $enabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'post') ?? false; $def_enabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'post_by_default') ?? false; - $host = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'host') ?: 'https://bsky.social'; + $pds = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'pds'); $handle = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'handle'); $did = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'did'); $token = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'access_token'); @@ -321,7 +330,7 @@ function bluesky_settings(array &$data) '$bydefault' => ['bluesky_bydefault', DI::l10n()->t('Post to Bluesky by default'), $def_enabled], '$import' => ['bluesky_import', DI::l10n()->t('Import the remote timeline'), $import], '$import_feeds' => ['bluesky_import_feeds', DI::l10n()->t('Import the pinned feeds'), $import_feeds, DI::l10n()->t('When activated, Posts will be imported from all the feeds that you pinned in Bluesky.')], - '$host' => ['bluesky_host', DI::l10n()->t('Bluesky host'), $host, '', '', 'readonly'], + '$pds' => ['bluesky_pds', DI::l10n()->t('Personal Data Server'), $pds, DI::l10n()->t('The personal data server (PDS) is the system that hosts your profile.'), '', 'readonly'], '$handle' => ['bluesky_handle', DI::l10n()->t('Bluesky handle'), $handle], '$did' => ['bluesky_did', DI::l10n()->t('Bluesky DID'), $did, DI::l10n()->t('This is the unique identifier. It will be fetched automatically, when the handle is entered.'), '', 'readonly'], '$password' => ['bluesky_password', DI::l10n()->t('Bluesky app password'), '', DI::l10n()->t("Please don't add your real password here, but instead create a specific app password in the Bluesky settings.")], @@ -342,27 +351,29 @@ function bluesky_settings_post(array &$b) if (empty($_POST['bluesky-submit'])) { return; } - - $old_host = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'host'); + + $old_pds = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'pds'); $old_handle = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'handle'); $old_did = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'did'); - $host = $_POST['bluesky_host']; $handle = $_POST['bluesky_handle']; DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'post', intval($_POST['bluesky'])); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'post_by_default', intval($_POST['bluesky_bydefault'])); - DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'host', $host); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'handle', $handle); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'import', intval($_POST['bluesky_import'])); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'import_feeds', intval($_POST['bluesky_import_feeds'])); if (!empty($host) && !empty($handle)) { - if (empty($old_did) || $old_host != $host || $old_handle != $handle) { - DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'did', bluesky_get_did(DI::userSession()->getLocalUserId(), DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'handle'))); + if (empty($old_did) || $old_handle != $handle) { + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'did', bluesky_get_did(DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'handle'))); + } + if (empty($old_pds) || $old_handle != $handle) { + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'pds', bluesky_get_pds(DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'did'))); } } else { DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'bluesky', 'did'); + DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'bluesky', 'pds'); } if (!empty($_POST['bluesky_password'])) { @@ -1452,10 +1463,9 @@ function bluesky_get_contact_fields(stdClass $author, int $uid, bool $update): a 'blocked' => false, 'readonly' => false, 'pending' => false, - 'baseurl' => BLUESKY_HOST, 'url' => $author->did, 'nurl' => $author->did, - 'alias' => BLUESKY_HOST . '/profile/' . $author->handle, + 'alias' => BLUESKY_WEB . '/profile/' . $author->handle, 'name' => $author->displayName ?? $author->handle, 'nick' => $author->handle, 'addr' => $author->handle, @@ -1466,6 +1476,12 @@ function bluesky_get_contact_fields(stdClass $author, int $uid, bool $update): a return $fields; } + $fields['baseurl'] = bluesky_get_pds($author->did); + if (!empty($fields['baseurl'])) { + GServer::check($fields['baseurl'], Protocol::BLUESKY); + $fields['gsid'] = GServer::getID($fields['baseurl'], true); + } + $data = bluesky_xrpc_get($uid, 'app.bsky.actor.getProfile', ['actor' => $author->did]); if (empty($data)) { Logger::debug('Error fetching contact fields', ['uid' => $uid, 'url' => $fields['url']]); @@ -1524,9 +1540,9 @@ function bluesky_get_preferences(int $uid): stdClass return $data; } -function bluesky_get_did(int $uid, string $handle): string +function bluesky_get_did(string $handle): string { - $data = bluesky_get($uid, '/xrpc/com.atproto.identity.resolveHandle?handle=' . urlencode($handle)); + $data = bluesky_get(BLUESKY_PDS . '/xrpc/com.atproto.identity.resolveHandle?handle=' . urlencode($handle)); if (empty($data)) { return ''; } @@ -1534,6 +1550,33 @@ function bluesky_get_did(int $uid, string $handle): string return $data->did; } +function bluesky_get_user_pds(int $uid): string +{ + $pds = DI::pConfig()->get($uid, 'bluesky', 'pds'); + if (!empty($pds)) { + return $pds; + } + $pds = bluesky_get_pds(DI::pConfig()->get($uid, 'bluesky', 'did')); + DI::pConfig()->set($uid, 'bluesky', 'pds', $pds); + return $pds; +} + +function bluesky_get_pds(string $did): ?string +{ + $data = bluesky_get(BLUESKY_DIRECTORY . '/' . $did); + if (empty($data) || empty($data->service)) { + return null; + } + + foreach ($data->service as $service) { + if (($service->id == '#atproto_pds') && ($service->type == 'AtprotoPersonalDataServer') && !empty($service->serviceEndpoint)) { + return $service->serviceEndpoint; + } + } + + return null; +} + function bluesky_get_token(int $uid): string { $token = DI::pConfig()->get($uid, 'bluesky', 'access_token'); @@ -1588,7 +1631,7 @@ function bluesky_xrpc_post(int $uid, string $url, $parameters): ?stdClass function bluesky_post(int $uid, string $url, string $params, array $headers): ?stdClass { try { - $curlResult = DI::httpClient()->post(DI::pConfig()->get($uid, 'bluesky', 'host') . $url, $params, $headers); + $curlResult = DI::httpClient()->post(bluesky_get_user_pds($uid) . $url, $params, $headers); } catch (\Exception $e) { Logger::notice('Exception on post', ['exception' => $e]); return null; @@ -1608,13 +1651,13 @@ function bluesky_xrpc_get(int $uid, string $url, array $parameters = []): ?stdCl $url .= '?' . http_build_query($parameters); } - return bluesky_get($uid, '/xrpc/' . $url, HttpClientAccept::JSON, [HttpClientOptions::HEADERS => ['Authorization' => ['Bearer ' . bluesky_get_token($uid)]]]); + return bluesky_get(bluesky_get_user_pds($uid) . '/xrpc/' . $url, HttpClientAccept::JSON, [HttpClientOptions::HEADERS => ['Authorization' => ['Bearer ' . bluesky_get_token($uid)]]]); } -function bluesky_get(int $uid, string $url, string $accept_content = HttpClientAccept::DEFAULT, array $opts = []): ?stdClass +function bluesky_get(string $url, string $accept_content = HttpClientAccept::DEFAULT, array $opts = []): ?stdClass { try { - $curlResult = DI::httpClient()->get(DI::pConfig()->get($uid, 'bluesky', 'host') . $url, $accept_content, $opts); + $curlResult = DI::httpClient()->get($url, $accept_content, $opts); } catch (\Exception $e) { Logger::notice('Exception on get', ['exception' => $e]); return null; diff --git a/bluesky/lang/C/messages.po b/bluesky/lang/C/messages.po index 139081f78..a5349142e 100644 --- a/bluesky/lang/C/messages.po +++ b/bluesky/lang/C/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-06-05 04:34+0000\n" +"POT-Creation-Date: 2023-11-19 18:51+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,70 +17,74 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: bluesky.php:314 +#: bluesky.php:325 msgid "" "You are authenticated to Bluesky. For security reasons the password isn't " "stored." msgstr "" -#: bluesky.php:314 +#: bluesky.php:325 msgid "You are not authenticated. Please enter the app password." msgstr "" -#: bluesky.php:318 +#: bluesky.php:329 msgid "Enable Bluesky Post Addon" msgstr "" -#: bluesky.php:319 +#: bluesky.php:330 msgid "Post to Bluesky by default" msgstr "" -#: bluesky.php:320 +#: bluesky.php:331 msgid "Import the remote timeline" msgstr "" -#: bluesky.php:321 +#: bluesky.php:332 msgid "Import the pinned feeds" msgstr "" -#: bluesky.php:321 +#: bluesky.php:332 msgid "" "When activated, Posts will be imported from all the feeds that you pinned in " "Bluesky." msgstr "" -#: bluesky.php:322 -msgid "Bluesky host" +#: bluesky.php:333 +msgid "Personal Data Server" msgstr "" -#: bluesky.php:323 +#: bluesky.php:333 +msgid "The personal data server (PDS) is the system that hosts your profile." +msgstr "" + +#: bluesky.php:334 msgid "Bluesky handle" msgstr "" -#: bluesky.php:324 +#: bluesky.php:335 msgid "Bluesky DID" msgstr "" -#: bluesky.php:324 +#: bluesky.php:335 msgid "" "This is the unique identifier. It will be fetched automatically, when the " "handle is entered." msgstr "" -#: bluesky.php:325 +#: bluesky.php:336 msgid "Bluesky app password" msgstr "" -#: bluesky.php:325 +#: bluesky.php:336 msgid "" "Please don't add your real password here, but instead create a specific app " "password in the Bluesky settings." msgstr "" -#: bluesky.php:331 +#: bluesky.php:342 msgid "Bluesky Import/Export" msgstr "" -#: bluesky.php:382 +#: bluesky.php:395 msgid "Post to Bluesky" msgstr "" diff --git a/bluesky/templates/connector_settings.tpl b/bluesky/templates/connector_settings.tpl index c4ffedff0..db5ac5d5b 100644 --- a/bluesky/templates/connector_settings.tpl +++ b/bluesky/templates/connector_settings.tpl @@ -3,7 +3,7 @@ {{include file="field_checkbox.tpl" field=$bydefault}} {{include file="field_checkbox.tpl" field=$import}} {{include file="field_checkbox.tpl" field=$import_feeds}} -{{include file="field_input.tpl" field=$host}} +{{include file="field_input.tpl" field=$pds}} {{include file="field_input.tpl" field=$handle}} {{include file="field_input.tpl" field=$did}} {{include file="field_input.tpl" field=$password}} \ No newline at end of file From 959576080072b2c7e8c59cbf7672158ad5ce74b9 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 20 Nov 2023 21:07:09 +0000 Subject: [PATCH 062/388] Bluesky: Tags are now supported --- bluesky/bluesky.php | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index 3b2ce7e09..39218016f 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -693,11 +693,20 @@ function bluesky_create_post(array $item, stdClass $root = null, stdClass $paren function bluesky_get_urls(string $body): array { // Remove all hashtag and mention links - $body = preg_replace("/([#@!])\[url\=(.*?)\](.*?)\[\/url\]/ism", '$1$3', $body); + $body = preg_replace("/([@!])\[url\=(.*?)\](.*?)\[\/url\]/ism", '$1$3', $body); $body = BBCode::expandVideoLinks($body); $urls = []; + // Search for hash tags + if (preg_match_all("/#\[url\=(https?:.*?)\](.*?)\[\/url\]/ism", $body, $matches, PREG_SET_ORDER)) { + foreach ($matches as $match) { + $text = '#' . $match[2]; + $urls[] = ['tag' => $match[2], 'text' => $text, 'hash' => $text]; + $body = str_replace($match[0], $text, $body); + } + } + // Search for pure links if (preg_match_all("/\[url\](https?:.*?)\[\/url\]/ism", $body, $matches, PREG_SET_ORDER)) { foreach ($matches as $match) { @@ -763,9 +772,17 @@ function bluesky_get_facets(string $body, array $urls): array $facet->index->byteStart = $pos; $feature = new stdClass; - $feature->uri = $url['url']; + $type = '$type'; - $feature->$type = 'app.bsky.richtext.facet#link'; + if (!empty($url['tag'])) { + $feature->tag = $url['tag']; + $feature->$type = 'app.bsky.richtext.facet#tag'; + } elseif (!empty($url['url'])) { + $feature->uri = $url['url']; + $feature->$type = 'app.bsky.richtext.facet#link'; + } else { + continue; + } $facet->features = [$feature]; $facets[] = $facet; @@ -1162,8 +1179,13 @@ function bluesky_get_text(stdClass $record): string } break; + case 'app.bsky.richtext.facet#tag'; + $url = DI::baseUrl() . '/search?tag=' . urlencode($feature->tag); + $linktext = '#' . $feature->tag; + break; + default: - Logger::notice('Unhandled feature type', ['type' => $feature->$type, 'record' => $record]); + Logger::notice('Unhandled feature type', ['type' => $feature->$type, 'feature' => $feature, 'record' => $record]); break; } } From e62f6a95869bf3683afbb1a68cad264ba7f9690a Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 25 Nov 2023 18:57:03 +0000 Subject: [PATCH 063/388] Bluesky: Provide the correct user id while fetching content --- bluesky/bluesky.php | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index 39218016f..68baf4471 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -174,7 +174,7 @@ function bluesky_item_by_link(array &$hookData) $uri = 'at://' . $did . '/app.bsky.feed.post/' . $matches[2]; - $uri = bluesky_fetch_missing_post($uri, $hookData['uid'], 0, 0); + $uri = bluesky_fetch_missing_post($uri, $hookData['uid'], $hookData['uid'], 0, 0); Logger::debug('Got post', ['profile' => $matches[1], 'cid' => $matches[2], 'result' => $uri]); if (!empty($uri)) { $item = Post::selectFirst(['id'], ['uri' => $uri, 'uid' => $hookData['uid']]); @@ -950,7 +950,7 @@ function bluesky_fetch_notifications(int $uid) $item['gravity'] = Item::GRAVITY_ACTIVITY; $item['body'] = $item['verb'] = Activity::LIKE; $item['thr-parent'] = bluesky_get_uri($notification->record->subject); - $item['thr-parent'] = bluesky_fetch_missing_post($item['thr-parent'], $uid, $item['contact-id'], 0); + $item['thr-parent'] = bluesky_fetch_missing_post($item['thr-parent'], $uid, $uid, $item['contact-id'], 0); if (!empty($item['thr-parent'])) { $data = Item::insert($item); Logger::debug('Got like', ['uid' => $uid, 'result' => $data, 'uri' => $uri]); @@ -964,7 +964,7 @@ function bluesky_fetch_notifications(int $uid) $item['gravity'] = Item::GRAVITY_ACTIVITY; $item['body'] = $item['verb'] = Activity::ANNOUNCE; $item['thr-parent'] = bluesky_get_uri($notification->record->subject); - $item['thr-parent'] = bluesky_fetch_missing_post($item['thr-parent'], $uid, $item['contact-id'], 0); + $item['thr-parent'] = bluesky_fetch_missing_post($item['thr-parent'], $uid, $uid, $item['contact-id'], 0); if (!empty($item['thr-parent'])) { $data = Item::insert($item); Logger::debug('Got repost', ['uid' => $uid, 'result' => $data, 'uri' => $uri]); @@ -1059,7 +1059,7 @@ function bluesky_process_post(stdClass $post, int $uid, int $post_reason, $level Logger::debug('Importing post', ['uid' => $uid, 'indexedAt' => $post->indexedAt, 'uri' => $post->uri, 'cid' => $post->cid, 'root' => $post->record->reply->root ?? '']); $item = bluesky_get_header($post, $uri, $uid, $uid); - $item = bluesky_get_content($item, $post->record, $uri, $uid, $level); + $item = bluesky_get_content($item, $post->record, $uri, $uid, $uid, $level); if (empty($item)) { return 0; } @@ -1110,7 +1110,7 @@ function bluesky_get_header(stdClass $post, string $uri, int $uid, int $fetch_ui return $item; } -function bluesky_get_content(array $item, stdClass $record, string $uri, int $uid, int $level): array +function bluesky_get_content(array $item, stdClass $record, string $uri, int $uid, int $fetch_uid, int $level): array { if (empty($item)) { return []; @@ -1119,7 +1119,7 @@ function bluesky_get_content(array $item, stdClass $record, string $uri, int $ui if (!empty($record->reply)) { $item['parent-uri'] = bluesky_get_uri($record->reply->root); if ($item['parent-uri'] != $uri) { - $item['parent-uri'] = bluesky_fetch_missing_post($item['parent-uri'], $uid, $item['contact-id'], $level); + $item['parent-uri'] = bluesky_fetch_missing_post($item['parent-uri'], $uid, $fetch_uid, $item['contact-id'], $level); if (empty($item['parent-uri'])) { return []; } @@ -1127,7 +1127,7 @@ function bluesky_get_content(array $item, stdClass $record, string $uri, int $ui $item['thr-parent'] = bluesky_get_uri($record->reply->parent); if (!in_array($item['thr-parent'], [$uri, $item['parent-uri']])) { - $item['thr-parent'] = bluesky_fetch_missing_post($item['thr-parent'], $uid, $item['contact-id'], $level, $item['parent-uri']); + $item['thr-parent'] = bluesky_fetch_missing_post($item['thr-parent'], $uid, $fetch_uid, $item['contact-id'], $level, $item['parent-uri']); if (empty($item['thr-parent'])) { return []; } @@ -1233,7 +1233,7 @@ function bluesky_add_media(stdClass $embed, array $item, int $fetch_uid, int $le break; } $shared = bluesky_get_header($embed->record, $uri, 0, $fetch_uid); - $shared = bluesky_get_content($shared, $embed->record->value, $uri, $item['uid'], $level); + $shared = bluesky_get_content($shared, $embed->record->value, $uri, $item['uid'], $fetch_uid, $level); if (!empty($shared)) { if (!empty($embed->record->embeds)) { foreach ($embed->record->embeds as $single) { @@ -1253,7 +1253,7 @@ function bluesky_add_media(stdClass $embed, array $item, int $fetch_uid, int $le $shared = Post::selectFirst(['uri-id'], ['uri' => $uri, 'uid' => $item['uid']]); if (empty($shared)) { $shared = bluesky_get_header($embed->record->record, $uri, 0, $fetch_uid); - $shared = bluesky_get_content($shared, $embed->record->record->value, $uri, $item['uid'], $level); + $shared = bluesky_get_content($shared, $embed->record->record->value, $uri, $item['uid'], $fetch_uid, $level); if (!empty($shared)) { if (!empty($embed->record->record->embeds)) { foreach ($embed->record->record->embeds as $single) { @@ -1331,7 +1331,7 @@ function bluesky_get_uri_parts(string $uri): ?stdClass return $class; } -function bluesky_fetch_missing_post(string $uri, int $uid, int $causer, int $level, string $fallback = ''): string +function bluesky_fetch_missing_post(string $uri, int $uid, int $fetch_uid, int $causer, int $level, string $fallback = ''): string { $fetched_uri = bluesky_fetch_post($uri, $uid); if (!empty($fetched_uri)) { @@ -1349,7 +1349,7 @@ function bluesky_fetch_missing_post(string $uri, int $uid, int $causer, int $lev $fetch_uri = $class->uri; Logger::debug('Fetch missing post', ['level' => $level, 'uid' => $uid, 'uri' => $uri]); - $data = bluesky_xrpc_get($uid, 'app.bsky.feed.getPostThread', ['uri' => $fetch_uri]); + $data = bluesky_xrpc_get($fetch_uid, 'app.bsky.feed.getPostThread', ['uri' => $fetch_uri]); if (empty($data)) { Logger::info('Thread was not fetched', ['level' => $level, 'uid' => $uid, 'uri' => $uri, 'fallback' => $fallback]); return $fallback; @@ -1363,7 +1363,7 @@ function bluesky_fetch_missing_post(string $uri, int $uid, int $causer, int $lev $cdata = []; } - return bluesky_process_thread($data->thread, $uid, $cdata, $level); + return bluesky_process_thread($data->thread, $uid, $fetch_uid, $cdata, $level); } function bluesky_fetch_post(string $uri, int $uid): string @@ -1381,7 +1381,7 @@ function bluesky_fetch_post(string $uri, int $uid): string return ''; } -function bluesky_process_thread(stdClass $thread, int $uid, array $cdata, int $level): string +function bluesky_process_thread(stdClass $thread, int $uid, int $fetch_uid, array $cdata, int $level): string { if (empty($thread->post)) { Logger::info('Invalid post', ['post' => $thread]); @@ -1393,7 +1393,7 @@ function bluesky_process_thread(stdClass $thread, int $uid, array $cdata, int $l if (empty($fetched_uri)) { Logger::debug('Process missing post', ['uri' => $uri]); $item = bluesky_get_header($thread->post, $uri, $uid, $uid); - $item = bluesky_get_content($item, $thread->post->record, $uri, $uid, $level); + $item = bluesky_get_content($item, $thread->post->record, $uri, $uid, $fetch_uid, $level); if (!empty($item)) { $item['post-reason'] = Item::PR_FETCHED; @@ -1420,7 +1420,7 @@ function bluesky_process_thread(stdClass $thread, int $uid, array $cdata, int $l } foreach ($thread->replies ?? [] as $reply) { - $reply_uri = bluesky_process_thread($reply, $uid, $cdata, $level); + $reply_uri = bluesky_process_thread($reply, $uid, $fetch_uid, $cdata, $level); Logger::debug('Reply has been processed', ['uri' => $uri, 'reply' => $reply_uri]); } @@ -1578,7 +1578,12 @@ function bluesky_get_user_pds(int $uid): string if (!empty($pds)) { return $pds; } - $pds = bluesky_get_pds(DI::pConfig()->get($uid, 'bluesky', 'did')); + $did = DI::pConfig()->get($uid, 'bluesky', 'did'); + if (empty($did)) { + Logger::debug('Blubb-1', ['uid' => $uid]); + return ''; + } + $pds = bluesky_get_pds($did); DI::pConfig()->set($uid, 'bluesky', 'pds', $pds); return $pds; } From 48cde643f6b0002a23895c2d5a35e71b192ba8ec Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 25 Nov 2023 19:02:10 +0000 Subject: [PATCH 064/388] Improved logging message --- bluesky/bluesky.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index 68baf4471..dd946a5af 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -1580,7 +1580,7 @@ function bluesky_get_user_pds(int $uid): string } $did = DI::pConfig()->get($uid, 'bluesky', 'did'); if (empty($did)) { - Logger::debug('Blubb-1', ['uid' => $uid]); + Logger::notice('Empty did for user', ['uid' => $uid]); return ''; } $pds = bluesky_get_pds($did); From 14fd9006286f338848876b843d060c629b59afb5 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 25 Nov 2023 22:00:45 +0000 Subject: [PATCH 065/388] Store hash tags --- bluesky/bluesky.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index dd946a5af..47e45f4eb 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -41,6 +41,7 @@ use Friendica\Model\Item; use Friendica\Model\ItemURI; use Friendica\Model\Photo; use Friendica\Model\Post; +use Friendica\Model\Tag; use Friendica\Network\HTTPClient\Client\HttpClientAccept; use Friendica\Network\HTTPClient\Client\HttpClientOptions; use Friendica\Object\Image; @@ -1134,13 +1135,13 @@ function bluesky_get_content(array $item, stdClass $record, string $uri, int $ui } } - $item['body'] = bluesky_get_text($record); + $item['body'] = bluesky_get_text($record, $item['uri-id']); $item['created'] = DateTimeFormat::utc($record->createdAt, DateTimeFormat::MYSQL); $item['transmitted-languages'] = $record->langs ?? []; return $item; } -function bluesky_get_text(stdClass $record): string +function bluesky_get_text(stdClass $record, int $uri_id): string { $text = $record->text ?? ''; @@ -1180,6 +1181,7 @@ function bluesky_get_text(stdClass $record): string break; case 'app.bsky.richtext.facet#tag'; + Tag::store($uri_id, Tag::HASHTAG, $feature->tag); $url = DI::baseUrl() . '/search?tag=' . urlencode($feature->tag); $linktext = '#' . $feature->tag; break; From 22bf23b8331d83e7c52982eb4731d1436ebc240f Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 4 Dec 2023 20:29:31 +0000 Subject: [PATCH 066/388] Bluesky: Fix adding a new account --- bluesky/bluesky.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index 47e45f4eb..d2f13ebed 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -352,7 +352,7 @@ function bluesky_settings_post(array &$b) if (empty($_POST['bluesky-submit'])) { return; } - + $old_pds = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'pds'); $old_handle = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'handle'); $old_did = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'did'); @@ -365,7 +365,7 @@ function bluesky_settings_post(array &$b) DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'import', intval($_POST['bluesky_import'])); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'import_feeds', intval($_POST['bluesky_import_feeds'])); - if (!empty($host) && !empty($handle)) { + if (!empty($handle)) { if (empty($old_did) || $old_handle != $handle) { DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'did', bluesky_get_did(DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'handle'))); } From 397282cbb355754bedc85cf606c16521ce42c2bf Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 6 Dec 2023 06:31:52 +0000 Subject: [PATCH 067/388] Bluesky: Improved on the connector page --- bluesky/bluesky.php | 85 ++++++++++++++++++++++++++++++++++---- bluesky/lang/C/messages.po | 76 +++++++++++++++++++++++----------- 2 files changed, 128 insertions(+), 33 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index d2f13ebed..1bbc6356f 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -53,6 +53,14 @@ use Friendica\Util\Strings; const BLUESKY_DEFAULT_POLL_INTERVAL = 10; // given in minutes const BLUESKY_IMAGE_SIZE = [1000000, 500000, 100000, 50000]; +const BLUEKSY_STATUS_UNKNOWN = 0; +const BLUEKSY_STATUS_TOKEN_OK = 1; +const BLUEKSY_STATUS_SUCCESS = 2; +const BLUEKSY_STATUS_API_FAIL = 10; +const BLUEKSY_STATUS_DID_FAIL = 11; +const BLUEKSY_STATUS_PDS_FAIL = 12; +const BLUEKSY_STATUS_TOKEN_FAIL = 13; + /* * (Currently) hard wired paths for Bluesky services */ @@ -323,8 +331,6 @@ function bluesky_settings(array &$data) $import = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'import') ?? false; $import_feeds = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'import_feeds') ?? false; - $status = $token ? DI::l10n()->t("You are authenticated to Bluesky. For security reasons the password isn't stored.") : DI::l10n()->t('You are not authenticated. Please enter the app password.'); - $t = Renderer::getMarkupTemplate('connector_settings.tpl', 'addon/bluesky/'); $html = Renderer::replaceMacros($t, [ '$enable' => ['bluesky', DI::l10n()->t('Enable Bluesky Post Addon'), $enabled], @@ -335,7 +341,7 @@ function bluesky_settings(array &$data) '$handle' => ['bluesky_handle', DI::l10n()->t('Bluesky handle'), $handle], '$did' => ['bluesky_did', DI::l10n()->t('Bluesky DID'), $did, DI::l10n()->t('This is the unique identifier. It will be fetched automatically, when the handle is entered.'), '', 'readonly'], '$password' => ['bluesky_password', DI::l10n()->t('Bluesky app password'), '', DI::l10n()->t("Please don't add your real password here, but instead create a specific app password in the Bluesky settings.")], - '$status' => $status + '$status' => bluesky_get_status($handle, $did, $pds, $token), ]); $data = [ @@ -347,6 +353,45 @@ function bluesky_settings(array &$data) ]; } +function bluesky_get_status(string $handle = null, string $did = null, string $pds = null, string $token = null): string +{ + if (empty($handle)) { + return DI::l10n()->t('You are not authenticated. Please enter your handle and the app password.'); + } + + $status = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'status') ?? BLUEKSY_STATUS_UNKNOWN; + + // Fallback mechanism for connection that had been established before the introduction of the status + if ($status == BLUEKSY_STATUS_UNKNOWN) { + if (empty($did)) { + $status = BLUEKSY_STATUS_DID_FAIL; + } elseif (empty($pds)) { + $status = BLUEKSY_STATUS_PDS_FAIL; + } elseif (!empty($token)) { + $status = BLUEKSY_STATUS_TOKEN_OK; + } else { + $status = BLUEKSY_STATUS_TOKEN_FAIL; + } + } + + switch ($status) { + case BLUEKSY_STATUS_TOKEN_OK: + return DI::l10n()->t("You are authenticated to Bluesky. For security reasons the password isn't stored."); + case BLUEKSY_STATUS_SUCCESS: + return DI::l10n()->t('The communication with the personal data server service (PDS) is established.'); + case BLUEKSY_STATUS_API_FAIL; + return DI::l10n()->t('Communication issues with the personal data server service (PDS).'); + case BLUEKSY_STATUS_DID_FAIL: + return DI::l10n()->t('The DID for the provided handle could not be detected. Please check if you entered the correct handle.'); + case BLUEKSY_STATUS_PDS_FAIL: + return DI::l10n()->t('The personal data server service (PDS) could not be detected.'); + case BLUEKSY_STATUS_TOKEN_FAIL: + return DI::l10n()->t('The authentication with the provided handle and password failed. Please check if you entered the correct password.'); + default: + return ''; + } +} + function bluesky_settings_post(array &$b) { if (empty($_POST['bluesky-submit'])) { @@ -367,17 +412,33 @@ function bluesky_settings_post(array &$b) if (!empty($handle)) { if (empty($old_did) || $old_handle != $handle) { - DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'did', bluesky_get_did(DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'handle'))); + $did = bluesky_get_did(DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'handle')); + if (empty($did)) { + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'status', BLUEKSY_STATUS_DID_FAIL); + } + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'did', $did); + } else { + $did = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'did'); } - if (empty($old_pds) || $old_handle != $handle) { - DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'pds', bluesky_get_pds(DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'did'))); + if (!empty($did) && (empty($old_pds) || $old_handle != $handle)) { + $pds = bluesky_get_pds($did); + if (empty($pds)) { + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'status', BLUEKSY_STATUS_PDS_FAIL); + } + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'pds', $pds); + } else { + $pds = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'pds'); } } else { DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'bluesky', 'did'); DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'bluesky', 'pds'); + DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'bluesky', 'access_token'); + DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'bluesky', 'refresh_token'); + DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'bluesky', 'token_created'); + DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'bluesky', 'status'); } - if (!empty($_POST['bluesky_password'])) { + if (!empty($did) && !empty($pds) && !empty($_POST['bluesky_password'])) { bluesky_create_token(DI::userSession()->getLocalUserId(), $_POST['bluesky_password']); } } @@ -1642,6 +1703,7 @@ function bluesky_create_token(int $uid, string $password): string $data = bluesky_post($uid, '/xrpc/com.atproto.server.createSession', json_encode(['identifier' => $did, 'password' => $password]), ['Content-type' => 'application/json']); if (empty($data)) { + DI::pConfig()->set($uid, 'bluesky', 'status', BLUEKSY_STATUS_TOKEN_FAIL); return ''; } @@ -1649,6 +1711,7 @@ function bluesky_create_token(int $uid, string $password): string DI::pConfig()->set($uid, 'bluesky', 'access_token', $data->accessJwt); DI::pConfig()->set($uid, 'bluesky', 'refresh_token', $data->refreshJwt); DI::pConfig()->set($uid, 'bluesky', 'token_created', time()); + DI::pConfig()->set($uid, 'bluesky', 'status', BLUEKSY_STATUS_TOKEN_OK); return $data->accessJwt; } @@ -1663,14 +1726,17 @@ function bluesky_post(int $uid, string $url, string $params, array $headers): ?s $curlResult = DI::httpClient()->post(bluesky_get_user_pds($uid) . $url, $params, $headers); } catch (\Exception $e) { Logger::notice('Exception on post', ['exception' => $e]); + DI::pConfig()->set($uid, 'bluesky', 'status', BLUEKSY_STATUS_API_FAIL); return null; } if (!$curlResult->isSuccess()) { Logger::notice('API Error', ['error' => json_decode($curlResult->getBody()) ?: $curlResult->getBody()]); + DI::pConfig()->set($uid, 'bluesky', 'status', BLUEKSY_STATUS_API_FAIL); return null; } + DI::pConfig()->set($uid, 'bluesky', 'status', BLUEKSY_STATUS_SUCCESS); return json_decode($curlResult->getBody()); } @@ -1680,7 +1746,10 @@ function bluesky_xrpc_get(int $uid, string $url, array $parameters = []): ?stdCl $url .= '?' . http_build_query($parameters); } - return bluesky_get(bluesky_get_user_pds($uid) . '/xrpc/' . $url, HttpClientAccept::JSON, [HttpClientOptions::HEADERS => ['Authorization' => ['Bearer ' . bluesky_get_token($uid)]]]); + $data = bluesky_get(bluesky_get_user_pds($uid) . '/xrpc/' . $url, HttpClientAccept::JSON, [HttpClientOptions::HEADERS => ['Authorization' => ['Bearer ' . bluesky_get_token($uid)]]]); + DI::pConfig()->set($uid, 'bluesky', 'status', is_null($data) ? BLUEKSY_STATUS_API_FAIL : BLUEKSY_STATUS_SUCCESS); + return $data; + } function bluesky_get(string $url, string $accept_content = HttpClientAccept::DEFAULT, array $opts = []): ?stdClass diff --git a/bluesky/lang/C/messages.po b/bluesky/lang/C/messages.po index a5349142e..132e608a1 100644 --- a/bluesky/lang/C/messages.po +++ b/bluesky/lang/C/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-11-19 18:51+0000\n" +"POT-Creation-Date: 2023-12-06 06:30+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,74 +17,100 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: bluesky.php:325 -msgid "" -"You are authenticated to Bluesky. For security reasons the password isn't " -"stored." -msgstr "" - -#: bluesky.php:325 -msgid "You are not authenticated. Please enter the app password." -msgstr "" - -#: bluesky.php:329 +#: bluesky.php:336 msgid "Enable Bluesky Post Addon" msgstr "" -#: bluesky.php:330 +#: bluesky.php:337 msgid "Post to Bluesky by default" msgstr "" -#: bluesky.php:331 +#: bluesky.php:338 msgid "Import the remote timeline" msgstr "" -#: bluesky.php:332 +#: bluesky.php:339 msgid "Import the pinned feeds" msgstr "" -#: bluesky.php:332 +#: bluesky.php:339 msgid "" "When activated, Posts will be imported from all the feeds that you pinned in " "Bluesky." msgstr "" -#: bluesky.php:333 +#: bluesky.php:340 msgid "Personal Data Server" msgstr "" -#: bluesky.php:333 +#: bluesky.php:340 msgid "The personal data server (PDS) is the system that hosts your profile." msgstr "" -#: bluesky.php:334 +#: bluesky.php:341 msgid "Bluesky handle" msgstr "" -#: bluesky.php:335 +#: bluesky.php:342 msgid "Bluesky DID" msgstr "" -#: bluesky.php:335 +#: bluesky.php:342 msgid "" "This is the unique identifier. It will be fetched automatically, when the " "handle is entered." msgstr "" -#: bluesky.php:336 +#: bluesky.php:343 msgid "Bluesky app password" msgstr "" -#: bluesky.php:336 +#: bluesky.php:343 msgid "" "Please don't add your real password here, but instead create a specific app " "password in the Bluesky settings." msgstr "" -#: bluesky.php:342 +#: bluesky.php:349 msgid "Bluesky Import/Export" msgstr "" -#: bluesky.php:395 +#: bluesky.php:359 +msgid "" +"You are not authenticated. Please enter your handle and the app password." +msgstr "" + +#: bluesky.php:379 +msgid "" +"You are authenticated to Bluesky. For security reasons the password isn't " +"stored." +msgstr "" + +#: bluesky.php:381 +msgid "" +"The communication with the personal data server service (PDS) is established." +msgstr "" + +#: bluesky.php:383 +msgid "Communication issues with the personal data server service (PDS)." +msgstr "" + +#: bluesky.php:385 +msgid "" +"The DID for the provided handle could not be detected. Please check if you " +"entered the correct handle." +msgstr "" + +#: bluesky.php:387 +msgid "The personal data server service (PDS) could not be detected." +msgstr "" + +#: bluesky.php:389 +msgid "" +"The authentication with the provided handle and password failed. Please " +"check if you entered the correct password." +msgstr "" + +#: bluesky.php:457 msgid "Post to Bluesky" msgstr "" From 50d8d44489e69fd0c9cb9cfeed7b32edd4d31520 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 7 Dec 2023 12:03:53 +0000 Subject: [PATCH 068/388] Bluesky: remove @ and spaces from the handle --- bluesky/bluesky.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index 1bbc6356f..2f70ed745 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -402,7 +402,7 @@ function bluesky_settings_post(array &$b) $old_handle = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'handle'); $old_did = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'did'); - $handle = $_POST['bluesky_handle']; + $handle = trim($_POST['bluesky_handle'], ' @'); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'post', intval($_POST['bluesky'])); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'post_by_default', intval($_POST['bluesky_bydefault'])); From 727eca1ce7797f818a5a0aa0b445283dced09205 Mon Sep 17 00:00:00 2001 From: loma-one Date: Sat, 16 Sep 2023 16:54:54 +0200 Subject: [PATCH 069/388] Coloured box added Among other things, I use the page header to inform about current maintenance work or other upcoming work. The information should therefore be provided within an appropriate framework. With a little CSS, the page header gets a frame in green. The font was adjusted to an appropriate size. --- pageheader/pageheader.css | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pageheader/pageheader.css b/pageheader/pageheader.css index 8b3282fb7..17ad64c19 100644 --- a/pageheader/pageheader.css +++ b/pageheader/pageheader.css @@ -21,3 +21,13 @@ margin-top: 25px; font-size: 20px; } + +/* The pageheader box */ +.pageheader { + padding: 20px; + background-color: #2eb885; /* Green */ + color: white; + border: 1px solid transparent; + border-radius: 2px; + margin-bottom: 15px; +} From d685663ac068584d4ed88f5424ab74ef55a4d9c1 Mon Sep 17 00:00:00 2001 From: loma-one Date: Wed, 20 Sep 2023 15:32:18 +0200 Subject: [PATCH 070/388] Coloured box added --- pageheader/pageheader.css | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/pageheader/pageheader.css b/pageheader/pageheader.css index 17ad64c19..3360522e2 100644 --- a/pageheader/pageheader.css +++ b/pageheader/pageheader.css @@ -20,14 +20,11 @@ width: 100%; margin-top: 25px; font-size: 20px; -} - -/* The pageheader box */ -.pageheader { - padding: 20px; - background-color: #2eb885; /* Green */ - color: white; - border: 1px solid transparent; - border-radius: 2px; - margin-bottom: 15px; + /* The pageheader box */ + padding: 20px; + background-color: #2eb885; /* Green */ + color: white; + border: 1px solid transparent; + border-radius: 2px; + margin-bottom: 15px; } From 9315b185e8b9a4ad39db90f731ae93098d551634 Mon Sep 17 00:00:00 2001 From: loma-one Date: Sat, 23 Sep 2023 18:28:54 +0200 Subject: [PATCH 071/388] pageheader/pageheader.css aktualisiert --- pageheader/pageheader.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pageheader/pageheader.css b/pageheader/pageheader.css index 3360522e2..33ab6ad75 100644 --- a/pageheader/pageheader.css +++ b/pageheader/pageheader.css @@ -22,8 +22,8 @@ font-size: 20px; /* The pageheader box */ padding: 20px; - background-color: #2eb885; /* Green */ - color: white; + /*background-color: #2eb885; /* Green */ + /*color: white;*/ border: 1px solid transparent; border-radius: 2px; margin-bottom: 15px; From 2c2a813324a192e9441a059c30a52292add56fea Mon Sep 17 00:00:00 2001 From: loma-one Date: Tue, 3 Oct 2023 10:51:42 +0200 Subject: [PATCH 072/388] [pageheader] Improve visibility Removed commented out code from your pull request --- pageheader/pageheader.css | 2 -- 1 file changed, 2 deletions(-) diff --git a/pageheader/pageheader.css b/pageheader/pageheader.css index 33ab6ad75..f6c28fbfa 100644 --- a/pageheader/pageheader.css +++ b/pageheader/pageheader.css @@ -22,8 +22,6 @@ font-size: 20px; /* The pageheader box */ padding: 20px; - /*background-color: #2eb885; /* Green */ - /*color: white;*/ border: 1px solid transparent; border-radius: 2px; margin-bottom: 15px; From eadbcc069f0dd793625afb54732b127c5bada676 Mon Sep 17 00:00:00 2001 From: loma-one Date: Sun, 3 Dec 2023 13:01:40 +0100 Subject: [PATCH 073/388] =?UTF-8?q?invidious=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- invidious | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 invidious diff --git a/invidious b/invidious new file mode 100644 index 000000000..e69de29bb From 46fdcc1c0ed09bc7c6e71f87845668362c2ee9ac Mon Sep 17 00:00:00 2001 From: loma-one Date: Sun, 3 Dec 2023 13:02:03 +0100 Subject: [PATCH 074/388] =?UTF-8?q?invidious=20gel=C3=B6scht?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- invidious | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 invidious diff --git a/invidious b/invidious deleted file mode 100644 index e69de29bb..000000000 From 9d932e6fa04e128451ea8907e69f10ea1e698c7f Mon Sep 17 00:00:00 2001 From: loma-one Date: Sun, 3 Dec 2023 13:07:45 +0100 Subject: [PATCH 075/388] Dateien nach "invidious" hochladen Replaces links to youtube.com to an invidious instance in all displays of postings on a node. --- invidious/invidious.php | 64 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 invidious/invidious.php diff --git a/invidious/invidious.php b/invidious/invidious.php new file mode 100644 index 000000000..4ff57fc04 --- /dev/null +++ b/invidious/invidious.php @@ -0,0 +1,64 @@ + + * + */ + +use Friendica\App; +use Friendica\Core\Hook; +use Friendica\Core\Renderer; +use Friendica\DI; + +function invidious_install() +{ + Hook::register('prepare_body_final', 'addon/invidious/invidious.php', 'invidious_render'); +} + +/* Handle the send data from the admin settings + */ +function invidious_addon_admin_post() +{ + DI::config()->set('invidious', 'server', rtrim(trim($_POST['invidiousserver']), '/')); +} + +/* Hook into the admin settings to let the admin choose an + * invidious server to use for the replacement. + */ +function invidious_addon_admin(string &$o) +{ + $invidiousserver = DI::config()->get('invidious', 'server'); + $t = Renderer::getMarkupTemplate('admin.tpl', 'addon/invidious/'); + $o = Renderer::replaceMacros($t, [ + '$settingdescription' => DI::l10n()->t('Which Invidious server shall be used for the replacements in the post bodies? Use the URL with servername and protocol. See %s for a list of available public Invidious servers.', 'https://redirect.invidious.io'), + '$invidiousserver' => ['invidiousserver', DI::l10n()->t('Invidious server'), $invidiousserver, 'https://example.com'], + '$submit' => DI::l10n()->t('Save Settings'), + ]); +} + +/* + * replace "youtube.com" with the chosen Invidious instance + */ +function invidious_render(array &$b) +{ + // this needs to be a system setting + $replaced = false; + $invidious = DI::config()->get('invidious', 'server', 'https://invidio.us'); + if (strstr($b['html'], 'https://www.youtube.com')) { + $b['html'] = str_replace('https://www.youtube.com', $invidious, $b['html']); + $replaced = true; + } + if (strstr($b['html'], 'https://youtube.com')) { + $b['html'] = str_replace('https://youtube.com', $invidious, $b['html']); + $replaced = true; + } + if (strstr($b['html'], 'https://youtu.be')) { + $b['html'] = str_replace('https://youtu.be', $invidious, $b['html']); + $replaced = true; + } + if ($replaced) { + $b['html'] .= '

' . DI::l10n()->t('(Invidious addon enabled: YouTube links via %s)', $invidious) . '

'; + } +} From ebf5ff1276b82f832736532bee75ebe1504b70ed Mon Sep 17 00:00:00 2001 From: loma-one Date: Sun, 3 Dec 2023 13:09:02 +0100 Subject: [PATCH 076/388] Dateien nach "invidious/templates" hochladen --- invidious/templates/admin.tpl | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 invidious/templates/admin.tpl diff --git a/invidious/templates/admin.tpl b/invidious/templates/admin.tpl new file mode 100644 index 000000000..1db85ff97 --- /dev/null +++ b/invidious/templates/admin.tpl @@ -0,0 +1,5 @@ +

{{$settingdescription}}

+ +{{include file="field_input.tpl" field=$invidiousserver}} + +
From f46980c7361139892ca4fc2fd563daca3f95a379 Mon Sep 17 00:00:00 2001 From: loma-one Date: Sun, 3 Dec 2023 13:11:50 +0100 Subject: [PATCH 077/388] Dateien nach "invidious/lang/C" hochladen --- invidious/lang/C/messages.po | 1 + 1 file changed, 1 insertion(+) create mode 100644 invidious/lang/C/messages.po diff --git a/invidious/lang/C/messages.po b/invidious/lang/C/messages.po new file mode 100644 index 000000000..8d1c8b69c --- /dev/null +++ b/invidious/lang/C/messages.po @@ -0,0 +1 @@ + From c98caaf41776d6c99657dc27bbcc09df255e0c9d Mon Sep 17 00:00:00 2001 From: loma-one Date: Sun, 3 Dec 2023 13:12:19 +0100 Subject: [PATCH 078/388] Dateien nach "invidious" hochladen --- invidious/README.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 invidious/README.md diff --git a/invidious/README.md b/invidious/README.md new file mode 100644 index 000000000..0f91fa021 --- /dev/null +++ b/invidious/README.md @@ -0,0 +1,4 @@ +invidious Addon for Friendica +========================== + +This addon will replace "youtube.com" with the chosen Invidious instance From 0f65c2349040eff6ecee294f8262faf6a3ddb11c Mon Sep 17 00:00:00 2001 From: loma-one Date: Sun, 3 Dec 2023 18:54:39 +0100 Subject: [PATCH 079/388] invidious/invidious.php aktualisiert Redirects from youtu.be do not work reliably. Therefore this one has been removed. --- invidious/invidious.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/invidious/invidious.php b/invidious/invidious.php index 4ff57fc04..c647fd1b7 100644 --- a/invidious/invidious.php +++ b/invidious/invidious.php @@ -53,10 +53,6 @@ function invidious_render(array &$b) if (strstr($b['html'], 'https://youtube.com')) { $b['html'] = str_replace('https://youtube.com', $invidious, $b['html']); $replaced = true; - } - if (strstr($b['html'], 'https://youtu.be')) { - $b['html'] = str_replace('https://youtu.be', $invidious, $b['html']); - $replaced = true; } if ($replaced) { $b['html'] .= '

' . DI::l10n()->t('(Invidious addon enabled: YouTube links via %s)', $invidious) . '

'; From dc2d00b6c626f7777e02de061421bf71f31ae6a6 Mon Sep 17 00:00:00 2001 From: loma-one Date: Sun, 3 Dec 2023 20:29:19 +0100 Subject: [PATCH 080/388] invidious/lang/C/messages.po aktualisiert --- invidious/lang/C/messages.po | 41 +++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/invidious/lang/C/messages.po b/invidious/lang/C/messages.po index 8d1c8b69c..f93a87d6d 100644 --- a/invidious/lang/C/messages.po +++ b/invidious/lang/C/messages.po @@ -1 +1,40 @@ - + # ADDON invidious +# Copyright (C) +# This file is distributed under the same license as the Friendica invidious addon package. +# +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-12-03 20:21+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: invidious.php:35 +#, php-format +msgid "" +"Which Invidious server shall be used for the replacements in the post " +"bodies? Use the URL with servername and protocol. See %s for a list of " +"available public Invidious servers." +msgstr "" + +#: invidious.php:36 +msgid "Invidious server" +msgstr "" + +#: invidious.php:37 +msgid "Save Settings" +msgstr "" + +#: invidious.php:64 +#, php-format +msgid "(Invidious addon enabled: YouTube links via %s)" +msgstr "" + From 668ea972ccb3974ceba4be993a8a39a9734c3cad Mon Sep 17 00:00:00 2001 From: loma-one Date: Mon, 4 Dec 2023 22:01:46 +0100 Subject: [PATCH 081/388] invidious/invidious.php aktualisiert --- invidious/invidious.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/invidious/invidious.php b/invidious/invidious.php index c647fd1b7..e6ac4ac38 100644 --- a/invidious/invidious.php +++ b/invidious/invidious.php @@ -50,7 +50,7 @@ function invidious_render(array &$b) $b['html'] = str_replace('https://www.youtube.com', $invidious, $b['html']); $replaced = true; } - if (strstr($b['html'], 'https://youtube.com')) { + if (strstr($b['html'], 'https://youtube.com')) { $b['html'] = str_replace('https://youtube.com', $invidious, $b['html']); $replaced = true; } From 90d897f4fab3f2c2fb7bb01daebdb58fffc710a1 Mon Sep 17 00:00:00 2001 From: loma-one Date: Tue, 5 Dec 2023 09:08:36 +0100 Subject: [PATCH 082/388] This addon will replace "youtube.com" with the chosen Invidious instance URL combine --- invidious/invidious.php | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/invidious/invidious.php b/invidious/invidious.php index e6ac4ac38..5c6250095 100644 --- a/invidious/invidious.php +++ b/invidious/invidious.php @@ -2,7 +2,7 @@ /* * Name: invidious * Description: Replaces links to youtube.com to an invidious instance in all displays of postings on a node. - * Version: 0.1 + * Version: 0.2 * Author: Matthias Ebers <@feb@loma.ml> * */ @@ -46,14 +46,19 @@ function invidious_render(array &$b) // this needs to be a system setting $replaced = false; $invidious = DI::config()->get('invidious', 'server', 'https://invidio.us'); - if (strstr($b['html'], 'https://www.youtube.com')) { - $b['html'] = str_replace('https://www.youtube.com', $invidious, $b['html']); - $replaced = true; - } - if (strstr($b['html'], 'https://youtube.com')) { - $b['html'] = str_replace('https://youtube.com', $invidious, $b['html']); - $replaced = true; + + $youtubeUrls = [ + 'https://www.youtube.com', + 'https://youtube.com', + ]; + + foreach ($youtubeUrls as $youtubeUrl) { + if (strstr($b['html'], $youtubeUrl)) { + $b['html'] = str_replace($youtubeUrl, $invidious, $b['html']); + $replaced = true; + } } + if ($replaced) { $b['html'] .= '

' . DI::l10n()->t('(Invidious addon enabled: YouTube links via %s)', $invidious) . '

'; } From 26983977c4e5453e72912d54dcd984c793ee1f8f Mon Sep 17 00:00:00 2001 From: loma-one Date: Tue, 5 Dec 2023 22:40:49 +0100 Subject: [PATCH 083/388] This addon will replace "youtube.com" with the chosen Invidious instance Suggestion from @heluecht for combined URLs adopted --- invidious/invidious.php | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/invidious/invidious.php b/invidious/invidious.php index 5c6250095..a92c49a67 100644 --- a/invidious/invidious.php +++ b/invidious/invidious.php @@ -3,7 +3,7 @@ * Name: invidious * Description: Replaces links to youtube.com to an invidious instance in all displays of postings on a node. * Version: 0.2 - * Author: Matthias Ebers <@feb@loma.ml> + * Author: Matthias Ebers * */ @@ -46,19 +46,10 @@ function invidious_render(array &$b) // this needs to be a system setting $replaced = false; $invidious = DI::config()->get('invidious', 'server', 'https://invidio.us'); - - $youtubeUrls = [ - 'https://www.youtube.com', - 'https://youtube.com', - ]; - - foreach ($youtubeUrls as $youtubeUrl) { - if (strstr($b['html'], $youtubeUrl)) { - $b['html'] = str_replace($youtubeUrl, $invidious, $b['html']); - $replaced = true; - } + if (strstr($b['html'], 'https://www.youtube.com')) { + $b['html'] = str_replace(['https://www.youtube.com', 'https://youtube.com'], $invidious, $b['html']); + $replaced = true; } - if ($replaced) { $b['html'] .= '

' . DI::l10n()->t('(Invidious addon enabled: YouTube links via %s)', $invidious) . '

'; } From f45f6ba992d7382abb742b0fb24021ba9c29afe4 Mon Sep 17 00:00:00 2001 From: loma-one Date: Wed, 6 Dec 2023 18:00:35 +0100 Subject: [PATCH 084/388] https://youtu.be Link Many thanks for the hint. With a small change '/watch?v=' the link to https://youtu.be now also works --- invidious/invidious.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/invidious/invidious.php b/invidious/invidious.php index a92c49a67..821d904cf 100644 --- a/invidious/invidious.php +++ b/invidious/invidious.php @@ -46,9 +46,9 @@ function invidious_render(array &$b) // this needs to be a system setting $replaced = false; $invidious = DI::config()->get('invidious', 'server', 'https://invidio.us'); - if (strstr($b['html'], 'https://www.youtube.com')) { - $b['html'] = str_replace(['https://www.youtube.com', 'https://youtube.com'], $invidious, $b['html']); - $replaced = true; + if (strpos($b['html'], 'https://www.youtube.com/') !== false || strpos($b['html'], 'https://youtube.com/') !== false || strpos($b['html'], 'https://youtu.be/') !== false) { + $b['html'] = str_replace('https://youtu.be/', $invidious . '/watch?v=', $b['html']); + $b['html'] = str_replace(['https://www.youtube.com/', 'https://youtube.com/'], $invidious . '/', $b['html']); } if ($replaced) { $b['html'] .= '

' . DI::l10n()->t('(Invidious addon enabled: YouTube links via %s)', $invidious) . '

'; From 372e75a91cde21e5057392d94e55cc4e722ccf12 Mon Sep 17 00:00:00 2001 From: loma-one Date: Wed, 6 Dec 2023 18:03:48 +0100 Subject: [PATCH 085/388] invidious/invidious.php aktualisiert --- invidious/invidious.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/invidious/invidious.php b/invidious/invidious.php index 821d904cf..ff984f6f8 100644 --- a/invidious/invidious.php +++ b/invidious/invidious.php @@ -47,8 +47,8 @@ function invidious_render(array &$b) $replaced = false; $invidious = DI::config()->get('invidious', 'server', 'https://invidio.us'); if (strpos($b['html'], 'https://www.youtube.com/') !== false || strpos($b['html'], 'https://youtube.com/') !== false || strpos($b['html'], 'https://youtu.be/') !== false) { - $b['html'] = str_replace('https://youtu.be/', $invidious . '/watch?v=', $b['html']); - $b['html'] = str_replace(['https://www.youtube.com/', 'https://youtube.com/'], $invidious . '/', $b['html']); + $b['html'] = str_replace('https://youtu.be/', $invidious . '/watch?v=', $b['html']); + $b['html'] = str_replace(['https://www.youtube.com/', 'https://youtube.com/'], $invidious . '/', $b['html']); } if ($replaced) { $b['html'] .= '

' . DI::l10n()->t('(Invidious addon enabled: YouTube links via %s)', $invidious) . '

'; From d53ad98af2cbce01d2cdd8375e2c2383d9f0eb98 Mon Sep 17 00:00:00 2001 From: loma-one Date: Wed, 6 Dec 2023 18:07:21 +0100 Subject: [PATCH 086/388] invidious/invidious.php aktualisiert --- invidious/invidious.php | 1 + 1 file changed, 1 insertion(+) diff --git a/invidious/invidious.php b/invidious/invidious.php index ff984f6f8..7692229db 100644 --- a/invidious/invidious.php +++ b/invidious/invidious.php @@ -49,6 +49,7 @@ function invidious_render(array &$b) if (strpos($b['html'], 'https://www.youtube.com/') !== false || strpos($b['html'], 'https://youtube.com/') !== false || strpos($b['html'], 'https://youtu.be/') !== false) { $b['html'] = str_replace('https://youtu.be/', $invidious . '/watch?v=', $b['html']); $b['html'] = str_replace(['https://www.youtube.com/', 'https://youtube.com/'], $invidious . '/', $b['html']); + $replaced = true; } if ($replaced) { $b['html'] .= '

' . DI::l10n()->t('(Invidious addon enabled: YouTube links via %s)', $invidious) . '

'; From a41a676bfb5491a46eaf93b9ef3cb7ea6fc17fe3 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 11 Dec 2023 04:36:20 +0000 Subject: [PATCH 087/388] Tumblr: Improved error handling whe fetching blog information --- tumblr/tumblr.php | 61 ++++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/tumblr/tumblr.php b/tumblr/tumblr.php index a7a0db4c0..812b5b30c 100644 --- a/tumblr/tumblr.php +++ b/tumblr/tumblr.php @@ -98,7 +98,7 @@ function tumblr_probe_detect(array &$hookData) return; } - $hookData['result'] = tumblr_get_contact_by_url($hookData['uri']); + $hookData['result'] = tumblr_get_contact_by_url($hookData['uri'], $hookData['uid']); // Authoritative probe should set the result even if the probe was unsuccessful if ($hookData['network'] == Protocol::TUMBLR && empty($hookData['result'])) { @@ -160,7 +160,7 @@ function tumblr_follow(array &$hook_data) Logger::debug('Check if contact is Tumblr', ['url' => $hook_data['url']]); - $fields = tumblr_get_contact_by_url($hook_data['url']); + $fields = tumblr_get_contact_by_url($hook_data['url'], $uid); if (empty($fields)) { Logger::debug('Contact is not a Tumblr contact', ['url' => $hook_data['url']]); return; @@ -1202,7 +1202,7 @@ function tumblr_get_page(int $uid, array $blogs = []): string function tumblr_get_blogs(int $uid): array { $userinfo = tumblr_get($uid, 'user/info'); - if ($userinfo->meta->status > 299) { + if ($userinfo->meta->status > 399) { Logger::notice('Error fetching blogs', ['meta' => $userinfo->meta, 'response' => $userinfo->response, 'errors' => $userinfo->errors]); return []; } @@ -1226,16 +1226,12 @@ function tumblr_enabled_for_user(int $uid) * Get a contact array from a Tumblr url * * @param string $url + * @param int $uid * @return array|null * @throws \Friendica\Network\HTTPException\InternalServerErrorException */ -function tumblr_get_contact_by_url(string $url): ?array +function tumblr_get_contact_by_url(string $url, int $uid): ?array { - $consumer_key = DI::config()->get('tumblr', 'consumer_key'); - if (empty($consumer_key)) { - return null; - } - if (!preg_match('#^https?://tumblr.com/(.+)#', $url, $matches) && !preg_match('#^https?://www\.tumblr.com/(.+)#', $url, $matches) && !preg_match('#^https?://(.+)\.tumblr.com#', $url, $matches)) { try { $curlResult = DI::httpClient()->get($url); @@ -1261,42 +1257,38 @@ function tumblr_get_contact_by_url(string $url): ?array return null; } - Logger::debug('Update Tumblr blog data', ['url' => $url]); + Logger::debug('Update Tumblr blog data', ['url' => $url, 'blog' => $blog, 'uid' => $uid]); - $curlResult = DI::httpClient()->get('https://api.tumblr.com/v2/blog/' . $blog . '/info?api_key=' . $consumer_key); - $body = $curlResult->getBody(); - $data = json_decode($body); - if (empty($data)) { - return null; - } - - if (is_array($data->response->blog) || empty($data->response->blog)) { - Logger::warning('Unexpected blog format', ['blog' => $blog, 'data' => $data]); + $info = tumblr_get($uid, 'blog/' . $blog . '/info'); + if ($info->meta->status > 399) { + Logger::notice('Error fetching blog info', ['meta' => $info->meta, 'response' => $info->response, 'errors' => $info->errors, 'blog' => $blog, 'uid' => $uid]); return null; + } else { + Logger::debug('Got data', ['blog' => $blog, 'meta' => $info->meta]); } $baseurl = 'https://tumblr.com'; - $url = $baseurl . '/' . $data->response->blog->name; + $url = $baseurl . '/' . $info->response->blog->name; return [ 'url' => $url, 'nurl' => Strings::normaliseLink($url), - 'addr' => $data->response->blog->name . '@tumblr.com', - 'alias' => $data->response->blog->url, + 'addr' => $info->response->blog->name . '@tumblr.com', + 'alias' => $info->response->blog->url, 'batch' => '', 'notify' => '', - 'poll' => 'tumblr::' . $data->response->blog->uuid, + 'poll' => 'tumblr::' . $info->response->blog->uuid, 'poco' => '', - 'name' => $data->response->blog->title ?: $data->response->blog->name, - 'nick' => $data->response->blog->name, + 'name' => $info->response->blog->title ?: $info->response->blog->name, + 'nick' => $info->response->blog->name, 'network' => Protocol::TUMBLR, 'baseurl' => $baseurl, 'pubkey' => '', 'priority' => 0, - 'guid' => $data->response->blog->uuid, - 'about' => HTML::toBBCode($data->response->blog->description), - 'photo' => $data->response->blog->avatar[0]->url, - 'header' => $data->response->blog->theme->header_image_focused, + 'guid' => $info->response->blog->uuid, + 'about' => HTML::toBBCode($info->response->blog->description), + 'photo' => $info->response->blog->avatar[0]->url, + 'header' => $info->response->blog->theme->header_image_focused, ]; } @@ -1312,11 +1304,20 @@ function tumblr_get(int $uid, string $url, array $parameters = []): stdClass { $url = 'https://api.tumblr.com/v2/' . $url; + if ($uid == 0) { + $consumer_key = DI::config()->get('tumblr', 'consumer_key'); + $parameters['api_key'] = $consumer_key; + } + if (!empty($parameters)) { $url .= '?' . http_build_query($parameters); } - $curlResult = DI::httpClient()->get($url, HttpClientAccept::JSON, [HttpClientOptions::HEADERS => ['Authorization' => ['Bearer ' . tumblr_get_token($uid)]]]); + if ($uid > 0) { + $curlResult = DI::httpClient()->get($url, HttpClientAccept::JSON, [HttpClientOptions::HEADERS => ['Authorization' => ['Bearer ' . tumblr_get_token($uid)]]]); + } else { + $curlResult = DI::httpClient()->get($url, HttpClientAccept::JSON); + } return tumblr_format_result($curlResult); } From 3a063f999d3b92e786d8e7d837e91878afb0d954 Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Sat, 16 Dec 2023 08:59:07 +0100 Subject: [PATCH 088/388] translation updates --- catavatar/lang/fr/messages.po | 15 ++- catavatar/lang/fr/strings.php | 8 +- langfilter/lang/ru/messages.po | 38 +++---- langfilter/lang/ru/strings.php | 4 +- mailstream/lang/fr/messages.po | 41 +++---- mailstream/lang/fr/strings.php | 1 + newmemberwidget/lang/cs/messages.po | 42 ++++---- newmemberwidget/lang/cs/strings.php | 5 - newmemberwidget/lang/de/messages.po | 47 ++++---- newmemberwidget/lang/de/strings.php | 12 +-- newmemberwidget/lang/es/messages.po | 52 ++++----- newmemberwidget/lang/es/strings.php | 8 +- newmemberwidget/lang/et/messages.po | 50 ++++----- newmemberwidget/lang/et/strings.php | 2 - newmemberwidget/lang/fr/messages.po | 49 ++++----- newmemberwidget/lang/fr/strings.php | 12 +-- newmemberwidget/lang/hu/messages.po | 50 ++++----- newmemberwidget/lang/hu/strings.php | 12 +-- newmemberwidget/lang/it/messages.po | 44 ++++---- newmemberwidget/lang/it/strings.php | 6 -- newmemberwidget/lang/pl/messages.po | 46 ++++---- newmemberwidget/lang/pl/strings.php | 6 -- newmemberwidget/lang/ru/messages.po | 58 +++++----- newmemberwidget/lang/ru/strings.php | 6 -- newmemberwidget/lang/sv/messages.po | 40 +++---- newmemberwidget/lang/sv/strings.php | 1 - nsfw/lang/fr/messages.po | 7 +- nsfw/lang/fr/strings.php | 4 +- piwik/lang/en-gb/strings.php | 2 +- piwik/lang/fr/messages.po | 27 +++-- piwik/lang/fr/strings.php | 1 + pumpio/lang/fr/messages.po | 45 ++++---- pumpio/lang/fr/strings.php | 2 +- securemail/lang/fr/messages.po | 9 +- securemail/lang/fr/strings.php | 4 +- showmore/lang/ru/messages.po | 32 +++--- showmore/lang/ru/strings.php | 6 +- tumblr/lang/es/messages.po | 91 +++++++++------- tumblr/lang/es/strings.php | 11 +- tumblr/lang/fr/messages.po | 68 +++++++----- tumblr/lang/fr/strings.php | 11 +- tumblr/lang/nl/messages.po | 81 +++++++++----- tumblr/lang/nl/strings.php | 3 +- twitter/lang/ar/messages.po | 113 ++++++-------------- twitter/lang/ar/strings.php | 1 - twitter/lang/cs/messages.po | 134 +++++++---------------- twitter/lang/cs/strings.php | 19 ---- twitter/lang/de/messages.po | 156 +++++++-------------------- twitter/lang/de/strings.php | 33 ++---- twitter/lang/es/messages.po | 133 +++++++---------------- twitter/lang/es/strings.php | 20 +--- twitter/lang/fr/messages.po | 158 +++++++-------------------- twitter/lang/fr/strings.php | 33 ++---- twitter/lang/hu/messages.po | 159 +++++++--------------------- twitter/lang/hu/strings.php | 33 ++---- twitter/lang/it/messages.po | 141 ++++++------------------ twitter/lang/it/strings.php | 16 --- twitter/lang/ja/messages.po | 145 ++++++++----------------- twitter/lang/ja/strings.php | 17 --- twitter/lang/nl/messages.po | 118 ++++++--------------- twitter/lang/nl/strings.php | 4 - twitter/lang/pl/messages.po | 155 +++++++-------------------- twitter/lang/pl/strings.php | 24 ----- twitter/lang/ru/messages.po | 131 ++++++++--------------- twitter/lang/ru/strings.php | 20 +--- twitter/lang/sv/messages.po | 130 ++++++----------------- twitter/lang/sv/strings.php | 4 - 67 files changed, 1026 insertions(+), 1930 deletions(-) diff --git a/catavatar/lang/fr/messages.po b/catavatar/lang/fr/messages.po index f4c4dd0d0..64e98568b 100644 --- a/catavatar/lang/fr/messages.po +++ b/catavatar/lang/fr/messages.po @@ -5,8 +5,7 @@ # # Translators: # Vladimir Núñez , 2019 -# Walter Bulbazor, 2021 -# Hypolite Petovan , 2022 +# Florent C., 2023 # #, fuzzy msgid "" @@ -15,8 +14,8 @@ msgstr "" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-11-21 19:14-0500\n" "PO-Revision-Date: 2018-04-07 05:23+0000\n" -"Last-Translator: Hypolite Petovan , 2022\n" -"Language-Team: French (https://www.transifex.com/Friendica/teams/12172/fr/)\n" +"Last-Translator: Florent C., 2023\n" +"Language-Team: French (https://app.transifex.com/Friendica/teams/12172/fr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -25,7 +24,7 @@ msgstr "" #: catavatar.php:48 msgid "Set default profile avatar or randomize the cat." -msgstr "Mettre l'avatar par défaut ou tirer au sort le Chat." +msgstr "Mettre l'avatar par défaut ou tirer au sort le chat." #: catavatar.php:53 msgid "Cat Avatar Settings" @@ -33,15 +32,15 @@ msgstr "Paramètres de Chat avatar" #: catavatar.php:56 msgid "Use Cat as Avatar" -msgstr "Utiliser Chat comme avatar" +msgstr "Utiliser ce Chat" #: catavatar.php:57 msgid "Another random Cat!" -msgstr "Un autre chat aléatoire !" +msgstr "Un autre Chat aléatoire !" #: catavatar.php:58 msgid "Reset to email Cat" -msgstr "Réinitialiser à Chat courriel" +msgstr "Revenir au Chat par défaut" #: catavatar.php:77 msgid "The cat hadn't found itself." diff --git a/catavatar/lang/fr/strings.php b/catavatar/lang/fr/strings.php index 5d8a10a3b..b68b9d453 100644 --- a/catavatar/lang/fr/strings.php +++ b/catavatar/lang/fr/strings.php @@ -5,11 +5,11 @@ function string_plural_select_fr($n){ $n = intval($n); if (($n == 0 || $n == 1)) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } }} -$a->strings['Set default profile avatar or randomize the cat.'] = 'Mettre l\'avatar par défaut ou tirer au sort le Chat.'; +$a->strings['Set default profile avatar or randomize the cat.'] = 'Mettre l\'avatar par défaut ou tirer au sort le chat.'; $a->strings['Cat Avatar Settings'] = 'Paramètres de Chat avatar'; -$a->strings['Use Cat as Avatar'] = 'Utiliser Chat comme avatar'; -$a->strings['Another random Cat!'] = 'Un autre chat aléatoire !'; -$a->strings['Reset to email Cat'] = 'Réinitialiser à Chat courriel'; +$a->strings['Use Cat as Avatar'] = 'Utiliser ce Chat'; +$a->strings['Another random Cat!'] = 'Un autre Chat aléatoire !'; +$a->strings['Reset to email Cat'] = 'Revenir au Chat par défaut'; $a->strings['The cat hadn\'t found itself.'] = 'Le Chat ne s\'y est pas retrouvé'; $a->strings['There was an error, the cat ran away.'] = 'Il y a eu une erreur et le chat s\'est enfui'; $a->strings['Profile Photos'] = 'Photos de profil'; diff --git a/langfilter/lang/ru/messages.po b/langfilter/lang/ru/messages.po index e1fbc9e83..45ad7b3d5 100644 --- a/langfilter/lang/ru/messages.po +++ b/langfilter/lang/ru/messages.po @@ -4,63 +4,59 @@ # # # Translators: -# Alexander An , 2020 +# Alexander An , 2020,2023 # Stanislav N. , 2018 msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-10-03 22:02-0400\n" -"PO-Revision-Date: 2020-10-09 17:48+0000\n" -"Last-Translator: Alexander An \n" -"Language-Team: Russian (http://www.transifex.com/Friendica/friendica/language/ru/)\n" +"POT-Creation-Date: 2021-11-21 19:15-0500\n" +"PO-Revision-Date: 2015-07-25 08:05+0000\n" +"Last-Translator: Alexander An , 2020,2023\n" +"Language-Team: Russian (http://app.transifex.com/Friendica/friendica/language/ru/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ru\n" "Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);\n" -#: langfilter.php:52 -msgid "Language Filter" -msgstr "Языковой фильтр" - -#: langfilter.php:53 +#: langfilter.php:49 msgid "" "This addon tries to identify the language posts are written in. If it does " "not match any language specified below, posts will be hidden by collapsing " "them." -msgstr "Это дополнение пытается идентифицировать язык, на котором написаны посты. Если язык не соответствует ни одному, указанному ниже, то такие посты будут скрыты." +msgstr "Это дополнение пытается идентифицировать язык, на котором сделаны записи. Если язык не соответствует ни одному, указанному ниже, то такие посты будут свёрнуты." -#: langfilter.php:54 +#: langfilter.php:50 msgid "Use the language filter" msgstr "Использовать языковой фильтр" -#: langfilter.php:55 +#: langfilter.php:51 msgid "Able to read" msgstr "Возможность читать" -#: langfilter.php:55 +#: langfilter.php:51 msgid "" "List of abbreviations (ISO 639-1 codes) for languages you speak, comma " "separated. For example \"de,it\"." msgstr "Список аббревиатур (кодов по ISO 639-1 ) для языков, на которых вы говорите. Например, \"ru,en\"." -#: langfilter.php:56 +#: langfilter.php:52 msgid "Minimum confidence in language detection" msgstr "Минимальная уверенность в определении языка" -#: langfilter.php:56 +#: langfilter.php:52 msgid "" "Minimum confidence in language detection being correct, from 0 to 100. Posts" " will not be filtered when the confidence of language detection is below " "this percent value." msgstr "Минимальная уверенность в правильном определении языка, от 0 до 100. Посты не будут скрыты, если уверенность в правильном определении языка в процентах ниже этого значения." -#: langfilter.php:57 +#: langfilter.php:53 msgid "Minimum length of message body" msgstr "Минимальная длина тела сообщения" -#: langfilter.php:57 +#: langfilter.php:53 msgid "" "Minimum number of characters in message body for filter to be used. Posts " "shorter than this will not be filtered. Note: Language detection is " @@ -68,10 +64,14 @@ msgid "" msgstr "Минимальное количество знаков в теле сообщения для применения фильтрации. Посты, длина которых меньше указанного значения, не будут отфильтрованы. Обратите внимание, что определение языка работает ненадежно для небольших постов (<200 символов)." #: langfilter.php:58 +msgid "Language Filter" +msgstr "Языковой фильтр" + +#: langfilter.php:60 msgid "Save Settings" msgstr "Сохранить настройки" -#: langfilter.php:189 +#: langfilter.php:193 #, php-format msgid "Filtered language: %s" msgstr "Отфильтрованный язык: %s" diff --git a/langfilter/lang/ru/strings.php b/langfilter/lang/ru/strings.php index 0489bd4fc..1f5619f76 100644 --- a/langfilter/lang/ru/strings.php +++ b/langfilter/lang/ru/strings.php @@ -5,8 +5,7 @@ function string_plural_select_ru($n){ $n = intval($n); if ($n%10==1 && $n%100!=11) { return 0; } else if ($n%10>=2 && $n%10<=4 && ($n%100<12 || $n%100>14)) { return 1; } else if ($n%10==0 || ($n%10>=5 && $n%10<=9) || ($n%100>=11 && $n%100<=14)) { return 2; } else { return 3; } }} -$a->strings['Language Filter'] = 'Языковой фильтр'; -$a->strings['This addon tries to identify the language posts are written in. If it does not match any language specified below, posts will be hidden by collapsing them.'] = 'Это дополнение пытается идентифицировать язык, на котором написаны посты. Если язык не соответствует ни одному, указанному ниже, то такие посты будут скрыты.'; +$a->strings['This addon tries to identify the language posts are written in. If it does not match any language specified below, posts will be hidden by collapsing them.'] = 'Это дополнение пытается идентифицировать язык, на котором сделаны записи. Если язык не соответствует ни одному, указанному ниже, то такие посты будут свёрнуты.'; $a->strings['Use the language filter'] = 'Использовать языковой фильтр'; $a->strings['Able to read'] = 'Возможность читать'; $a->strings['List of abbreviations (ISO 639-1 codes) for languages you speak, comma separated. For example "de,it".'] = 'Список аббревиатур (кодов по ISO 639-1 ) для языков, на которых вы говорите. Например, "ru,en".'; @@ -14,5 +13,6 @@ $a->strings['Minimum confidence in language detection'] = 'Минимальна $a->strings['Minimum confidence in language detection being correct, from 0 to 100. Posts will not be filtered when the confidence of language detection is below this percent value.'] = 'Минимальная уверенность в правильном определении языка, от 0 до 100. Посты не будут скрыты, если уверенность в правильном определении языка в процентах ниже этого значения.'; $a->strings['Minimum length of message body'] = 'Минимальная длина тела сообщения'; $a->strings['Minimum number of characters in message body for filter to be used. Posts shorter than this will not be filtered. Note: Language detection is unreliable for short content (<200 characters).'] = 'Минимальное количество знаков в теле сообщения для применения фильтрации. Посты, длина которых меньше указанного значения, не будут отфильтрованы. Обратите внимание, что определение языка работает ненадежно для небольших постов (<200 символов).'; +$a->strings['Language Filter'] = 'Языковой фильтр'; $a->strings['Save Settings'] = 'Сохранить настройки'; $a->strings['Filtered language: %s'] = 'Отфильтрованный язык: %s'; diff --git a/mailstream/lang/fr/messages.po b/mailstream/lang/fr/messages.po index 488d4c087..043181c5f 100644 --- a/mailstream/lang/fr/messages.po +++ b/mailstream/lang/fr/messages.po @@ -4,6 +4,7 @@ # # # Translators: +# Florent C., 2023 # Nicolas Derive, 2022 # ea1cd8241cb389ffb6f92bc6891eff5d_dc12308 <70dced5587d47e18d88f9298024d96f8_93383>, 2015 # StefOfficiel , 2015 @@ -13,8 +14,8 @@ msgstr "" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-11-21 19:15-0500\n" "PO-Revision-Date: 2014-06-23 09:54+0000\n" -"Last-Translator: Nicolas Derive, 2022\n" -"Language-Team: French (http://www.transifex.com/Friendica/friendica/language/fr/)\n" +"Last-Translator: Florent C., 2023\n" +"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -33,68 +34,72 @@ msgstr "Adresse de courriel de laquelle les éléments du flux sembleront proven msgid "Save Settings" msgstr "Sauvegarder les paramètres" -#: mailstream.php:301 +#: mailstream.php:311 msgid "Re:" msgstr "Re :" -#: mailstream.php:314 mailstream.php:317 +#: mailstream.php:324 mailstream.php:327 msgid "Friendica post" msgstr "Message Friendica" -#: mailstream.php:320 +#: mailstream.php:330 msgid "Diaspora post" msgstr "Message Diaspora" -#: mailstream.php:330 +#: mailstream.php:340 msgid "Feed item" msgstr "Élément du flux" -#: mailstream.php:333 +#: mailstream.php:343 msgid "Email" msgstr "Courriel" -#: mailstream.php:335 +#: mailstream.php:345 msgid "Friendica Item" msgstr "Élément de Friendica" -#: mailstream.php:404 +#: mailstream.php:419 msgid "Upstream" msgstr "En amont" -#: mailstream.php:405 +#: mailstream.php:420 +msgid "URI" +msgstr "URI" + +#: mailstream.php:421 msgid "Local" msgstr "Local" -#: mailstream.php:481 +#: mailstream.php:499 msgid "Enabled" msgstr "Activer" -#: mailstream.php:486 +#: mailstream.php:504 msgid "Email Address" msgstr "Adresse de courriel" -#: mailstream.php:488 +#: mailstream.php:506 msgid "Leave blank to use your account email address" msgstr "Laissez vide pour utiliser l'adresse de courriel de votre compte" -#: mailstream.php:492 +#: mailstream.php:510 msgid "Exclude Likes" msgstr "Exclure les \"j'aime\"" -#: mailstream.php:494 +#: mailstream.php:512 msgid "Check this to omit mailing \"Like\" notifications" msgstr "Cochez ceci pour éviter d'envoyer les notifications des \"J'aime\"" -#: mailstream.php:498 +#: mailstream.php:516 msgid "Attach Images" msgstr "Attacher les images" -#: mailstream.php:500 +#: mailstream.php:518 msgid "" "Download images in posts and attach them to the email. Useful for reading " "email while offline." msgstr "Télécharger les images des messages et les attacher au courriel. Utile pour les les courriels hors-ligne." -#: mailstream.php:507 +#: mailstream.php:525 msgid "Mail Stream Settings" msgstr "Paramètres de Mail Stream" diff --git a/mailstream/lang/fr/strings.php b/mailstream/lang/fr/strings.php index bfaf43893..a21d80b8a 100644 --- a/mailstream/lang/fr/strings.php +++ b/mailstream/lang/fr/strings.php @@ -15,6 +15,7 @@ $a->strings['Feed item'] = 'Élément du flux'; $a->strings['Email'] = 'Courriel'; $a->strings['Friendica Item'] = 'Élément de Friendica'; $a->strings['Upstream'] = 'En amont'; +$a->strings['URI'] = 'URI'; $a->strings['Local'] = 'Local'; $a->strings['Enabled'] = 'Activer'; $a->strings['Email Address'] = 'Adresse de courriel'; diff --git a/newmemberwidget/lang/cs/messages.po b/newmemberwidget/lang/cs/messages.po index 604734735..387144aba 100644 --- a/newmemberwidget/lang/cs/messages.po +++ b/newmemberwidget/lang/cs/messages.po @@ -10,7 +10,7 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-02-01 18:15+0100\n" +"POT-Creation-Date: 2023-06-03 15:50-0400\n" "PO-Revision-Date: 2014-06-23 10:26+0000\n" "Last-Translator: Aditoo, 2018\n" "Language-Team: Czech (http://app.transifex.com/Friendica/friendica/language/cs/)\n" @@ -29,48 +29,48 @@ msgid "Tips for New Members" msgstr "Tipy pro nové členy" #: newmemberwidget.php:33 -msgid "Global Support Forum" -msgstr "Globální fórum podpory" +msgid "Global Support Group" +msgstr "" #: newmemberwidget.php:37 -msgid "Local Support Forum" -msgstr "Místní fórum podpory" +msgid "Local Support Group" +msgstr "" -#: newmemberwidget.php:65 +#: newmemberwidget.php:62 msgid "Save Settings" msgstr "Uložit nastavení" -#: newmemberwidget.php:66 +#: newmemberwidget.php:63 msgid "Message" msgstr "Zpráva" -#: newmemberwidget.php:66 +#: newmemberwidget.php:63 msgid "Your message for new members. You can use bbcode here." msgstr "Vaše zpráva pro nové členy. Zde můžete použít BBCode." -#: newmemberwidget.php:67 -msgid "Add a link to global support forum" -msgstr "Přidejte odkaz na globální fórum podpory" +#: newmemberwidget.php:64 +msgid "Add a link to global support group" +msgstr "" -#: newmemberwidget.php:67 -msgid "Should a link to the global support forum be displayed?" -msgstr "Má být zobrazen odkaz na globální fórum podpory?" +#: newmemberwidget.php:64 +msgid "Should a link to the global support group be displayed?" +msgstr "" -#: newmemberwidget.php:68 -msgid "Add a link to the local support forum" -msgstr "Přidejte odkaz na místní fórum podpory" +#: newmemberwidget.php:65 +msgid "Add a link to the local support group" +msgstr "" -#: newmemberwidget.php:68 +#: newmemberwidget.php:65 msgid "" -"If you have a local support forum and want to have a link displayed in the " +"If you have a local support group and want to have a link displayed in the " "widget, check this box." msgstr "" -#: newmemberwidget.php:69 +#: newmemberwidget.php:66 msgid "Name of the local support group" msgstr "Název místního fóra podpory" -#: newmemberwidget.php:69 +#: newmemberwidget.php:66 msgid "" "If you checked the above, specify the nickname of the local support" " group here (i.e. helpers)" diff --git a/newmemberwidget/lang/cs/strings.php b/newmemberwidget/lang/cs/strings.php index 3b6dc2721..2f1504665 100644 --- a/newmemberwidget/lang/cs/strings.php +++ b/newmemberwidget/lang/cs/strings.php @@ -7,13 +7,8 @@ function string_plural_select_cs($n){ }} $a->strings['New Member'] = 'Nový člen'; $a->strings['Tips for New Members'] = 'Tipy pro nové členy'; -$a->strings['Global Support Forum'] = 'Globální fórum podpory'; -$a->strings['Local Support Forum'] = 'Místní fórum podpory'; $a->strings['Save Settings'] = 'Uložit nastavení'; $a->strings['Message'] = 'Zpráva'; $a->strings['Your message for new members. You can use bbcode here.'] = 'Vaše zpráva pro nové členy. Zde můžete použít BBCode.'; -$a->strings['Add a link to global support forum'] = 'Přidejte odkaz na globální fórum podpory'; -$a->strings['Should a link to the global support forum be displayed?'] = 'Má být zobrazen odkaz na globální fórum podpory?'; -$a->strings['Add a link to the local support forum'] = 'Přidejte odkaz na místní fórum podpory'; $a->strings['Name of the local support group'] = 'Název místního fóra podpory'; $a->strings['If you checked the above, specify the nickname of the local support group here (i.e. helpers)'] = 'Pokud jste zaškrtl/a výše uvedenou možnost, specifikujte zde přezdívku místní skupiny podpory (např. pomocnici)'; diff --git a/newmemberwidget/lang/de/messages.po b/newmemberwidget/lang/de/messages.po index 851dfdce7..87289e3ea 100644 --- a/newmemberwidget/lang/de/messages.po +++ b/newmemberwidget/lang/de/messages.po @@ -4,15 +4,16 @@ # # # Translators: +# Raroun, 2023 # Tobias Diekershoff , 2021 # Ulf Rompe , 2019 msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-02-01 18:15+0100\n" +"POT-Creation-Date: 2023-06-03 15:50-0400\n" "PO-Revision-Date: 2014-06-23 10:26+0000\n" -"Last-Translator: Tobias Diekershoff , 2021\n" +"Last-Translator: Raroun, 2023\n" "Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -29,48 +30,48 @@ msgid "Tips for New Members" msgstr "Tipps für neue Nutzer" #: newmemberwidget.php:33 -msgid "Global Support Forum" -msgstr "Globales Forum für Hilfsanfragen" +msgid "Global Support Group" +msgstr "Globale Support-Gruppe" #: newmemberwidget.php:37 -msgid "Local Support Forum" -msgstr "Lokales Forum für Hilfsanfragen" +msgid "Local Support Group" +msgstr "Lokale Support-Gruppe" -#: newmemberwidget.php:65 +#: newmemberwidget.php:62 msgid "Save Settings" msgstr "Einstellungen speichern" -#: newmemberwidget.php:66 +#: newmemberwidget.php:63 msgid "Message" msgstr "Nachricht" -#: newmemberwidget.php:66 +#: newmemberwidget.php:63 msgid "Your message for new members. You can use bbcode here." msgstr "Deine Nachricht für neue Nutzer. BBCode kann verwendet werden." -#: newmemberwidget.php:67 -msgid "Add a link to global support forum" -msgstr "Link zum globalen Support-Forum anzeigen" +#: newmemberwidget.php:64 +msgid "Add a link to global support group" +msgstr "Fügen Sie einen Link der globalen Support-Gruppe hinzu" -#: newmemberwidget.php:67 -msgid "Should a link to the global support forum be displayed?" -msgstr "Soll ein Link zum globalen Support-Forum angezeigt werden?" +#: newmemberwidget.php:64 +msgid "Should a link to the global support group be displayed?" +msgstr "Soll ein Link zur globalen Support-Gruppe angezeigt werden?" -#: newmemberwidget.php:68 -msgid "Add a link to the local support forum" -msgstr "Link zum lokalen Support-Forum anzeigen" +#: newmemberwidget.php:65 +msgid "Add a link to the local support group" +msgstr "Fügen Sie einen Link der lokalen Support-Gruppe hinzu" -#: newmemberwidget.php:68 +#: newmemberwidget.php:65 msgid "" -"If you have a local support forum and want to have a link displayed in the " +"If you have a local support group and want to have a link displayed in the " "widget, check this box." -msgstr "Wenn du ein lokales Support-Forum eingerichtet hast und ein Link darauf angezeigt werden soll, schalte dies ein." +msgstr "Wenn Sie eine lokale Support-Gruppe haben und einen Link im Widget anzeigen lassen möchten, markieren Sie dieses Feld." -#: newmemberwidget.php:69 +#: newmemberwidget.php:66 msgid "Name of the local support group" msgstr "Name des lokalen Support-Forums" -#: newmemberwidget.php:69 +#: newmemberwidget.php:66 msgid "" "If you checked the above, specify the nickname of the local support" " group here (i.e. helpers)" diff --git a/newmemberwidget/lang/de/strings.php b/newmemberwidget/lang/de/strings.php index c7dc503ce..aa3e0f884 100644 --- a/newmemberwidget/lang/de/strings.php +++ b/newmemberwidget/lang/de/strings.php @@ -7,14 +7,14 @@ function string_plural_select_de($n){ }} $a->strings['New Member'] = 'Neue Nutzer'; $a->strings['Tips for New Members'] = 'Tipps für neue Nutzer'; -$a->strings['Global Support Forum'] = 'Globales Forum für Hilfsanfragen'; -$a->strings['Local Support Forum'] = 'Lokales Forum für Hilfsanfragen'; +$a->strings['Global Support Group'] = 'Globale Support-Gruppe'; +$a->strings['Local Support Group'] = 'Lokale Support-Gruppe'; $a->strings['Save Settings'] = 'Einstellungen speichern'; $a->strings['Message'] = 'Nachricht'; $a->strings['Your message for new members. You can use bbcode here.'] = 'Deine Nachricht für neue Nutzer. BBCode kann verwendet werden.'; -$a->strings['Add a link to global support forum'] = 'Link zum globalen Support-Forum anzeigen'; -$a->strings['Should a link to the global support forum be displayed?'] = 'Soll ein Link zum globalen Support-Forum angezeigt werden?'; -$a->strings['Add a link to the local support forum'] = 'Link zum lokalen Support-Forum anzeigen'; -$a->strings['If you have a local support forum and want to have a link displayed in the widget, check this box.'] = 'Wenn du ein lokales Support-Forum eingerichtet hast und ein Link darauf angezeigt werden soll, schalte dies ein.'; +$a->strings['Add a link to global support group'] = 'Fügen Sie einen Link der globalen Support-Gruppe hinzu'; +$a->strings['Should a link to the global support group be displayed?'] = 'Soll ein Link zur globalen Support-Gruppe angezeigt werden?'; +$a->strings['Add a link to the local support group'] = 'Fügen Sie einen Link der lokalen Support-Gruppe hinzu'; +$a->strings['If you have a local support group and want to have a link displayed in the widget, check this box.'] = 'Wenn Sie eine lokale Support-Gruppe haben und einen Link im Widget anzeigen lassen möchten, markieren Sie dieses Feld.'; $a->strings['Name of the local support group'] = 'Name des lokalen Support-Forums'; $a->strings['If you checked the above, specify the nickname of the local support group here (i.e. helpers)'] = 'Wenn der Link angezeigt werden soll, dann trage hier den Spitznamen des Forums ein (z.B. helpers)'; diff --git a/newmemberwidget/lang/es/messages.po b/newmemberwidget/lang/es/messages.po index fb31e1430..b731a041b 100644 --- a/newmemberwidget/lang/es/messages.po +++ b/newmemberwidget/lang/es/messages.po @@ -10,15 +10,15 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-02-01 18:15+0100\n" -"PO-Revision-Date: 2021-04-06 01:46+0000\n" -"Last-Translator: Senex Petrovic \n" -"Language-Team: Spanish (http://www.transifex.com/Friendica/friendica/language/es/)\n" +"POT-Creation-Date: 2023-06-03 15:50-0400\n" +"PO-Revision-Date: 2014-06-23 10:26+0000\n" +"Last-Translator: Senex Petrovic , 2021\n" +"Language-Team: Spanish (http://app.transifex.com/Friendica/friendica/language/es/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: es\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" #: newmemberwidget.php:29 msgid "New Member" @@ -29,48 +29,48 @@ msgid "Tips for New Members" msgstr "Consejos para Nuevos Miembros" #: newmemberwidget.php:33 -msgid "Global Support Forum" -msgstr "Foro de Soporte Global" +msgid "Global Support Group" +msgstr "" #: newmemberwidget.php:37 -msgid "Local Support Forum" -msgstr "Foro de Soporte Local" +msgid "Local Support Group" +msgstr "" -#: newmemberwidget.php:65 +#: newmemberwidget.php:62 msgid "Save Settings" msgstr "Guardar Ajustes" -#: newmemberwidget.php:66 +#: newmemberwidget.php:63 msgid "Message" msgstr "Mensaje" -#: newmemberwidget.php:66 +#: newmemberwidget.php:63 msgid "Your message for new members. You can use bbcode here." msgstr "Su mensaje para los nuevos miembros. Puede usar bbcode aquí" -#: newmemberwidget.php:67 -msgid "Add a link to global support forum" -msgstr "Añadir un enlace al foro de soporte global" +#: newmemberwidget.php:64 +msgid "Add a link to global support group" +msgstr "" -#: newmemberwidget.php:67 -msgid "Should a link to the global support forum be displayed?" -msgstr "¿Debería mostrarse un enlace al foro de soporte global?" +#: newmemberwidget.php:64 +msgid "Should a link to the global support group be displayed?" +msgstr "" -#: newmemberwidget.php:68 -msgid "Add a link to the local support forum" -msgstr "Añadir un enlace al foro de soporte local" +#: newmemberwidget.php:65 +msgid "Add a link to the local support group" +msgstr "" -#: newmemberwidget.php:68 +#: newmemberwidget.php:65 msgid "" -"If you have a local support forum and want to have a link displayed in the " +"If you have a local support group and want to have a link displayed in the " "widget, check this box." -msgstr "Si tiene foro de soporte local y desea que se muestre un enlace en el widget, marque esta casilla." +msgstr "" -#: newmemberwidget.php:69 +#: newmemberwidget.php:66 msgid "Name of the local support group" msgstr "Nombre del grupo de soporte local" -#: newmemberwidget.php:69 +#: newmemberwidget.php:66 msgid "" "If you checked the above, specify the nickname of the local support" " group here (i.e. helpers)" diff --git a/newmemberwidget/lang/es/strings.php b/newmemberwidget/lang/es/strings.php index 28253b733..8798813ad 100644 --- a/newmemberwidget/lang/es/strings.php +++ b/newmemberwidget/lang/es/strings.php @@ -3,18 +3,12 @@ if(! function_exists("string_plural_select_es")) { function string_plural_select_es($n){ $n = intval($n); - return intval($n != 1); + if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } }} $a->strings['New Member'] = 'Nuevo Miembro'; $a->strings['Tips for New Members'] = 'Consejos para Nuevos Miembros'; -$a->strings['Global Support Forum'] = 'Foro de Soporte Global'; -$a->strings['Local Support Forum'] = 'Foro de Soporte Local'; $a->strings['Save Settings'] = 'Guardar Ajustes'; $a->strings['Message'] = 'Mensaje'; $a->strings['Your message for new members. You can use bbcode here.'] = 'Su mensaje para los nuevos miembros. Puede usar bbcode aquí'; -$a->strings['Add a link to global support forum'] = 'Añadir un enlace al foro de soporte global'; -$a->strings['Should a link to the global support forum be displayed?'] = '¿Debería mostrarse un enlace al foro de soporte global?'; -$a->strings['Add a link to the local support forum'] = 'Añadir un enlace al foro de soporte local'; -$a->strings['If you have a local support forum and want to have a link displayed in the widget, check this box.'] = 'Si tiene foro de soporte local y desea que se muestre un enlace en el widget, marque esta casilla.'; $a->strings['Name of the local support group'] = 'Nombre del grupo de soporte local'; $a->strings['If you checked the above, specify the nickname of the local support group here (i.e. helpers)'] = 'Si chequeó arriba, especifique el apodo del grupo de soporte local aquí (asistentes)'; diff --git a/newmemberwidget/lang/et/messages.po b/newmemberwidget/lang/et/messages.po index 969efad95..6f52dff8a 100644 --- a/newmemberwidget/lang/et/messages.po +++ b/newmemberwidget/lang/et/messages.po @@ -9,67 +9,67 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-06-01 14:12+0200\n" -"PO-Revision-Date: 2019-04-16 05:07+0000\n" -"Last-Translator: Rain Hawk\n" -"Language-Team: Estonian (http://www.transifex.com/Friendica/friendica/language/et/)\n" +"POT-Creation-Date: 2023-06-03 15:50-0400\n" +"PO-Revision-Date: 2014-06-23 10:26+0000\n" +"Last-Translator: Rain Hawk, 2019\n" +"Language-Team: Estonian (http://app.transifex.com/Friendica/friendica/language/et/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: et\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: newmemberwidget.php:21 +#: newmemberwidget.php:29 msgid "New Member" msgstr "Uus liige" -#: newmemberwidget.php:22 +#: newmemberwidget.php:30 msgid "Tips for New Members" msgstr "Nippe uutele liikmetele" -#: newmemberwidget.php:24 -msgid "Global Support Forum" -msgstr "Globaalne tugifoorum" +#: newmemberwidget.php:33 +msgid "Global Support Group" +msgstr "" -#: newmemberwidget.php:26 -msgid "Local Support Forum" -msgstr "Lokaalne tugifoorum" +#: newmemberwidget.php:37 +msgid "Local Support Group" +msgstr "" -#: newmemberwidget.php:49 +#: newmemberwidget.php:62 msgid "Save Settings" msgstr "Salvesta sätted" -#: newmemberwidget.php:50 +#: newmemberwidget.php:63 msgid "Message" msgstr "Sõnum" -#: newmemberwidget.php:50 +#: newmemberwidget.php:63 msgid "Your message for new members. You can use bbcode here." msgstr "" -#: newmemberwidget.php:51 -msgid "Add a link to global support forum" +#: newmemberwidget.php:64 +msgid "Add a link to global support group" msgstr "" -#: newmemberwidget.php:51 -msgid "Should a link to the global support forum be displayed?" +#: newmemberwidget.php:64 +msgid "Should a link to the global support group be displayed?" msgstr "" -#: newmemberwidget.php:52 -msgid "Add a link to the local support forum" +#: newmemberwidget.php:65 +msgid "Add a link to the local support group" msgstr "" -#: newmemberwidget.php:52 +#: newmemberwidget.php:65 msgid "" -"If you have a local support forum and wand to have a link displayed in the " +"If you have a local support group and want to have a link displayed in the " "widget, check this box." msgstr "" -#: newmemberwidget.php:53 +#: newmemberwidget.php:66 msgid "Name of the local support group" msgstr "" -#: newmemberwidget.php:53 +#: newmemberwidget.php:66 msgid "" "If you checked the above, specify the nickname of the local support" " group here (i.e. helpers)" diff --git a/newmemberwidget/lang/et/strings.php b/newmemberwidget/lang/et/strings.php index 3d4f81679..e4465d993 100644 --- a/newmemberwidget/lang/et/strings.php +++ b/newmemberwidget/lang/et/strings.php @@ -7,7 +7,5 @@ function string_plural_select_et($n){ }} $a->strings['New Member'] = 'Uus liige'; $a->strings['Tips for New Members'] = 'Nippe uutele liikmetele'; -$a->strings['Global Support Forum'] = 'Globaalne tugifoorum'; -$a->strings['Local Support Forum'] = 'Lokaalne tugifoorum'; $a->strings['Save Settings'] = 'Salvesta sätted'; $a->strings['Message'] = 'Sõnum'; diff --git a/newmemberwidget/lang/fr/messages.po b/newmemberwidget/lang/fr/messages.po index 296c2755c..3e1f2505c 100644 --- a/newmemberwidget/lang/fr/messages.po +++ b/newmemberwidget/lang/fr/messages.po @@ -4,6 +4,7 @@ # # # Translators: +# Florent C., 2023 # Hypolite Petovan , 2022 # Nicolas Derive, 2022 # StefOfficiel , 2015 @@ -11,10 +12,10 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-02-01 18:15+0100\n" +"POT-Creation-Date: 2023-06-03 15:50-0400\n" "PO-Revision-Date: 2014-06-23 10:26+0000\n" -"Last-Translator: Nicolas Derive, 2022\n" -"Language-Team: French (http://www.transifex.com/Friendica/friendica/language/fr/)\n" +"Last-Translator: Florent C., 2023\n" +"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -30,48 +31,48 @@ msgid "Tips for New Members" msgstr "Conseils aux nouveaux venus" #: newmemberwidget.php:33 -msgid "Global Support Forum" -msgstr "Forum de support global" +msgid "Global Support Group" +msgstr "Groupe de support global" #: newmemberwidget.php:37 -msgid "Local Support Forum" -msgstr "Forum de support local" +msgid "Local Support Group" +msgstr "Groupe de support local" -#: newmemberwidget.php:65 +#: newmemberwidget.php:62 msgid "Save Settings" msgstr "Enregistrer les paramètres" -#: newmemberwidget.php:66 +#: newmemberwidget.php:63 msgid "Message" msgstr "Message" -#: newmemberwidget.php:66 +#: newmemberwidget.php:63 msgid "Your message for new members. You can use bbcode here." msgstr "Votre messages aux nouveaux venus. Vous pouvez utiliser des BBCodes." -#: newmemberwidget.php:67 -msgid "Add a link to global support forum" -msgstr "Ajouter un lien vers le forum de support global" +#: newmemberwidget.php:64 +msgid "Add a link to global support group" +msgstr "Ajouter un lien vers le groupe de support global" -#: newmemberwidget.php:67 -msgid "Should a link to the global support forum be displayed?" -msgstr "Montrer un lien vers le forum de support global?" +#: newmemberwidget.php:64 +msgid "Should a link to the global support group be displayed?" +msgstr "Montrer un lien vers le groupe de support global ?" -#: newmemberwidget.php:68 -msgid "Add a link to the local support forum" -msgstr "Ajouter un lien vers le forum de support local" +#: newmemberwidget.php:65 +msgid "Add a link to the local support group" +msgstr "Ajouter un lien vers le groupe de support local" -#: newmemberwidget.php:68 +#: newmemberwidget.php:65 msgid "" -"If you have a local support forum and want to have a link displayed in the " +"If you have a local support group and want to have a link displayed in the " "widget, check this box." -msgstr "Si vous avez un forum d'assistance local et désirez avoir un lien affiché dans l'appliquette/widget, cochez cette case." +msgstr "Si vous avez un groupe de support local et désirez avoir un lien affiché dans l'appliquette/widget, cochez cette case." -#: newmemberwidget.php:69 +#: newmemberwidget.php:66 msgid "Name of the local support group" msgstr "Nom du groupe de support local" -#: newmemberwidget.php:69 +#: newmemberwidget.php:66 msgid "" "If you checked the above, specify the nickname of the local support" " group here (i.e. helpers)" diff --git a/newmemberwidget/lang/fr/strings.php b/newmemberwidget/lang/fr/strings.php index 8de178f20..cc437f897 100644 --- a/newmemberwidget/lang/fr/strings.php +++ b/newmemberwidget/lang/fr/strings.php @@ -7,14 +7,14 @@ function string_plural_select_fr($n){ }} $a->strings['New Member'] = 'Nouveau Membre'; $a->strings['Tips for New Members'] = 'Conseils aux nouveaux venus'; -$a->strings['Global Support Forum'] = 'Forum de support global'; -$a->strings['Local Support Forum'] = 'Forum de support local'; +$a->strings['Global Support Group'] = 'Groupe de support global'; +$a->strings['Local Support Group'] = 'Groupe de support local'; $a->strings['Save Settings'] = 'Enregistrer les paramètres'; $a->strings['Message'] = 'Message'; $a->strings['Your message for new members. You can use bbcode here.'] = 'Votre messages aux nouveaux venus. Vous pouvez utiliser des BBCodes.'; -$a->strings['Add a link to global support forum'] = 'Ajouter un lien vers le forum de support global'; -$a->strings['Should a link to the global support forum be displayed?'] = 'Montrer un lien vers le forum de support global?'; -$a->strings['Add a link to the local support forum'] = 'Ajouter un lien vers le forum de support local'; -$a->strings['If you have a local support forum and want to have a link displayed in the widget, check this box.'] = 'Si vous avez un forum d\'assistance local et désirez avoir un lien affiché dans l\'appliquette/widget, cochez cette case.'; +$a->strings['Add a link to global support group'] = 'Ajouter un lien vers le groupe de support global'; +$a->strings['Should a link to the global support group be displayed?'] = 'Montrer un lien vers le groupe de support global ?'; +$a->strings['Add a link to the local support group'] = 'Ajouter un lien vers le groupe de support local'; +$a->strings['If you have a local support group and want to have a link displayed in the widget, check this box.'] = 'Si vous avez un groupe de support local et désirez avoir un lien affiché dans l\'appliquette/widget, cochez cette case.'; $a->strings['Name of the local support group'] = 'Nom du groupe de support local'; $a->strings['If you checked the above, specify the nickname of the local support group here (i.e. helpers)'] = 'Si vous avez coché la case ci-dessus, spécifiez le nom d\'utilisateur du groupe de support local (par ex. "helpers")'; diff --git a/newmemberwidget/lang/hu/messages.po b/newmemberwidget/lang/hu/messages.po index 41453463d..f3babd21b 100644 --- a/newmemberwidget/lang/hu/messages.po +++ b/newmemberwidget/lang/hu/messages.po @@ -4,15 +4,15 @@ # # # Translators: -# Balázs Úr, 2020-2021 +# Balázs Úr, 2020-2021,2023 msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-02-01 18:15+0100\n" +"POT-Creation-Date: 2023-06-03 15:50-0400\n" "PO-Revision-Date: 2014-06-23 10:26+0000\n" -"Last-Translator: Balázs Úr, 2020-2021\n" -"Language-Team: Hungarian (http://www.transifex.com/Friendica/friendica/language/hu/)\n" +"Last-Translator: Balázs Úr, 2020-2021,2023\n" +"Language-Team: Hungarian (http://app.transifex.com/Friendica/friendica/language/hu/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -28,48 +28,48 @@ msgid "Tips for New Members" msgstr "Tippek új tagoknak" #: newmemberwidget.php:33 -msgid "Global Support Forum" -msgstr "Globális támogató fórum" +msgid "Global Support Group" +msgstr "Globális támogatási csoport" #: newmemberwidget.php:37 -msgid "Local Support Forum" -msgstr "Helyi támogató fórum" +msgid "Local Support Group" +msgstr "Helyi támogatási csoport" -#: newmemberwidget.php:65 +#: newmemberwidget.php:62 msgid "Save Settings" msgstr "Beállítások mentése" -#: newmemberwidget.php:66 +#: newmemberwidget.php:63 msgid "Message" msgstr "Üzenet" -#: newmemberwidget.php:66 +#: newmemberwidget.php:63 msgid "Your message for new members. You can use bbcode here." msgstr "Az Ön üzenete az új tagoknak. Itt használhat BBCode-ot." -#: newmemberwidget.php:67 -msgid "Add a link to global support forum" -msgstr "A globális támogató fórumra mutató hivatkozás hozzáadása" +#: newmemberwidget.php:64 +msgid "Add a link to global support group" +msgstr "A globális támogatási csoportra mutató hivatkozás hozzáadása" -#: newmemberwidget.php:67 -msgid "Should a link to the global support forum be displayed?" -msgstr "Meg kell jeleníteni a globális támogató fórumra mutató hivatkozást?" +#: newmemberwidget.php:64 +msgid "Should a link to the global support group be displayed?" +msgstr "Meg kell jeleníteni a globális támogatási csoportra mutató hivatkozást?" -#: newmemberwidget.php:68 -msgid "Add a link to the local support forum" -msgstr "A helyi támogató fórumra mutató hivatkozás hozzáadása" +#: newmemberwidget.php:65 +msgid "Add a link to the local support group" +msgstr "A helyi támogatási csoportra mutató hivatkozás hozzáadása" -#: newmemberwidget.php:68 +#: newmemberwidget.php:65 msgid "" -"If you have a local support forum and want to have a link displayed in the " +"If you have a local support group and want to have a link displayed in the " "widget, check this box." -msgstr "Ha van helyi támogató fóruma és szeretne egy hivatkozást megjeleníteni a felületi elemben, akkor jelölje be azt a négyzetet." +msgstr "Ha van helyi támogatási csoportja és meg szeretne jeleníteni egy hivatkozást a felületi elemben, akkor jelölje be ezt a négyzetet." -#: newmemberwidget.php:69 +#: newmemberwidget.php:66 msgid "Name of the local support group" msgstr "A helyi támogató csoport neve" -#: newmemberwidget.php:69 +#: newmemberwidget.php:66 msgid "" "If you checked the above, specify the nickname of the local support" " group here (i.e. helpers)" diff --git a/newmemberwidget/lang/hu/strings.php b/newmemberwidget/lang/hu/strings.php index edf2a0034..2f0066cd8 100644 --- a/newmemberwidget/lang/hu/strings.php +++ b/newmemberwidget/lang/hu/strings.php @@ -7,14 +7,14 @@ function string_plural_select_hu($n){ }} $a->strings['New Member'] = 'Új tag'; $a->strings['Tips for New Members'] = 'Tippek új tagoknak'; -$a->strings['Global Support Forum'] = 'Globális támogató fórum'; -$a->strings['Local Support Forum'] = 'Helyi támogató fórum'; +$a->strings['Global Support Group'] = 'Globális támogatási csoport'; +$a->strings['Local Support Group'] = 'Helyi támogatási csoport'; $a->strings['Save Settings'] = 'Beállítások mentése'; $a->strings['Message'] = 'Üzenet'; $a->strings['Your message for new members. You can use bbcode here.'] = 'Az Ön üzenete az új tagoknak. Itt használhat BBCode-ot.'; -$a->strings['Add a link to global support forum'] = 'A globális támogató fórumra mutató hivatkozás hozzáadása'; -$a->strings['Should a link to the global support forum be displayed?'] = 'Meg kell jeleníteni a globális támogató fórumra mutató hivatkozást?'; -$a->strings['Add a link to the local support forum'] = 'A helyi támogató fórumra mutató hivatkozás hozzáadása'; -$a->strings['If you have a local support forum and want to have a link displayed in the widget, check this box.'] = 'Ha van helyi támogató fóruma és szeretne egy hivatkozást megjeleníteni a felületi elemben, akkor jelölje be azt a négyzetet.'; +$a->strings['Add a link to global support group'] = 'A globális támogatási csoportra mutató hivatkozás hozzáadása'; +$a->strings['Should a link to the global support group be displayed?'] = 'Meg kell jeleníteni a globális támogatási csoportra mutató hivatkozást?'; +$a->strings['Add a link to the local support group'] = 'A helyi támogatási csoportra mutató hivatkozás hozzáadása'; +$a->strings['If you have a local support group and want to have a link displayed in the widget, check this box.'] = 'Ha van helyi támogatási csoportja és meg szeretne jeleníteni egy hivatkozást a felületi elemben, akkor jelölje be ezt a négyzetet.'; $a->strings['Name of the local support group'] = 'A helyi támogató csoport neve'; $a->strings['If you checked the above, specify the nickname of the local support group here (i.e. helpers)'] = 'Ha bejelölte a fentit, akkor itt adja meg a helyi támogató csoport becenevét (például segítők)'; diff --git a/newmemberwidget/lang/it/messages.po b/newmemberwidget/lang/it/messages.po index 389d73376..91d5c03e2 100644 --- a/newmemberwidget/lang/it/messages.po +++ b/newmemberwidget/lang/it/messages.po @@ -10,7 +10,7 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-02-01 18:15+0100\n" +"POT-Creation-Date: 2023-06-03 15:50-0400\n" "PO-Revision-Date: 2014-06-23 10:26+0000\n" "Last-Translator: Sylke Vicious , 2020-2021\n" "Language-Team: Italian (http://app.transifex.com/Friendica/friendica/language/it/)\n" @@ -29,48 +29,48 @@ msgid "Tips for New Members" msgstr "Consigli per i Nuovi Utenti" #: newmemberwidget.php:33 -msgid "Global Support Forum" -msgstr "Forum Globale di Supporto" +msgid "Global Support Group" +msgstr "" #: newmemberwidget.php:37 -msgid "Local Support Forum" -msgstr "Forum Locale di Supporto" +msgid "Local Support Group" +msgstr "" -#: newmemberwidget.php:65 +#: newmemberwidget.php:62 msgid "Save Settings" msgstr "Salva Impostazioni" -#: newmemberwidget.php:66 +#: newmemberwidget.php:63 msgid "Message" msgstr "Messaggio" -#: newmemberwidget.php:66 +#: newmemberwidget.php:63 msgid "Your message for new members. You can use bbcode here." msgstr "Il tuo messaggio per i nuovi utenti. Puoi usare BBCode" -#: newmemberwidget.php:67 -msgid "Add a link to global support forum" -msgstr "Aggiunge un collegamento al forum di supporto globale" +#: newmemberwidget.php:64 +msgid "Add a link to global support group" +msgstr "" -#: newmemberwidget.php:67 -msgid "Should a link to the global support forum be displayed?" -msgstr "Mostrare il collegamento al forum di supporto globale?" +#: newmemberwidget.php:64 +msgid "Should a link to the global support group be displayed?" +msgstr "" -#: newmemberwidget.php:68 -msgid "Add a link to the local support forum" -msgstr "Aggiunge un collegamento al forum di supporto locale" +#: newmemberwidget.php:65 +msgid "Add a link to the local support group" +msgstr "" -#: newmemberwidget.php:68 +#: newmemberwidget.php:65 msgid "" -"If you have a local support forum and want to have a link displayed in the " +"If you have a local support group and want to have a link displayed in the " "widget, check this box." -msgstr "Se hai un forum di supporto locale e vuoi che sia mostrato il collegamento nel widget, seleziona questo box." +msgstr "" -#: newmemberwidget.php:69 +#: newmemberwidget.php:66 msgid "Name of the local support group" msgstr "Nome del gruppo locale di supporto" -#: newmemberwidget.php:69 +#: newmemberwidget.php:66 msgid "" "If you checked the above, specify the nickname of the local support" " group here (i.e. helpers)" diff --git a/newmemberwidget/lang/it/strings.php b/newmemberwidget/lang/it/strings.php index f459f79e3..56798c2a7 100644 --- a/newmemberwidget/lang/it/strings.php +++ b/newmemberwidget/lang/it/strings.php @@ -7,14 +7,8 @@ function string_plural_select_it($n){ }} $a->strings['New Member'] = 'Nuovi Utenti'; $a->strings['Tips for New Members'] = 'Consigli per i Nuovi Utenti'; -$a->strings['Global Support Forum'] = 'Forum Globale di Supporto'; -$a->strings['Local Support Forum'] = 'Forum Locale di Supporto'; $a->strings['Save Settings'] = 'Salva Impostazioni'; $a->strings['Message'] = 'Messaggio'; $a->strings['Your message for new members. You can use bbcode here.'] = 'Il tuo messaggio per i nuovi utenti. Puoi usare BBCode'; -$a->strings['Add a link to global support forum'] = 'Aggiunge un collegamento al forum di supporto globale'; -$a->strings['Should a link to the global support forum be displayed?'] = 'Mostrare il collegamento al forum di supporto globale?'; -$a->strings['Add a link to the local support forum'] = 'Aggiunge un collegamento al forum di supporto locale'; -$a->strings['If you have a local support forum and want to have a link displayed in the widget, check this box.'] = 'Se hai un forum di supporto locale e vuoi che sia mostrato il collegamento nel widget, seleziona questo box.'; $a->strings['Name of the local support group'] = 'Nome del gruppo locale di supporto'; $a->strings['If you checked the above, specify the nickname of the local support group here (i.e. helpers)'] = 'Se hai selezionato il box sopra, specifica qui il nome utente del gruppo locale di supporto (e.s. \'supporto\')'; diff --git a/newmemberwidget/lang/pl/messages.po b/newmemberwidget/lang/pl/messages.po index 3f1838b51..90dda1ffb 100644 --- a/newmemberwidget/lang/pl/messages.po +++ b/newmemberwidget/lang/pl/messages.po @@ -10,10 +10,10 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-02-01 18:15+0100\n" +"POT-Creation-Date: 2023-06-03 15:50-0400\n" "PO-Revision-Date: 2014-06-23 10:26+0000\n" "Last-Translator: Piotr Strębski , 2022\n" -"Language-Team: Polish (http://www.transifex.com/Friendica/friendica/language/pl/)\n" +"Language-Team: Polish (http://app.transifex.com/Friendica/friendica/language/pl/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -29,48 +29,48 @@ msgid "Tips for New Members" msgstr "Wskazówki dla nowych użytkowników" #: newmemberwidget.php:33 -msgid "Global Support Forum" -msgstr "Globalne forum pomocy technicznej" +msgid "Global Support Group" +msgstr "" #: newmemberwidget.php:37 -msgid "Local Support Forum" -msgstr "Lokalne Forum Wsparcia" +msgid "Local Support Group" +msgstr "" -#: newmemberwidget.php:65 +#: newmemberwidget.php:62 msgid "Save Settings" msgstr "Zapisz ustawienia" -#: newmemberwidget.php:66 +#: newmemberwidget.php:63 msgid "Message" msgstr "Wiadomość" -#: newmemberwidget.php:66 +#: newmemberwidget.php:63 msgid "Your message for new members. You can use bbcode here." msgstr "Twoja wiadomość dla nowych członków. Możesz tutaj użyć bbcode." -#: newmemberwidget.php:67 -msgid "Add a link to global support forum" -msgstr "Dodaj odnośnik do globalnego forum pomocy technicznej" +#: newmemberwidget.php:64 +msgid "Add a link to global support group" +msgstr "" -#: newmemberwidget.php:67 -msgid "Should a link to the global support forum be displayed?" -msgstr "Czy powinien być wyświetlany odnośnik do globalnego forum pomocy technicznej?" +#: newmemberwidget.php:64 +msgid "Should a link to the global support group be displayed?" +msgstr "" -#: newmemberwidget.php:68 -msgid "Add a link to the local support forum" -msgstr "Dodaj odnośnik do lokalnego forum pomocy technicznej" +#: newmemberwidget.php:65 +msgid "Add a link to the local support group" +msgstr "" -#: newmemberwidget.php:68 +#: newmemberwidget.php:65 msgid "" -"If you have a local support forum and want to have a link displayed in the " +"If you have a local support group and want to have a link displayed in the " "widget, check this box." -msgstr "Jeżeli masz lokalne wsparcie forum i chcesz mieć łącze wyświetlane w widżecie, zaznacz to pole wyboru." +msgstr "" -#: newmemberwidget.php:69 +#: newmemberwidget.php:66 msgid "Name of the local support group" msgstr "Nazwa grupy lokalnej pomocy technicznej" -#: newmemberwidget.php:69 +#: newmemberwidget.php:66 msgid "" "If you checked the above, specify the nickname of the local support" " group here (i.e. helpers)" diff --git a/newmemberwidget/lang/pl/strings.php b/newmemberwidget/lang/pl/strings.php index 97103add2..22a9e9a92 100644 --- a/newmemberwidget/lang/pl/strings.php +++ b/newmemberwidget/lang/pl/strings.php @@ -7,14 +7,8 @@ function string_plural_select_pl($n){ }} $a->strings['New Member'] = 'Nowy użytkownik'; $a->strings['Tips for New Members'] = 'Wskazówki dla nowych użytkowników'; -$a->strings['Global Support Forum'] = 'Globalne forum pomocy technicznej'; -$a->strings['Local Support Forum'] = 'Lokalne Forum Wsparcia'; $a->strings['Save Settings'] = 'Zapisz ustawienia'; $a->strings['Message'] = 'Wiadomość'; $a->strings['Your message for new members. You can use bbcode here.'] = 'Twoja wiadomość dla nowych członków. Możesz tutaj użyć bbcode.'; -$a->strings['Add a link to global support forum'] = 'Dodaj odnośnik do globalnego forum pomocy technicznej'; -$a->strings['Should a link to the global support forum be displayed?'] = 'Czy powinien być wyświetlany odnośnik do globalnego forum pomocy technicznej?'; -$a->strings['Add a link to the local support forum'] = 'Dodaj odnośnik do lokalnego forum pomocy technicznej'; -$a->strings['If you have a local support forum and want to have a link displayed in the widget, check this box.'] = 'Jeżeli masz lokalne wsparcie forum i chcesz mieć łącze wyświetlane w widżecie, zaznacz to pole wyboru.'; $a->strings['Name of the local support group'] = 'Nazwa grupy lokalnej pomocy technicznej'; $a->strings['If you checked the above, specify the nickname of the local support group here (i.e. helpers)'] = 'Jeśli zaznaczyłeś powyższe, określ tutaj pseudonim lokalnej grupy wsparcia (np. Pomocnicy)'; diff --git a/newmemberwidget/lang/ru/messages.po b/newmemberwidget/lang/ru/messages.po index 94d61e3f9..1fe611e91 100644 --- a/newmemberwidget/lang/ru/messages.po +++ b/newmemberwidget/lang/ru/messages.po @@ -9,67 +9,67 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-06-01 14:12+0200\n" -"PO-Revision-Date: 2020-04-23 14:23+0000\n" -"Last-Translator: Alexander An \n" -"Language-Team: Russian (http://www.transifex.com/Friendica/friendica/language/ru/)\n" +"POT-Creation-Date: 2023-06-03 15:50-0400\n" +"PO-Revision-Date: 2014-06-23 10:26+0000\n" +"Last-Translator: Alexander An , 2020\n" +"Language-Team: Russian (http://app.transifex.com/Friendica/friendica/language/ru/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ru\n" "Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);\n" -#: newmemberwidget.php:21 +#: newmemberwidget.php:29 msgid "New Member" msgstr "Новичок" -#: newmemberwidget.php:22 +#: newmemberwidget.php:30 msgid "Tips for New Members" msgstr "Советы новичкам" -#: newmemberwidget.php:24 -msgid "Global Support Forum" -msgstr "Общий форум поддержки" +#: newmemberwidget.php:33 +msgid "Global Support Group" +msgstr "" -#: newmemberwidget.php:26 -msgid "Local Support Forum" -msgstr "Местный форум поддержки" +#: newmemberwidget.php:37 +msgid "Local Support Group" +msgstr "" -#: newmemberwidget.php:49 +#: newmemberwidget.php:62 msgid "Save Settings" msgstr "Сохранить настройки" -#: newmemberwidget.php:50 +#: newmemberwidget.php:63 msgid "Message" msgstr "Сообщение" -#: newmemberwidget.php:50 +#: newmemberwidget.php:63 msgid "Your message for new members. You can use bbcode here." msgstr "Ваше сообщение новичкам. Вы можете использовать BBCode." -#: newmemberwidget.php:51 -msgid "Add a link to global support forum" -msgstr "Добавить ссылку на общий форум поддержки" +#: newmemberwidget.php:64 +msgid "Add a link to global support group" +msgstr "" -#: newmemberwidget.php:51 -msgid "Should a link to the global support forum be displayed?" -msgstr "Показывать ссылку на общий форум поддержки?" +#: newmemberwidget.php:64 +msgid "Should a link to the global support group be displayed?" +msgstr "" -#: newmemberwidget.php:52 -msgid "Add a link to the local support forum" -msgstr "Добавить ссылку на местный форум поддержки" +#: newmemberwidget.php:65 +msgid "Add a link to the local support group" +msgstr "" -#: newmemberwidget.php:52 +#: newmemberwidget.php:65 msgid "" -"If you have a local support forum and wand to have a link displayed in the " +"If you have a local support group and want to have a link displayed in the " "widget, check this box." -msgstr "Если у вас есть местный форум поддержки и вы хотите добавить ссылку на него, включите это." +msgstr "" -#: newmemberwidget.php:53 +#: newmemberwidget.php:66 msgid "Name of the local support group" msgstr "Название местной группы поддержки" -#: newmemberwidget.php:53 +#: newmemberwidget.php:66 msgid "" "If you checked the above, specify the nickname of the local support" " group here (i.e. helpers)" diff --git a/newmemberwidget/lang/ru/strings.php b/newmemberwidget/lang/ru/strings.php index 7992e64b1..6f27bb1a4 100644 --- a/newmemberwidget/lang/ru/strings.php +++ b/newmemberwidget/lang/ru/strings.php @@ -7,14 +7,8 @@ function string_plural_select_ru($n){ }} $a->strings['New Member'] = 'Новичок'; $a->strings['Tips for New Members'] = 'Советы новичкам'; -$a->strings['Global Support Forum'] = 'Общий форум поддержки'; -$a->strings['Local Support Forum'] = 'Местный форум поддержки'; $a->strings['Save Settings'] = 'Сохранить настройки'; $a->strings['Message'] = 'Сообщение'; $a->strings['Your message for new members. You can use bbcode here.'] = 'Ваше сообщение новичкам. Вы можете использовать BBCode.'; -$a->strings['Add a link to global support forum'] = 'Добавить ссылку на общий форум поддержки'; -$a->strings['Should a link to the global support forum be displayed?'] = 'Показывать ссылку на общий форум поддержки?'; -$a->strings['Add a link to the local support forum'] = 'Добавить ссылку на местный форум поддержки'; -$a->strings['If you have a local support forum and wand to have a link displayed in the widget, check this box.'] = 'Если у вас есть местный форум поддержки и вы хотите добавить ссылку на него, включите это.'; $a->strings['Name of the local support group'] = 'Название местной группы поддержки'; $a->strings['If you checked the above, specify the nickname of the local support group here (i.e. helpers)'] = 'Если вы включили настройку выше, укажите никместной группы поддержки пользователей.'; diff --git a/newmemberwidget/lang/sv/messages.po b/newmemberwidget/lang/sv/messages.po index 0d6171b2e..a1a6167af 100644 --- a/newmemberwidget/lang/sv/messages.po +++ b/newmemberwidget/lang/sv/messages.po @@ -9,10 +9,10 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-02-01 18:15+0100\n" -"PO-Revision-Date: 2022-01-16 00:48+0000\n" -"Last-Translator: Kristoffer Grundström \n" -"Language-Team: Swedish (http://www.transifex.com/Friendica/friendica/language/sv/)\n" +"POT-Creation-Date: 2023-06-03 15:50-0400\n" +"PO-Revision-Date: 2014-06-23 10:26+0000\n" +"Last-Translator: Kristoffer Grundström , 2022\n" +"Language-Team: Swedish (http://app.transifex.com/Friendica/friendica/language/sv/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -28,48 +28,48 @@ msgid "Tips for New Members" msgstr "Tips för nya medlemmar" #: newmemberwidget.php:33 -msgid "Global Support Forum" +msgid "Global Support Group" msgstr "" #: newmemberwidget.php:37 -msgid "Local Support Forum" -msgstr "Lokalt hjälpforum" +msgid "Local Support Group" +msgstr "" -#: newmemberwidget.php:65 +#: newmemberwidget.php:62 msgid "Save Settings" msgstr "Spara inställningar" -#: newmemberwidget.php:66 +#: newmemberwidget.php:63 msgid "Message" msgstr "Meddelande" -#: newmemberwidget.php:66 +#: newmemberwidget.php:63 msgid "Your message for new members. You can use bbcode here." msgstr "" -#: newmemberwidget.php:67 -msgid "Add a link to global support forum" +#: newmemberwidget.php:64 +msgid "Add a link to global support group" msgstr "" -#: newmemberwidget.php:67 -msgid "Should a link to the global support forum be displayed?" +#: newmemberwidget.php:64 +msgid "Should a link to the global support group be displayed?" msgstr "" -#: newmemberwidget.php:68 -msgid "Add a link to the local support forum" +#: newmemberwidget.php:65 +msgid "Add a link to the local support group" msgstr "" -#: newmemberwidget.php:68 +#: newmemberwidget.php:65 msgid "" -"If you have a local support forum and want to have a link displayed in the " +"If you have a local support group and want to have a link displayed in the " "widget, check this box." msgstr "" -#: newmemberwidget.php:69 +#: newmemberwidget.php:66 msgid "Name of the local support group" msgstr "" -#: newmemberwidget.php:69 +#: newmemberwidget.php:66 msgid "" "If you checked the above, specify the nickname of the local support" " group here (i.e. helpers)" diff --git a/newmemberwidget/lang/sv/strings.php b/newmemberwidget/lang/sv/strings.php index 38292306a..e92a428ff 100644 --- a/newmemberwidget/lang/sv/strings.php +++ b/newmemberwidget/lang/sv/strings.php @@ -7,6 +7,5 @@ function string_plural_select_sv($n){ }} $a->strings['New Member'] = 'Ny medlem'; $a->strings['Tips for New Members'] = 'Tips för nya medlemmar'; -$a->strings['Local Support Forum'] = 'Lokalt hjälpforum'; $a->strings['Save Settings'] = 'Spara inställningar'; $a->strings['Message'] = 'Meddelande'; diff --git a/nsfw/lang/fr/messages.po b/nsfw/lang/fr/messages.po index 5748f90a2..36fd22cc8 100644 --- a/nsfw/lang/fr/messages.po +++ b/nsfw/lang/fr/messages.po @@ -4,6 +4,7 @@ # # # Translators: +# Florent C., 2023 # Nicolas Derive, 2022-2023 # StefOfficiel , 2015 # Vincent Vindarel , 2018 @@ -13,7 +14,7 @@ msgstr "" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2022-12-10 14:42-0500\n" "PO-Revision-Date: 2014-06-23 10:34+0000\n" -"Last-Translator: Nicolas Derive, 2022-2023\n" +"Last-Translator: Florent C., 2023\n" "Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -41,7 +42,7 @@ msgstr "Liste de mots-clés - séparés par des virgules - à cacher" msgid "" "Use /expression/ to provide regular expressions, #tag to specfically match " "hashtags (case-insensitive), or regular words (case-sensitive)" -msgstr "Utiliser /expression/ pour fournir des expressions régulières, #tag pour correspondre à un mot-dièse (hashtag, insensible à la casse), ou des mots classiques (sensible à la casse)" +msgstr "Utiliser /expression/ pour fournir des expressions régulières, #tag pour correspondre à un tag (insensible à la casse), ou des mots classiques (sensible à la casse)" #: nsfw.php:72 msgid "Content Filter (NSFW and more)" @@ -55,7 +56,7 @@ msgstr "La compilation de l'expression régulière \"%s\" a échoué" #: nsfw.php:154 #, php-format msgid "Filtered tag: %s" -msgstr "Tag filtré: %s" +msgstr "Tag filtré : %s" #: nsfw.php:156 #, php-format diff --git a/nsfw/lang/fr/strings.php b/nsfw/lang/fr/strings.php index ee3734ec7..fc03d5ada 100644 --- a/nsfw/lang/fr/strings.php +++ b/nsfw/lang/fr/strings.php @@ -8,8 +8,8 @@ function string_plural_select_fr($n){ $a->strings['This addon searches for specified words/text in posts and collapses them. It can be used to filter content tagged with for instance #NSFW that may be deemed inappropriate at certain times or places, such as being at work. It is also useful for hiding irrelevant or annoying content from direct view.'] = 'Cette extension recherche des mots/textes spécifiés dans les publications et les masque. Elle peut être utilisée pour filtrer le contenu étiqueté par exemple avec #NSFW qui peut être considéré comme inapproprié à certains moments ou endroits, comme par exemple au travail. Elle est aussi utile pour cacher du contenu non pertinent ou ennuyeux d\'une vue directe.'; $a->strings['Enable Content filter'] = 'Activer le filtrage de contenu'; $a->strings['Comma separated list of keywords to hide'] = 'Liste de mots-clés - séparés par des virgules - à cacher'; -$a->strings['Use /expression/ to provide regular expressions, #tag to specfically match hashtags (case-insensitive), or regular words (case-sensitive)'] = 'Utiliser /expression/ pour fournir des expressions régulières, #tag pour correspondre à un mot-dièse (hashtag, insensible à la casse), ou des mots classiques (sensible à la casse)'; +$a->strings['Use /expression/ to provide regular expressions, #tag to specfically match hashtags (case-insensitive), or regular words (case-sensitive)'] = 'Utiliser /expression/ pour fournir des expressions régulières, #tag pour correspondre à un tag (insensible à la casse), ou des mots classiques (sensible à la casse)'; $a->strings['Content Filter (NSFW and more)'] = 'Filtre de contenu (NSFW et autres)'; $a->strings['Regular expression "%s" fails to compile'] = 'La compilation de l\'expression régulière "%s" a échoué'; -$a->strings['Filtered tag: %s'] = 'Tag filtré: %s'; +$a->strings['Filtered tag: %s'] = 'Tag filtré : %s'; $a->strings['Filtered word: %s'] = 'Mot filtré: %s'; diff --git a/piwik/lang/en-gb/strings.php b/piwik/lang/en-gb/strings.php index 4d7e37b87..ab46f8591 100644 --- a/piwik/lang/en-gb/strings.php +++ b/piwik/lang/en-gb/strings.php @@ -13,5 +13,5 @@ $a->strings['Absolute path to your Matomo (Piwik) installation. (without protoco $a->strings['Site ID'] = 'Site ID'; $a->strings['Show opt-out cookie link?'] = 'Show opt-out cookie link?'; $a->strings['Asynchronous tracking'] = 'Asynchronous tracking'; +$a->strings['Shortcut path to the script (\'/js/\' instead of \'/piwik.js\')'] = 'Shortcut path to the script (\'/js/\' instead of \'/piwik.js\')'; $a->strings['Settings updated.'] = 'Settings updated.'; -$a->strings["Shortcut path to the script ('/js/' instead of '/piwik.js')"] = "Shortcut path to the script ('/js/' instead of '/piwik.js')"; \ No newline at end of file diff --git a/piwik/lang/fr/messages.po b/piwik/lang/fr/messages.po index 8e832d79f..b8bf84ce0 100644 --- a/piwik/lang/fr/messages.po +++ b/piwik/lang/fr/messages.po @@ -4,6 +4,7 @@ # # # Translators: +# Florent C., 2023 # Hypolite Petovan , 2022 # Nicolas Derive, 2022 # ea1cd8241cb389ffb6f92bc6891eff5d_dc12308 <70dced5587d47e18d88f9298024d96f8_93383>, 2015 @@ -12,23 +13,23 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-02-01 18:15+0100\n" +"POT-Creation-Date: 2023-05-01 07:39+0200\n" "PO-Revision-Date: 2014-06-23 11:18+0000\n" -"Last-Translator: Nicolas Derive, 2022\n" -"Language-Team: French (http://www.transifex.com/Friendica/friendica/language/fr/)\n" +"Last-Translator: Florent C., 2023\n" +"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: fr\n" "Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" -#: piwik.php:87 +#: piwik.php:96 msgid "" "This website is tracked using the Matomo" " analytics tool." msgstr "Ce site Internet utilise Matomo pour mesurer son audience." -#: piwik.php:90 +#: piwik.php:99 #, php-format msgid "" "If you do not want that your visits are logged in this way you (opt-out)." msgstr "Si vous ne désirez pas que vos visites soient journalisées de cette manière, vous pouvez définir un cookie pour empêcher Matomo/Piwik de surveiller de prochaines visites sur le site (opt-out)" -#: piwik.php:97 +#: piwik.php:108 msgid "Save Settings" msgstr "Sauvegarder les paramètres" -#: piwik.php:98 +#: piwik.php:109 msgid "Matomo (Piwik) Base URL" msgstr "URL de base de Matomo (Piwik)" -#: piwik.php:98 +#: piwik.php:109 msgid "" "Absolute path to your Matomo (Piwik) installation. (without protocol " "(http/s), with trailing slash)" msgstr "Chemin absolu vers votre installation Matomo (Piwik) (sans protocole (http/s), avec un slash à la fin)." -#: piwik.php:99 +#: piwik.php:110 msgid "Site ID" msgstr "ID du site" -#: piwik.php:100 +#: piwik.php:111 msgid "Show opt-out cookie link?" msgstr "Montrer le lien d'opt-out pour les cookies ?" -#: piwik.php:101 +#: piwik.php:112 msgid "Asynchronous tracking" msgstr "Suivi asynchrone" + +#: piwik.php:113 +msgid "Shortcut path to the script ('/js/' instead of '/piwik.js')" +msgstr "Chemin réduit vers le script ('/js/' au lieu de '/piwik.js') " diff --git a/piwik/lang/fr/strings.php b/piwik/lang/fr/strings.php index 23899d0fb..3c150e019 100644 --- a/piwik/lang/fr/strings.php +++ b/piwik/lang/fr/strings.php @@ -13,3 +13,4 @@ $a->strings['Absolute path to your Matomo (Piwik) installation. (without protoco $a->strings['Site ID'] = 'ID du site'; $a->strings['Show opt-out cookie link?'] = 'Montrer le lien d\'opt-out pour les cookies ?'; $a->strings['Asynchronous tracking'] = 'Suivi asynchrone'; +$a->strings['Shortcut path to the script (\'/js/\' instead of \'/piwik.js\')'] = 'Chemin réduit vers le script (\'/js/\' au lieu de \'/piwik.js\') '; diff --git a/pumpio/lang/fr/messages.po b/pumpio/lang/fr/messages.po index 2966c49c4..22b987434 100644 --- a/pumpio/lang/fr/messages.po +++ b/pumpio/lang/fr/messages.po @@ -4,6 +4,7 @@ # # # Translators: +# Florent C., 2023 # Hypolite Petovan , 2022 # ea1cd8241cb389ffb6f92bc6891eff5d_dc12308 <70dced5587d47e18d88f9298024d96f8_93383>, 2015 # StefOfficiel , 2015 @@ -11,86 +12,86 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-21 19:17-0500\n" +"POT-Creation-Date: 2023-06-03 15:50-0400\n" "PO-Revision-Date: 2014-06-23 11:30+0000\n" -"Last-Translator: Hypolite Petovan , 2022\n" -"Language-Team: French (http://www.transifex.com/Friendica/friendica/language/fr/)\n" +"Last-Translator: Florent C., 2023\n" +"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: fr\n" "Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" -#: pumpio.php:57 +#: pumpio.php:62 msgid "Permission denied." msgstr "Permission refusée." -#: pumpio.php:152 +#: pumpio.php:156 #, php-format msgid "Unable to register the client at the pump.io server '%s'." msgstr "Impossible d'enregistrer le client sur le serveur pump.io \"%s\"." -#: pumpio.php:192 +#: pumpio.php:196 msgid "You are now authenticated to pumpio." msgstr "Vous êtes maintenant authentifié sur pump.io." -#: pumpio.php:193 +#: pumpio.php:197 msgid "return to the connector page" msgstr "Retourner à la page du connecteur" -#: pumpio.php:213 +#: pumpio.php:217 msgid "Post to pumpio" msgstr "Publier sur pump.io" -#: pumpio.php:237 +#: pumpio.php:241 msgid "Save Settings" msgstr "Sauvegarder les paramètres" -#: pumpio.php:239 +#: pumpio.php:243 msgid "Delete this preset" msgstr "Supprimer ce préréglage" -#: pumpio.php:245 +#: pumpio.php:249 msgid "Authenticate your pump.io connection" msgstr "Identifiez votre connexion à pump.io" -#: pumpio.php:252 +#: pumpio.php:256 msgid "Pump.io servername (without \"http://\" or \"https://\" )" msgstr "Domaine du serveur Pump.io (sans \"http://\" ou \"https://\")" -#: pumpio.php:253 +#: pumpio.php:257 msgid "Pump.io username (without the servername)" msgstr "Nom d'utilisateur Pump.io (sans le domaine de serveur)" -#: pumpio.php:254 +#: pumpio.php:258 msgid "Import the remote timeline" -msgstr "Importer la timeline distante" +msgstr "Importer le flux distant" -#: pumpio.php:255 +#: pumpio.php:259 msgid "Enable Pump.io Post Addon" msgstr "Activer l'extension Pump.io" -#: pumpio.php:256 +#: pumpio.php:260 msgid "Post to Pump.io by default" msgstr "Publier sur Pump.io par défaut" -#: pumpio.php:257 +#: pumpio.php:261 msgid "Should posts be public?" msgstr "Les messages devraient être publiques ?" -#: pumpio.php:258 +#: pumpio.php:262 msgid "Mirror all public posts" msgstr "Refléter toutes les publications publiques" -#: pumpio.php:263 +#: pumpio.php:267 msgid "Pump.io Import/Export/Mirror" msgstr "Import/Export/Miroir Pump.io" -#: pumpio.php:920 +#: pumpio.php:924 msgid "status" msgstr "statut" -#: pumpio.php:924 +#: pumpio.php:928 #, php-format msgid "%1$s likes %2$s's %3$s" msgstr "%1$s aime lea %3$s de %2$s" diff --git a/pumpio/lang/fr/strings.php b/pumpio/lang/fr/strings.php index bdbbc462f..14ddade19 100644 --- a/pumpio/lang/fr/strings.php +++ b/pumpio/lang/fr/strings.php @@ -15,7 +15,7 @@ $a->strings['Delete this preset'] = 'Supprimer ce préréglage'; $a->strings['Authenticate your pump.io connection'] = 'Identifiez votre connexion à pump.io'; $a->strings['Pump.io servername (without "http://" or "https://" )'] = 'Domaine du serveur Pump.io (sans "http://" ou "https://")'; $a->strings['Pump.io username (without the servername)'] = 'Nom d\'utilisateur Pump.io (sans le domaine de serveur)'; -$a->strings['Import the remote timeline'] = 'Importer la timeline distante'; +$a->strings['Import the remote timeline'] = 'Importer le flux distant'; $a->strings['Enable Pump.io Post Addon'] = 'Activer l\'extension Pump.io'; $a->strings['Post to Pump.io by default'] = 'Publier sur Pump.io par défaut'; $a->strings['Should posts be public?'] = 'Les messages devraient être publiques ?'; diff --git a/securemail/lang/fr/messages.po b/securemail/lang/fr/messages.po index bb15513d9..828d507b0 100644 --- a/securemail/lang/fr/messages.po +++ b/securemail/lang/fr/messages.po @@ -5,6 +5,7 @@ # # Translators: # Hypolite Petovan , 2022 +# Florent C., 2023 # #, fuzzy msgid "" @@ -13,8 +14,8 @@ msgstr "" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-11-21 19:16-0500\n" "PO-Revision-Date: 2018-03-20 07:26+0000\n" -"Last-Translator: Hypolite Petovan , 2022\n" -"Language-Team: French (https://www.transifex.com/Friendica/teams/12172/fr/)\n" +"Last-Translator: Florent C., 2023\n" +"Language-Team: French (https://app.transifex.com/Friendica/teams/12172/fr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -47,8 +48,8 @@ msgstr "Enregistrer et envoyer un message de test" #: securemail.php:93 msgid "Test email sent" -msgstr "Message de test envoyé avec succès" +msgstr "Courriel de test envoyé avec succès" #: securemail.php:95 msgid "There was an error sending the test email" -msgstr "Une erreur est survenue pendant l'envoi du message de test" +msgstr "Une erreur est survenue pendant l'envoi du courriel de test" diff --git a/securemail/lang/fr/strings.php b/securemail/lang/fr/strings.php index 91b8f1f2e..9d40a8e23 100644 --- a/securemail/lang/fr/strings.php +++ b/securemail/lang/fr/strings.php @@ -11,5 +11,5 @@ $a->strings['Your public PGP key, ascii armored format'] = 'Votre clé publique $a->strings['"Secure Mail" Settings'] = 'Paramètres des emails sécurisés'; $a->strings['Save Settings'] = 'Enregistrer les paramètres'; $a->strings['Save and send test'] = 'Enregistrer et envoyer un message de test'; -$a->strings['Test email sent'] = 'Message de test envoyé avec succès'; -$a->strings['There was an error sending the test email'] = 'Une erreur est survenue pendant l\'envoi du message de test'; +$a->strings['Test email sent'] = 'Courriel de test envoyé avec succès'; +$a->strings['There was an error sending the test email'] = 'Une erreur est survenue pendant l\'envoi du courriel de test'; diff --git a/showmore/lang/ru/messages.po b/showmore/lang/ru/messages.po index 2b4c74131..650269b28 100644 --- a/showmore/lang/ru/messages.po +++ b/showmore/lang/ru/messages.po @@ -4,41 +4,33 @@ # # # Translators: -# Alexander An , 2020 +# Alexander An , 2020,2023 msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-04-01 11:11-0400\n" -"PO-Revision-Date: 2020-04-23 14:25+0000\n" -"Last-Translator: Alexander An \n" -"Language-Team: Russian (http://www.transifex.com/Friendica/friendica/language/ru/)\n" +"POT-Creation-Date: 2021-11-21 19:16-0500\n" +"PO-Revision-Date: 2014-06-23 12:37+0000\n" +"Last-Translator: Alexander An , 2020,2023\n" +"Language-Team: Russian (http://app.transifex.com/Friendica/friendica/language/ru/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ru\n" "Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);\n" -#: showmore.php:41 showmore.php:45 -msgid "\"Show more\" Settings" -msgstr "Настройки \"показать ещё\"" - -#: showmore.php:50 +#: showmore.php:37 msgid "Enable Show More" msgstr "Включить \"показать ещё\"" -#: showmore.php:53 -msgid "Cutting posts after how much characters" +#: showmore.php:38 +msgid "Cutting posts after how many characters" msgstr "Обрезать записи после превышения этого числа символов" -#: showmore.php:57 -msgid "Save Settings" -msgstr "Сохранить настройки" +#: showmore.php:43 +msgid "\"Show more\" Settings" +msgstr "Настройки \"показать ещё\"" -#: showmore.php:74 -msgid "Show More Settings saved." -msgstr "Настройки сохранены." - -#: showmore.php:134 +#: showmore.php:119 msgid "show more" msgstr "показать ещё" diff --git a/showmore/lang/ru/strings.php b/showmore/lang/ru/strings.php index da3c94666..a12af848b 100644 --- a/showmore/lang/ru/strings.php +++ b/showmore/lang/ru/strings.php @@ -5,9 +5,7 @@ function string_plural_select_ru($n){ $n = intval($n); if ($n%10==1 && $n%100!=11) { return 0; } else if ($n%10>=2 && $n%10<=4 && ($n%100<12 || $n%100>14)) { return 1; } else if ($n%10==0 || ($n%10>=5 && $n%10<=9) || ($n%100>=11 && $n%100<=14)) { return 2; } else { return 3; } }} -$a->strings['"Show more" Settings'] = 'Настройки "показать ещё"'; $a->strings['Enable Show More'] = 'Включить "показать ещё"'; -$a->strings['Cutting posts after how much characters'] = 'Обрезать записи после превышения этого числа символов'; -$a->strings['Save Settings'] = 'Сохранить настройки'; -$a->strings['Show More Settings saved.'] = 'Настройки сохранены.'; +$a->strings['Cutting posts after how many characters'] = 'Обрезать записи после превышения этого числа символов'; +$a->strings['"Show more" Settings'] = 'Настройки "показать ещё"'; $a->strings['show more'] = 'показать ещё'; diff --git a/tumblr/lang/es/messages.po b/tumblr/lang/es/messages.po index 83f1d7bec..d78060c6a 100644 --- a/tumblr/lang/es/messages.po +++ b/tumblr/lang/es/messages.po @@ -10,64 +10,81 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-02-01 18:16+0100\n" -"PO-Revision-Date: 2021-04-06 02:11+0000\n" -"Last-Translator: Senex Petrovic \n" -"Language-Team: Spanish (http://www.transifex.com/Friendica/friendica/language/es/)\n" +"POT-Creation-Date: 2023-04-29 06:56+0000\n" +"PO-Revision-Date: 2014-06-23 12:58+0000\n" +"Last-Translator: Senex Petrovic , 2021\n" +"Language-Team: Spanish (http://app.transifex.com/Friendica/friendica/language/es/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: es\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" -#: tumblr.php:39 +#: tumblr.php:243 msgid "Permission denied." msgstr "Permiso denegado." -#: tumblr.php:69 tumblr.php:283 +#: tumblr.php:296 msgid "Save Settings" msgstr "Guardar ajustes" -#: tumblr.php:71 +#: tumblr.php:297 msgid "Consumer Key" msgstr "Consumer Key" -#: tumblr.php:72 +#: tumblr.php:298 msgid "Consumer Secret" msgstr "Consumer Secret" -#: tumblr.php:177 -msgid "You are now authenticated to tumblr." -msgstr "Está ahora autenticado en tumblr." +#: tumblr.php:299 +msgid "Maximum tags" +msgstr "" -#: tumblr.php:178 -msgid "return to the connector page" -msgstr "Vuelva a la página del conector" +#: tumblr.php:299 +msgid "" +"Maximum number of tags that a user can follow. Enter 0 to deactivate the " +"feature." +msgstr "" -#: tumblr.php:194 -msgid "Post to Tumblr" -msgstr "Publicar en Tumblr" - -#: tumblr.php:224 tumblr.php:228 -msgid "Tumblr Export" -msgstr "Exportar a Tumblr " - -#: tumblr.php:232 -msgid "(Re-)Authenticate your tumblr page" -msgstr "(Re-)autenticar su página de tumblr" - -#: tumblr.php:236 -msgid "Enable Tumblr Post Addon" -msgstr "Habilitar el complemento de publicación de Tumblr" - -#: tumblr.php:242 -msgid "Post to Tumblr by default" -msgstr "Publique en Tumblr por defecto" - -#: tumblr.php:263 +#: tumblr.php:336 msgid "Post to page:" msgstr "Publicar en página:" -#: tumblr.php:277 +#: tumblr.php:342 +msgid "(Re-)Authenticate your tumblr page" +msgstr "(Re-)autenticar su página de tumblr" + +#: tumblr.php:343 msgid "You are not authenticated to tumblr" msgstr "No está autenticado en tumblr" + +#: tumblr.php:348 +msgid "Enable Tumblr Post Addon" +msgstr "Habilitar el complemento de publicación de Tumblr" + +#: tumblr.php:349 +msgid "Post to Tumblr by default" +msgstr "Publique en Tumblr por defecto" + +#: tumblr.php:350 +msgid "Import the remote timeline" +msgstr "" + +#: tumblr.php:351 +msgid "Subscribed tags" +msgstr "" + +#: tumblr.php:351 +#, php-format +msgid "" +"Comma separated list of up to %d tags that will be imported additionally to " +"the timeline" +msgstr "" + +#: tumblr.php:357 +msgid "Tumblr Import/Export" +msgstr "" + +#: tumblr.php:375 +msgid "Post to Tumblr" +msgstr "Publicar en Tumblr" diff --git a/tumblr/lang/es/strings.php b/tumblr/lang/es/strings.php index a124729bd..550f6dc81 100644 --- a/tumblr/lang/es/strings.php +++ b/tumblr/lang/es/strings.php @@ -3,18 +3,15 @@ if(! function_exists("string_plural_select_es")) { function string_plural_select_es($n){ $n = intval($n); - return intval($n != 1); + if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } }} $a->strings['Permission denied.'] = 'Permiso denegado.'; $a->strings['Save Settings'] = 'Guardar ajustes'; $a->strings['Consumer Key'] = 'Consumer Key'; $a->strings['Consumer Secret'] = 'Consumer Secret'; -$a->strings['You are now authenticated to tumblr.'] = 'Está ahora autenticado en tumblr.'; -$a->strings['return to the connector page'] = 'Vuelva a la página del conector'; -$a->strings['Post to Tumblr'] = 'Publicar en Tumblr'; -$a->strings['Tumblr Export'] = 'Exportar a Tumblr '; +$a->strings['Post to page:'] = 'Publicar en página:'; $a->strings['(Re-)Authenticate your tumblr page'] = '(Re-)autenticar su página de tumblr'; +$a->strings['You are not authenticated to tumblr'] = 'No está autenticado en tumblr'; $a->strings['Enable Tumblr Post Addon'] = 'Habilitar el complemento de publicación de Tumblr'; $a->strings['Post to Tumblr by default'] = 'Publique en Tumblr por defecto'; -$a->strings['Post to page:'] = 'Publicar en página:'; -$a->strings['You are not authenticated to tumblr'] = 'No está autenticado en tumblr'; +$a->strings['Post to Tumblr'] = 'Publicar en Tumblr'; diff --git a/tumblr/lang/fr/messages.po b/tumblr/lang/fr/messages.po index 3e9fe83d1..ef2f0e3c7 100644 --- a/tumblr/lang/fr/messages.po +++ b/tumblr/lang/fr/messages.po @@ -5,69 +5,87 @@ # # Translators: # bob lebonche , 2021 +# Florent C., 2023 # StefOfficiel , 2015 msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-21 19:17-0500\n" +"POT-Creation-Date: 2023-04-29 06:56+0000\n" "PO-Revision-Date: 2014-06-23 12:58+0000\n" -"Last-Translator: bob lebonche , 2021\n" -"Language-Team: French (http://www.transifex.com/Friendica/friendica/language/fr/)\n" +"Last-Translator: Florent C., 2023\n" +"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: fr\n" "Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" -#: tumblr.php:39 +#: tumblr.php:243 msgid "Permission denied." msgstr "Permission refusée." -#: tumblr.php:69 +#: tumblr.php:296 msgid "Save Settings" msgstr "Sauvegarder les paramètres" -#: tumblr.php:71 +#: tumblr.php:297 msgid "Consumer Key" msgstr "Clé utilisateur" -#: tumblr.php:72 +#: tumblr.php:298 msgid "Consumer Secret" msgstr "Secret utilisateur" -#: tumblr.php:177 -msgid "You are now authenticated to tumblr." -msgstr "Vous êtes maintenant identifié sur Tumblr" +#: tumblr.php:299 +msgid "Maximum tags" +msgstr "Tags maximum" -#: tumblr.php:178 -msgid "return to the connector page" -msgstr "Revenir à la page de connexion" +#: tumblr.php:299 +msgid "" +"Maximum number of tags that a user can follow. Enter 0 to deactivate the " +"feature." +msgstr "Nombre maximum de tags qu'un utilisateur peut suivre. Entrez 0 pour désactiver cette fonctionnalité." -#: tumblr.php:194 -msgid "Post to Tumblr" -msgstr "Publier vers Tumblr" - -#: tumblr.php:225 +#: tumblr.php:336 msgid "Post to page:" msgstr "Publier sur la page :" -#: tumblr.php:231 +#: tumblr.php:342 msgid "(Re-)Authenticate your tumblr page" msgstr "(re)Authentifiez votre page Tumblr" -#: tumblr.php:232 +#: tumblr.php:343 msgid "You are not authenticated to tumblr" msgstr "Vous n'êtes pas identifié sur Tumblr" -#: tumblr.php:237 +#: tumblr.php:348 msgid "Enable Tumblr Post Addon" msgstr "Activez l'extension de publication Tumblr" -#: tumblr.php:238 +#: tumblr.php:349 msgid "Post to Tumblr by default" msgstr "Publier sur Tumblr par défaut" -#: tumblr.php:244 -msgid "Tumblr Export" -msgstr "Exporter vers Tumblr" +#: tumblr.php:350 +msgid "Import the remote timeline" +msgstr "Importer le flux distant" + +#: tumblr.php:351 +msgid "Subscribed tags" +msgstr "Tags suivis" + +#: tumblr.php:351 +#, php-format +msgid "" +"Comma separated list of up to %d tags that will be imported additionally to " +"the timeline" +msgstr "Liste séparée par des virgules contenant jusqu'à %d tags qui seront importés dans le flux" + +#: tumblr.php:357 +msgid "Tumblr Import/Export" +msgstr "Import/Export Tumblr" + +#: tumblr.php:375 +msgid "Post to Tumblr" +msgstr "Publier vers Tumblr" diff --git a/tumblr/lang/fr/strings.php b/tumblr/lang/fr/strings.php index b3e0ec777..ece76c746 100644 --- a/tumblr/lang/fr/strings.php +++ b/tumblr/lang/fr/strings.php @@ -9,12 +9,15 @@ $a->strings['Permission denied.'] = 'Permission refusée.'; $a->strings['Save Settings'] = 'Sauvegarder les paramètres'; $a->strings['Consumer Key'] = 'Clé utilisateur'; $a->strings['Consumer Secret'] = 'Secret utilisateur'; -$a->strings['You are now authenticated to tumblr.'] = 'Vous êtes maintenant identifié sur Tumblr'; -$a->strings['return to the connector page'] = 'Revenir à la page de connexion'; -$a->strings['Post to Tumblr'] = 'Publier vers Tumblr'; +$a->strings['Maximum tags'] = 'Tags maximum'; +$a->strings['Maximum number of tags that a user can follow. Enter 0 to deactivate the feature.'] = 'Nombre maximum de tags qu\'un utilisateur peut suivre. Entrez 0 pour désactiver cette fonctionnalité.'; $a->strings['Post to page:'] = 'Publier sur la page :'; $a->strings['(Re-)Authenticate your tumblr page'] = '(re)Authentifiez votre page Tumblr'; $a->strings['You are not authenticated to tumblr'] = 'Vous n\'êtes pas identifié sur Tumblr'; $a->strings['Enable Tumblr Post Addon'] = 'Activez l\'extension de publication Tumblr'; $a->strings['Post to Tumblr by default'] = 'Publier sur Tumblr par défaut'; -$a->strings['Tumblr Export'] = 'Exporter vers Tumblr'; +$a->strings['Import the remote timeline'] = 'Importer le flux distant'; +$a->strings['Subscribed tags'] = 'Tags suivis'; +$a->strings['Comma separated list of up to %d tags that will be imported additionally to the timeline'] = 'Liste séparée par des virgules contenant jusqu\'à %d tags qui seront importés dans le flux'; +$a->strings['Tumblr Import/Export'] = 'Import/Export Tumblr'; +$a->strings['Post to Tumblr'] = 'Publier vers Tumblr'; diff --git a/tumblr/lang/nl/messages.po b/tumblr/lang/nl/messages.po index f299c6f39..ae8e284c8 100644 --- a/tumblr/lang/nl/messages.po +++ b/tumblr/lang/nl/messages.po @@ -9,56 +9,81 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-02-27 05:01-0500\n" -"PO-Revision-Date: 2018-08-24 13:53+0000\n" -"Last-Translator: Jeroen De Meerleer \n" -"Language-Team: Dutch (http://www.transifex.com/Friendica/friendica/language/nl/)\n" +"POT-Creation-Date: 2023-04-29 06:56+0000\n" +"PO-Revision-Date: 2014-06-23 12:58+0000\n" +"Last-Translator: Jeroen De Meerleer , 2018\n" +"Language-Team: Dutch (http://app.transifex.com/Friendica/friendica/language/nl/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: nl\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: tumblr.php:34 +#: tumblr.php:243 msgid "Permission denied." msgstr "Toegang geweigerd." -#: tumblr.php:144 -msgid "You are now authenticated to tumblr." -msgstr "Je bent nu aangemeld bij tumblr" - -#: tumblr.php:145 -msgid "return to the connector page" +#: tumblr.php:296 +msgid "Save Settings" msgstr "" -#: tumblr.php:158 -msgid "Post to Tumblr" +#: tumblr.php:297 +msgid "Consumer Key" msgstr "" -#: tumblr.php:185 -msgid "Tumblr Post Settings" +#: tumblr.php:298 +msgid "Consumer Secret" msgstr "" -#: tumblr.php:188 -msgid "(Re-)Authenticate your tumblr page" +#: tumblr.php:299 +msgid "Maximum tags" msgstr "" -#: tumblr.php:192 -msgid "Enable Tumblr Post Addon" -msgstr "Tumblr Post Addon inschakelen" +#: tumblr.php:299 +msgid "" +"Maximum number of tags that a user can follow. Enter 0 to deactivate the " +"feature." +msgstr "" -#: tumblr.php:197 -msgid "Post to Tumblr by default" -msgstr "Plaatsen op Tumblr als standaard instellen " - -#: tumblr.php:217 +#: tumblr.php:336 msgid "Post to page:" msgstr "Plaats op pagina:" -#: tumblr.php:228 +#: tumblr.php:342 +msgid "(Re-)Authenticate your tumblr page" +msgstr "" + +#: tumblr.php:343 msgid "You are not authenticated to tumblr" msgstr "" -#: tumblr.php:233 -msgid "Submit" +#: tumblr.php:348 +msgid "Enable Tumblr Post Addon" +msgstr "Tumblr Post Addon inschakelen" + +#: tumblr.php:349 +msgid "Post to Tumblr by default" +msgstr "Plaatsen op Tumblr als standaard instellen " + +#: tumblr.php:350 +msgid "Import the remote timeline" +msgstr "" + +#: tumblr.php:351 +msgid "Subscribed tags" +msgstr "" + +#: tumblr.php:351 +#, php-format +msgid "" +"Comma separated list of up to %d tags that will be imported additionally to " +"the timeline" +msgstr "" + +#: tumblr.php:357 +msgid "Tumblr Import/Export" +msgstr "" + +#: tumblr.php:375 +msgid "Post to Tumblr" msgstr "" diff --git a/tumblr/lang/nl/strings.php b/tumblr/lang/nl/strings.php index 9f7f28280..0c70f7f3a 100644 --- a/tumblr/lang/nl/strings.php +++ b/tumblr/lang/nl/strings.php @@ -6,7 +6,6 @@ function string_plural_select_nl($n){ return intval($n != 1); }} $a->strings['Permission denied.'] = 'Toegang geweigerd.'; -$a->strings['You are now authenticated to tumblr.'] = 'Je bent nu aangemeld bij tumblr'; +$a->strings['Post to page:'] = 'Plaats op pagina:'; $a->strings['Enable Tumblr Post Addon'] = 'Tumblr Post Addon inschakelen'; $a->strings['Post to Tumblr by default'] = 'Plaatsen op Tumblr als standaard instellen '; -$a->strings['Post to page:'] = 'Plaats op pagina:'; diff --git a/twitter/lang/ar/messages.po b/twitter/lang/ar/messages.po index 0c1b26ae6..e12139c6d 100644 --- a/twitter/lang/ar/messages.po +++ b/twitter/lang/ar/messages.po @@ -9,121 +9,72 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-10-08 22:25-0400\n" -"PO-Revision-Date: 2021-10-09 06:17+0000\n" -"Last-Translator: Transifex Bot <>\n" -"Language-Team: Arabic (http://www.transifex.com/Friendica/friendica/language/ar/)\n" +"POT-Creation-Date: 2023-08-16 03:27+0000\n" +"PO-Revision-Date: 2014-06-23 12:58+0000\n" +"Last-Translator: Farida Khalaf , 2021\n" +"Language-Team: Arabic (http://app.transifex.com/Friendica/friendica/language/ar/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ar\n" "Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" -#: twitter.php:224 +#: twitter.php:84 msgid "Post to Twitter" msgstr "" -#: twitter.php:269 -msgid "" -"You submitted an empty PIN, please Sign In with Twitter again to get a new " -"one." +#: twitter.php:123 +msgid "No status." msgstr "" -#: twitter.php:329 twitter.php:333 -msgid "Twitter Import/Export/Mirror" -msgstr "" - -#: twitter.php:340 -msgid "" -"No consumer key pair for Twitter found. Please contact your site " -"administrator." -msgstr "" - -#: twitter.php:352 -msgid "" -"At this Friendica instance the Twitter addon was enabled but you have not " -"yet connected your account to your Twitter account. To do so click the " -"button below to get a PIN from Twitter which you have to copy into the input" -" box below and submit the form. Only your public posts will" -" be posted to Twitter." -msgstr "" - -#: twitter.php:353 -msgid "Log in with Twitter" -msgstr "" - -#: twitter.php:355 -msgid "Copy the PIN from Twitter here" -msgstr "" - -#: twitter.php:360 twitter.php:415 twitter.php:803 -msgid "Save Settings" -msgstr "حفظ الإعدادات" - -#: twitter.php:362 twitter.php:417 -msgid "An error occured: " -msgstr "" - -#: twitter.php:379 -msgid "Currently connected to: " -msgstr "" - -#: twitter.php:380 twitter.php:390 -msgid "Disconnect" -msgstr "" - -#: twitter.php:397 +#: twitter.php:129 msgid "Allow posting to Twitter" msgstr "" -#: twitter.php:397 +#: twitter.php:129 msgid "" "If enabled all your public postings can be posted to the " "associated Twitter account. You can choose to do so by default (here) or for" " every posting separately in the posting options when writing the entry." msgstr "" -#: twitter.php:400 -msgid "" -"Note: Due to your privacy settings (Hide your profile " -"details from unknown viewers?) the link potentially included in public " -"postings relayed to Twitter will lead the visitor to a blank page informing " -"the visitor that the access to your profile has been restricted." -msgstr "" - -#: twitter.php:403 +#: twitter.php:130 msgid "Send public postings to Twitter by default" msgstr "" -#: twitter.php:406 -msgid "Mirror all posts from twitter that are no replies" +#: twitter.php:131 +msgid "API Key" msgstr "" -#: twitter.php:409 -msgid "Import the remote timeline" +#: twitter.php:132 +msgid "API Secret" msgstr "" -#: twitter.php:412 -msgid "Automatically create contacts" +#: twitter.php:133 +msgid "Access Token" msgstr "" -#: twitter.php:412 +#: twitter.php:134 +msgid "Access Secret" +msgstr "" + +#: twitter.php:135 msgid "" -"This will automatically create a contact in Friendica as soon as you receive" -" a message from an existing contact via the Twitter network. If you do not " -"enable this, you need to manually add those Twitter contacts in Friendica " -"from whom you would like to see posts here." +"Each user needs to register their own app to be able to post to Twitter. " +"Please visit https://developer.twitter.com/en/portal/projects-and-apps to " +"register a project. Inside the project you then have to register an app. You" +" will find the needed data for the connector on the page \"Keys and token\" " +"in the app settings." msgstr "" -#: twitter.php:805 -msgid "Consumer key" +#: twitter.php:136 +msgid "Last Status Summary" msgstr "" -#: twitter.php:806 -msgid "Consumer secret" +#: twitter.php:137 +msgid "Last Status Content" msgstr "" -#: twitter.php:1002 -#, php-format -msgid "%s on Twitter" +#: twitter.php:142 +msgid "Twitter Export" msgstr "" diff --git a/twitter/lang/ar/strings.php b/twitter/lang/ar/strings.php index 285ad3039..eea34dd65 100644 --- a/twitter/lang/ar/strings.php +++ b/twitter/lang/ar/strings.php @@ -5,4 +5,3 @@ function string_plural_select_ar($n){ $n = intval($n); if ($n==0) { return 0; } else if ($n==1) { return 1; } else if ($n==2) { return 2; } else if ($n%100>=3 && $n%100<=10) { return 3; } else if ($n%100>=11 && $n%100<=99) { return 4; } else { return 5; } }} -$a->strings['Save Settings'] = 'حفظ الإعدادات'; diff --git a/twitter/lang/cs/messages.po b/twitter/lang/cs/messages.po index 68586a7ec..3e9d27d5c 100644 --- a/twitter/lang/cs/messages.po +++ b/twitter/lang/cs/messages.po @@ -11,126 +11,72 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-06-02 10:25+0700\n" -"PO-Revision-Date: 2018-06-14 10:10+0000\n" -"Last-Translator: Aditoo\n" -"Language-Team: Czech (http://www.transifex.com/Friendica/friendica/language/cs/)\n" +"POT-Creation-Date: 2023-08-16 03:27+0000\n" +"PO-Revision-Date: 2014-06-23 12:58+0000\n" +"Last-Translator: Aditoo, 2018\n" +"Language-Team: Czech (http://app.transifex.com/Friendica/friendica/language/cs/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: cs\n" "Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\n" -#: twitter.php:195 +#: twitter.php:84 msgid "Post to Twitter" msgstr "Poslat příspěvek na Twitter" -#: twitter.php:236 -msgid "" -"You submitted an empty PIN, please Sign In with Twitter again to get a new " -"one." -msgstr "Vložil/a jste prázdný PIN kód, prosím přihlaste se opět na Twitter pro nový." +#: twitter.php:123 +msgid "No status." +msgstr "" -#: twitter.php:263 -msgid "Twitter settings updated." -msgstr "Nastavení pro Twitter aktualizována." - -#: twitter.php:293 twitter.php:297 -msgid "Twitter Import/Export/Mirror" -msgstr "Import/Export/Zrcadlení Twitteru" - -#: twitter.php:304 -msgid "" -"No consumer key pair for Twitter found. Please contact your site " -"administrator." -msgstr "Nenalezen žádný spotřebitelský páru klíčů pro Twitter. Obraťte se na administrátora webu." - -#: twitter.php:316 -msgid "" -"At this Friendica instance the Twitter addon was enabled but you have not " -"yet connected your account to your Twitter account. To do so click the " -"button below to get a PIN from Twitter which you have to copy into the input" -" box below and submit the form. Only your public posts will" -" be posted to Twitter." -msgstr "Na této instanci Friendica byl doplněk pro Twitter povolen, ještě jste však nepřipojil/a Váš účet k Vašemu účtu na Twitteru. Pokud to chcete udělat, kliknutím na tlačítko níže získáte od Twitteru PIN kód, zkopírujte jej do pole níže a odešlete formulář. Pouze Vaše veřejné příspěvky budou odesílány na Twitter." - -#: twitter.php:317 -msgid "Log in with Twitter" -msgstr "Přihlásit se přes Twitter" - -#: twitter.php:319 -msgid "Copy the PIN from Twitter here" -msgstr "Zkopírujte sem PIN z Twitteru" - -#: twitter.php:324 twitter.php:366 twitter.php:636 -msgid "Save Settings" -msgstr "Uložit nastavení" - -#: twitter.php:336 -msgid "Currently connected to: " -msgstr "V současné době připojen k:" - -#: twitter.php:337 -msgid "Disconnect" -msgstr "Odpojit" - -#: twitter.php:347 +#: twitter.php:129 msgid "Allow posting to Twitter" msgstr "Povolit odesílání na Twitter" -#: twitter.php:347 +#: twitter.php:129 msgid "" "If enabled all your public postings can be posted to the " "associated Twitter account. You can choose to do so by default (here) or for" " every posting separately in the posting options when writing the entry." msgstr "Je-li povoleno, všechny Vaše veřejné příspěvky mohou být zasílány na související účet na Twitteru. Můžete si vybrat, zda-li toto bude výchozí nastavení (zde), nebo budete mít možnost si vybrat požadované chování při psaní každého příspěvku." -#: twitter.php:350 -msgid "" -"Note: Due to your privacy settings (Hide your profile " -"details from unknown viewers?) the link potentially included in public " -"postings relayed to Twitter will lead the visitor to a blank page informing " -"the visitor that the access to your profile has been restricted." -msgstr "Poznámka: Kvůli vašim nastavením o soukromí (Skrýt Vaše profilové detaily před neznámými návštěvníky?), odkaz potenciálně obsažen ve veřejných příspěvcích přeposílaných na Twitter zavedou návštěvníky na prázdnou stránku informující návštěvníky, že přístup na Váš profil byl zakázán." - -#: twitter.php:353 +#: twitter.php:130 msgid "Send public postings to Twitter by default" msgstr "Defaultně zasílat veřejné komentáře na Twitter" -#: twitter.php:356 -msgid "Mirror all posts from twitter that are no replies" -msgstr "Zrcadlit všechny příspěvky z Twitteru, které nejsou odpovědi." +#: twitter.php:131 +msgid "API Key" +msgstr "" -#: twitter.php:359 -msgid "Import the remote timeline" -msgstr "Importovat vzdálenou časovou osu" +#: twitter.php:132 +msgid "API Secret" +msgstr "" -#: twitter.php:362 -msgid "Automatically create contacts" -msgstr "Automaticky vytvořit kontakty" +#: twitter.php:133 +msgid "Access Token" +msgstr "" -#: twitter.php:362 +#: twitter.php:134 +msgid "Access Secret" +msgstr "" + +#: twitter.php:135 msgid "" -"This will automatically create a contact in Friendica as soon as you receive" -" a message from an existing contact via the Twitter network. If you do not " -"enable this, you need to manually add those Twitter contacts in Friendica " -"from whom you would like to see posts here. However if enabled, you cannot " -"merely remove a twitter contact from the Friendica contact list, as it will " -"recreate this contact when they post again." -msgstr "Tato možnost automaticky vytvoří kontakt na Friendica, jakmile obdržíte zprávu od existujícího kontaktu přes síť Twitter. Pokud toto nezapnete, budete si muset tyto kontakty na Twitteru, od kterých chcete dostávat příspěvky, přidávat do Friendica manuálně. Pokud toto ovšem zapnete, nemůžete jednoduše odstranit kontakt na Twitteru ze seznamu kontaktů na Friendica, neboť tato možnost jej při každém novém příspěvku opět vytvoří." +"Each user needs to register their own app to be able to post to Twitter. " +"Please visit https://developer.twitter.com/en/portal/projects-and-apps to " +"register a project. Inside the project you then have to register an app. You" +" will find the needed data for the connector on the page \"Keys and token\" " +"in the app settings." +msgstr "" -#: twitter.php:614 -msgid "Twitter post failed. Queued for retry." -msgstr "Poslání příspěvku na Twitter selhalo. Příspěvek byl poslán do fronty pro zopakování." +#: twitter.php:136 +msgid "Last Status Summary" +msgstr "" -#: twitter.php:628 -msgid "Settings updated." -msgstr "Nastavení aktualizováno." +#: twitter.php:137 +msgid "Last Status Content" +msgstr "" -#: twitter.php:638 -msgid "Consumer key" -msgstr "Consumer key" - -#: twitter.php:639 -msgid "Consumer secret" -msgstr "Consumer secret" +#: twitter.php:142 +msgid "Twitter Export" +msgstr "" diff --git a/twitter/lang/cs/strings.php b/twitter/lang/cs/strings.php index 59a584ced..da68673d6 100644 --- a/twitter/lang/cs/strings.php +++ b/twitter/lang/cs/strings.php @@ -6,25 +6,6 @@ function string_plural_select_cs($n){ if (($n == 1 && $n % 1 == 0)) { return 0; } else if (($n >= 2 && $n <= 4 && $n % 1 == 0)) { return 1; } else if (($n % 1 != 0 )) { return 2; } else { return 3; } }} $a->strings['Post to Twitter'] = 'Poslat příspěvek na Twitter'; -$a->strings['You submitted an empty PIN, please Sign In with Twitter again to get a new one.'] = 'Vložil/a jste prázdný PIN kód, prosím přihlaste se opět na Twitter pro nový.'; -$a->strings['Twitter settings updated.'] = 'Nastavení pro Twitter aktualizována.'; -$a->strings['Twitter Import/Export/Mirror'] = 'Import/Export/Zrcadlení Twitteru'; -$a->strings['No consumer key pair for Twitter found. Please contact your site administrator.'] = 'Nenalezen žádný spotřebitelský páru klíčů pro Twitter. Obraťte se na administrátora webu.'; -$a->strings['At this Friendica instance the Twitter addon was enabled but you have not yet connected your account to your Twitter account. To do so click the button below to get a PIN from Twitter which you have to copy into the input box below and submit the form. Only your public posts will be posted to Twitter.'] = 'Na této instanci Friendica byl doplněk pro Twitter povolen, ještě jste však nepřipojil/a Váš účet k Vašemu účtu na Twitteru. Pokud to chcete udělat, kliknutím na tlačítko níže získáte od Twitteru PIN kód, zkopírujte jej do pole níže a odešlete formulář. Pouze Vaše veřejné příspěvky budou odesílány na Twitter.'; -$a->strings['Log in with Twitter'] = 'Přihlásit se přes Twitter'; -$a->strings['Copy the PIN from Twitter here'] = 'Zkopírujte sem PIN z Twitteru'; -$a->strings['Save Settings'] = 'Uložit nastavení'; -$a->strings['Currently connected to: '] = 'V současné době připojen k:'; -$a->strings['Disconnect'] = 'Odpojit'; $a->strings['Allow posting to Twitter'] = 'Povolit odesílání na Twitter'; $a->strings['If enabled all your public postings can be posted to the associated Twitter account. You can choose to do so by default (here) or for every posting separately in the posting options when writing the entry.'] = 'Je-li povoleno, všechny Vaše veřejné příspěvky mohou být zasílány na související účet na Twitteru. Můžete si vybrat, zda-li toto bude výchozí nastavení (zde), nebo budete mít možnost si vybrat požadované chování při psaní každého příspěvku.'; -$a->strings['Note: Due to your privacy settings (Hide your profile details from unknown viewers?) the link potentially included in public postings relayed to Twitter will lead the visitor to a blank page informing the visitor that the access to your profile has been restricted.'] = 'Poznámka: Kvůli vašim nastavením o soukromí (Skrýt Vaše profilové detaily před neznámými návštěvníky?), odkaz potenciálně obsažen ve veřejných příspěvcích přeposílaných na Twitter zavedou návštěvníky na prázdnou stránku informující návštěvníky, že přístup na Váš profil byl zakázán.'; $a->strings['Send public postings to Twitter by default'] = 'Defaultně zasílat veřejné komentáře na Twitter'; -$a->strings['Mirror all posts from twitter that are no replies'] = 'Zrcadlit všechny příspěvky z Twitteru, které nejsou odpovědi.'; -$a->strings['Import the remote timeline'] = 'Importovat vzdálenou časovou osu'; -$a->strings['Automatically create contacts'] = 'Automaticky vytvořit kontakty'; -$a->strings['This will automatically create a contact in Friendica as soon as you receive a message from an existing contact via the Twitter network. If you do not enable this, you need to manually add those Twitter contacts in Friendica from whom you would like to see posts here. However if enabled, you cannot merely remove a twitter contact from the Friendica contact list, as it will recreate this contact when they post again.'] = 'Tato možnost automaticky vytvoří kontakt na Friendica, jakmile obdržíte zprávu od existujícího kontaktu přes síť Twitter. Pokud toto nezapnete, budete si muset tyto kontakty na Twitteru, od kterých chcete dostávat příspěvky, přidávat do Friendica manuálně. Pokud toto ovšem zapnete, nemůžete jednoduše odstranit kontakt na Twitteru ze seznamu kontaktů na Friendica, neboť tato možnost jej při každém novém příspěvku opět vytvoří.'; -$a->strings['Twitter post failed. Queued for retry.'] = 'Poslání příspěvku na Twitter selhalo. Příspěvek byl poslán do fronty pro zopakování.'; -$a->strings['Settings updated.'] = 'Nastavení aktualizováno.'; -$a->strings['Consumer key'] = 'Consumer key'; -$a->strings['Consumer secret'] = 'Consumer secret'; diff --git a/twitter/lang/de/messages.po b/twitter/lang/de/messages.po index 66a6f3874..a38392a2b 100644 --- a/twitter/lang/de/messages.po +++ b/twitter/lang/de/messages.po @@ -4,6 +4,7 @@ # # # Translators: +# Raroun, 2023 # Till Mohr , 2021 # Tobias Diekershoff , 2014-2015 # Tobias Diekershoff , 2018,2020-2022 @@ -12,9 +13,9 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-11-13 10:15+0000\n" +"POT-Creation-Date: 2023-08-16 03:27+0000\n" "PO-Revision-Date: 2014-06-23 12:58+0000\n" -"Last-Translator: Tobias Diekershoff , 2018,2020-2022\n" +"Last-Translator: Raroun, 2023\n" "Language-Team: German (http://app.transifex.com/Friendica/friendica/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -22,143 +23,62 @@ msgstr "" "Language: de\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: twitter.php:216 +#: twitter.php:84 msgid "Post to Twitter" msgstr "Auf Twitter veröffentlichen" -#: twitter.php:263 -msgid "" -"You submitted an empty PIN, please Sign In with Twitter again to get a new " -"one." -msgstr "Du hast keine PIN übertragen. Bitte melde dich erneut bei Twitter an, um eine neue PIN zu erhalten." +#: twitter.php:123 +msgid "No status." +msgstr "Kein Status." -#: twitter.php:330 -msgid "" -"No consumer key pair for Twitter found. Please contact your site " -"administrator." -msgstr "Kein Consumer-Schlüsselpaar für Twitter gefunden. Bitte wende dich an den Administrator der Seite." - -#: twitter.php:343 -msgid "" -"At this Friendica instance the Twitter addon was enabled but you have not " -"yet connected your account to your Twitter account. To do so click the " -"button below to get a PIN from Twitter which you have to copy into the input" -" box below and submit the form. Only your public posts will" -" be posted to Twitter." -msgstr "Auf diesem Friendica-Server wurde das Twitter-Addon aktiviert, aber du hast deinen Account noch nicht mit deinem Twitter-Account verbunden. Klicke dazu auf die Schaltfläche unten. Du erhältst dann eine PIN von Twitter, die du in das Eingabefeld unten einfügst. Denk daran, den Senden-Knopf zu drücken! Nur öffentliche Beiträge werden bei Twitter veröffentlicht." - -#: twitter.php:344 -msgid "Log in with Twitter" -msgstr "bei Twitter anmelden" - -#: twitter.php:346 -msgid "Copy the PIN from Twitter here" -msgstr "Kopiere die Twitter-PIN hierher" - -#: twitter.php:354 twitter.php:399 -msgid "An error occured: " -msgstr "Ein Fehler ist aufgetreten:" - -#: twitter.php:368 -#, php-format -msgid "" -"Currently connected to: %1$s" -msgstr "Derzeit verbunden mit: %1$s" - -#: twitter.php:374 -msgid "" -"Note: Due to your privacy settings (Hide your profile " -"details from unknown viewers?) the link potentially included in public " -"postings relayed to Twitter will lead the visitor to a blank page informing " -"the visitor that the access to your profile has been restricted." -msgstr "Hinweis: Aufgrund deiner Privatsphären-Einstellungen (Profil-Details vor unbekannten Betrachtern verbergen?) wird der Link, der eventuell an deinen Twitter-Beitrag angehängt wird, um auf den Originalbeitrag zu verweisen, den Betrachter auf eine leere Seite führen, die ihn darüber informiert, dass der Zugriff eingeschränkt wurde." - -#: twitter.php:381 -msgid "Invalid Twitter info" -msgstr "Ungültige Twitter Informationen" - -#: twitter.php:382 -msgid "Disconnect" -msgstr "Trennen" - -#: twitter.php:387 +#: twitter.php:129 msgid "Allow posting to Twitter" msgstr "Veröffentlichung bei Twitter erlauben" -#: twitter.php:387 +#: twitter.php:129 msgid "" "If enabled all your public postings can be posted to the " "associated Twitter account. You can choose to do so by default (here) or for" " every posting separately in the posting options when writing the entry." msgstr "Wenn aktiviert, können all deine öffentlichen Einträge auf dem verbundenen Twitter-Konto veröffentlicht werden. Du kannst dies (hier) als Standardverhalten einstellen oder beim Schreiben eines Beitrags in den Beitragsoptionen festlegen." -#: twitter.php:388 +#: twitter.php:130 msgid "Send public postings to Twitter by default" msgstr "Veröffentliche öffentliche Beiträge standardmäßig bei Twitter" -#: twitter.php:389 -msgid "Use threads instead of truncating the content" -msgstr "Verwende Threads anstelle den Inhalt zu kürzen" +#: twitter.php:131 +msgid "API Key" +msgstr "API Key" -#: twitter.php:390 -msgid "Mirror all posts from twitter that are no replies" -msgstr "Spiegle alle Beiträge von Twitter, die keine Antworten sind" +#: twitter.php:132 +msgid "API Secret" +msgstr "API Secret" -#: twitter.php:391 -msgid "Import the remote timeline" -msgstr "Importiere die Remote-Zeitleiste" +#: twitter.php:133 +msgid "Access Token" +msgstr "Access Token" -#: twitter.php:392 -msgid "Automatically create contacts" -msgstr "Automatisch Kontakte anlegen" +#: twitter.php:134 +msgid "Access Secret" +msgstr "Access Secret" -#: twitter.php:392 +#: twitter.php:135 msgid "" -"This will automatically create a contact in Friendica as soon as you receive" -" a message from an existing contact via the Twitter network. If you do not " -"enable this, you need to manually add those Twitter contacts in Friendica " -"from whom you would like to see posts here." -msgstr "Mit dieser Option wird automatisch ein Kontakt bei Friendica angelegt, wenn du eine Nachricht von einem bestehenden Kontakt auf Twitter erhältst. Ist die Option nicht aktiv, musst du manuell Kontakte für diejenigen deiner Twitter-Kontakte anlegen, deren Nachrichten du auf Friendica lesen möchtest." +"Each user needs to register their own app to be able to post to Twitter. " +"Please visit https://developer.twitter.com/en/portal/projects-and-apps to " +"register a project. Inside the project you then have to register an app. You" +" will find the needed data for the connector on the page \"Keys and token\" " +"in the app settings." +msgstr "Jeder Nutzer muss seine eigene App registrieren, um auf Twitter posten zu können. Bitte besuchen Sie https://developer.twitter.com/en/portal/projects-and-apps, um ein Projekt zu registrieren. Innerhalb des Projekts müssen Sie dann eine App registrieren. Die benötigten Daten für den Connector finden Sie auf der Seite \"Keys and token\" in den App-Einstellungen." -#: twitter.php:393 -msgid "Follow in fediverse" -msgstr "Im Fediverse folgen" +#: twitter.php:136 +msgid "Last Status Summary" +msgstr "Zusammenfassung des letzten Status" -#: twitter.php:393 -msgid "" -"Automatically subscribe to the contact in the fediverse, when a fediverse " -"account is mentioned in name or description and we are following the Twitter" -" contact." -msgstr "Hat ein Twitter Kontakt eine Profiladresse im Fediverse im Namen oder der Beschreibung genannt, wird dieser automatisch gefolgt." +#: twitter.php:137 +msgid "Last Status Content" +msgstr "Inhalt des letzten Status" -#: twitter.php:406 -msgid "Twitter Import/Export/Mirror" -msgstr "Twitter-Import/Export/Spiegeln" - -#: twitter.php:558 -msgid "" -"Please connect a Twitter account in your Social Network settings to import " -"Twitter posts." -msgstr "Bitte verbinde deinen Twitter Account in den Einstellungen zu den Soziale Netzwerken damit deine Twitter Beiträge importiert werden." - -#: twitter.php:565 -msgid "Twitter post not found." -msgstr "Beiträge auf Twitter nicht gefunden." - -#: twitter.php:965 -msgid "Save Settings" -msgstr "Einstellungen speichern" - -#: twitter.php:967 -msgid "Consumer key" -msgstr "Consumer Key" - -#: twitter.php:968 -msgid "Consumer secret" -msgstr "Consumer Secret" - -#: twitter.php:1167 -#, php-format -msgid "%s on Twitter" -msgstr "%s auf Twitter" +#: twitter.php:142 +msgid "Twitter Export" +msgstr "Twitter Export" diff --git a/twitter/lang/de/strings.php b/twitter/lang/de/strings.php index f465aab2e..4079ddfe1 100644 --- a/twitter/lang/de/strings.php +++ b/twitter/lang/de/strings.php @@ -6,30 +6,15 @@ function string_plural_select_de($n){ return intval($n != 1); }} $a->strings['Post to Twitter'] = 'Auf Twitter veröffentlichen'; -$a->strings['You submitted an empty PIN, please Sign In with Twitter again to get a new one.'] = 'Du hast keine PIN übertragen. Bitte melde dich erneut bei Twitter an, um eine neue PIN zu erhalten.'; -$a->strings['No consumer key pair for Twitter found. Please contact your site administrator.'] = 'Kein Consumer-Schlüsselpaar für Twitter gefunden. Bitte wende dich an den Administrator der Seite.'; -$a->strings['At this Friendica instance the Twitter addon was enabled but you have not yet connected your account to your Twitter account. To do so click the button below to get a PIN from Twitter which you have to copy into the input box below and submit the form. Only your public posts will be posted to Twitter.'] = 'Auf diesem Friendica-Server wurde das Twitter-Addon aktiviert, aber du hast deinen Account noch nicht mit deinem Twitter-Account verbunden. Klicke dazu auf die Schaltfläche unten. Du erhältst dann eine PIN von Twitter, die du in das Eingabefeld unten einfügst. Denk daran, den Senden-Knopf zu drücken! Nur öffentliche Beiträge werden bei Twitter veröffentlicht.'; -$a->strings['Log in with Twitter'] = 'bei Twitter anmelden'; -$a->strings['Copy the PIN from Twitter here'] = 'Kopiere die Twitter-PIN hierher'; -$a->strings['An error occured: '] = 'Ein Fehler ist aufgetreten:'; -$a->strings['Currently connected to: %1$s'] = 'Derzeit verbunden mit: %1$s'; -$a->strings['Note: Due to your privacy settings (Hide your profile details from unknown viewers?) the link potentially included in public postings relayed to Twitter will lead the visitor to a blank page informing the visitor that the access to your profile has been restricted.'] = 'Hinweis: Aufgrund deiner Privatsphären-Einstellungen (Profil-Details vor unbekannten Betrachtern verbergen?) wird der Link, der eventuell an deinen Twitter-Beitrag angehängt wird, um auf den Originalbeitrag zu verweisen, den Betrachter auf eine leere Seite führen, die ihn darüber informiert, dass der Zugriff eingeschränkt wurde.'; -$a->strings['Invalid Twitter info'] = 'Ungültige Twitter Informationen'; -$a->strings['Disconnect'] = 'Trennen'; +$a->strings['No status.'] = 'Kein Status.'; $a->strings['Allow posting to Twitter'] = 'Veröffentlichung bei Twitter erlauben'; $a->strings['If enabled all your public postings can be posted to the associated Twitter account. You can choose to do so by default (here) or for every posting separately in the posting options when writing the entry.'] = 'Wenn aktiviert, können all deine öffentlichen Einträge auf dem verbundenen Twitter-Konto veröffentlicht werden. Du kannst dies (hier) als Standardverhalten einstellen oder beim Schreiben eines Beitrags in den Beitragsoptionen festlegen.'; $a->strings['Send public postings to Twitter by default'] = 'Veröffentliche öffentliche Beiträge standardmäßig bei Twitter'; -$a->strings['Use threads instead of truncating the content'] = 'Verwende Threads anstelle den Inhalt zu kürzen'; -$a->strings['Mirror all posts from twitter that are no replies'] = 'Spiegle alle Beiträge von Twitter, die keine Antworten sind'; -$a->strings['Import the remote timeline'] = 'Importiere die Remote-Zeitleiste'; -$a->strings['Automatically create contacts'] = 'Automatisch Kontakte anlegen'; -$a->strings['This will automatically create a contact in Friendica as soon as you receive a message from an existing contact via the Twitter network. If you do not enable this, you need to manually add those Twitter contacts in Friendica from whom you would like to see posts here.'] = 'Mit dieser Option wird automatisch ein Kontakt bei Friendica angelegt, wenn du eine Nachricht von einem bestehenden Kontakt auf Twitter erhältst. Ist die Option nicht aktiv, musst du manuell Kontakte für diejenigen deiner Twitter-Kontakte anlegen, deren Nachrichten du auf Friendica lesen möchtest.'; -$a->strings['Follow in fediverse'] = 'Im Fediverse folgen'; -$a->strings['Automatically subscribe to the contact in the fediverse, when a fediverse account is mentioned in name or description and we are following the Twitter contact.'] = 'Hat ein Twitter Kontakt eine Profiladresse im Fediverse im Namen oder der Beschreibung genannt, wird dieser automatisch gefolgt.'; -$a->strings['Twitter Import/Export/Mirror'] = 'Twitter-Import/Export/Spiegeln'; -$a->strings['Please connect a Twitter account in your Social Network settings to import Twitter posts.'] = 'Bitte verbinde deinen Twitter Account in den Einstellungen zu den Soziale Netzwerken damit deine Twitter Beiträge importiert werden.'; -$a->strings['Twitter post not found.'] = 'Beiträge auf Twitter nicht gefunden.'; -$a->strings['Save Settings'] = 'Einstellungen speichern'; -$a->strings['Consumer key'] = 'Consumer Key'; -$a->strings['Consumer secret'] = 'Consumer Secret'; -$a->strings['%s on Twitter'] = '%s auf Twitter'; +$a->strings['API Key'] = 'API Key'; +$a->strings['API Secret'] = 'API Secret'; +$a->strings['Access Token'] = 'Access Token'; +$a->strings['Access Secret'] = 'Access Secret'; +$a->strings['Each user needs to register their own app to be able to post to Twitter. Please visit https://developer.twitter.com/en/portal/projects-and-apps to register a project. Inside the project you then have to register an app. You will find the needed data for the connector on the page "Keys and token" in the app settings.'] = 'Jeder Nutzer muss seine eigene App registrieren, um auf Twitter posten zu können. Bitte besuchen Sie https://developer.twitter.com/en/portal/projects-and-apps, um ein Projekt zu registrieren. Innerhalb des Projekts müssen Sie dann eine App registrieren. Die benötigten Daten für den Connector finden Sie auf der Seite "Keys and token" in den App-Einstellungen.'; +$a->strings['Last Status Summary'] = 'Zusammenfassung des letzten Status'; +$a->strings['Last Status Content'] = 'Inhalt des letzten Status'; +$a->strings['Twitter Export'] = 'Twitter Export'; diff --git a/twitter/lang/es/messages.po b/twitter/lang/es/messages.po index 6673ef0a0..f479b846a 100644 --- a/twitter/lang/es/messages.po +++ b/twitter/lang/es/messages.po @@ -11,123 +11,72 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-02-01 18:16+0100\n" -"PO-Revision-Date: 2021-04-06 02:17+0000\n" -"Last-Translator: Senex Petrovic \n" -"Language-Team: Spanish (http://www.transifex.com/Friendica/friendica/language/es/)\n" +"POT-Creation-Date: 2023-08-16 03:27+0000\n" +"PO-Revision-Date: 2014-06-23 12:58+0000\n" +"Last-Translator: Senex Petrovic , 2021\n" +"Language-Team: Spanish (http://app.transifex.com/Friendica/friendica/language/es/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: es\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" -#: twitter.php:189 +#: twitter.php:84 msgid "Post to Twitter" msgstr "Entrada para Twitter" -#: twitter.php:234 -msgid "" -"You submitted an empty PIN, please Sign In with Twitter again to get a new " -"one." -msgstr "Envió un PIN vacío, inicie sesión con Twitter nuevamente para obtener uno nuevo." +#: twitter.php:123 +msgid "No status." +msgstr "" -#: twitter.php:291 twitter.php:295 -msgid "Twitter Import/Export/Mirror" -msgstr "Importación / Exportación / Espejo de Twitter" - -#: twitter.php:302 -msgid "" -"No consumer key pair for Twitter found. Please contact your site " -"administrator." -msgstr "No se ha encontrado ningún par de claves de consumidor para Twitter. Por favor, póngase en contacto con el administrador de su sitio. " - -#: twitter.php:314 -msgid "" -"At this Friendica instance the Twitter addon was enabled but you have not " -"yet connected your account to your Twitter account. To do so click the " -"button below to get a PIN from Twitter which you have to copy into the input" -" box below and submit the form. Only your public posts will" -" be posted to Twitter." -msgstr "En esta instancia de Friendica, se habilitó el complemento de Twitter, pero aún no ha conectado su cuenta a su cuenta de Twitter. Para hacerlo, haga clic en el botón de abajo para obtener un PIN de Twitter que debe copiar en el cuadro de entrada a continuación y enviar el formulario. Solo sus publicaciones de public se publicarán en Twitter." - -#: twitter.php:315 -msgid "Log in with Twitter" -msgstr "Iniciar sesión con Twitter" - -#: twitter.php:317 -msgid "Copy the PIN from Twitter here" -msgstr "Copie el PIN de Twitter aquí" - -#: twitter.php:322 twitter.php:377 twitter.php:768 -msgid "Save Settings" -msgstr "Guardar ajustes" - -#: twitter.php:324 twitter.php:379 -msgid "An error occured: " -msgstr "Ocurrió un error:" - -#: twitter.php:341 -msgid "Currently connected to: " -msgstr "Moneda conectada a:" - -#: twitter.php:342 twitter.php:352 -msgid "Disconnect" -msgstr "Desconectar" - -#: twitter.php:359 +#: twitter.php:129 msgid "Allow posting to Twitter" msgstr "Permitir publicar en Twitter" -#: twitter.php:359 +#: twitter.php:129 msgid "" "If enabled all your public postings can be posted to the " "associated Twitter account. You can choose to do so by default (here) or for" " every posting separately in the posting options when writing the entry." msgstr "Si habilita todas sus publicaciones públicas pueden ser publicadas en la cuenta de Twitter asociada. Puede elegir hacer eso por defecto (aquí) o por cada publicación por separado en las opciones de entrada cuando escriba la entrada." -#: twitter.php:362 -msgid "" -"Note: Due to your privacy settings (Hide your profile " -"details from unknown viewers?) the link potentially included in public " -"postings relayed to Twitter will lead the visitor to a blank page informing " -"the visitor that the access to your profile has been restricted." -msgstr "Nota: Debido a tu privacidad (Ocultar tu perfil de desconocidos?) el enlace potencialmente incluido en publicaciones públicas retransmitidas a Twitter llevará al visitante a una página en blanco que le informa que el acceso a su perfil ha sido restringido." - -#: twitter.php:365 +#: twitter.php:130 msgid "Send public postings to Twitter by default" msgstr "Enviar publicaciones públicas a Twitter por defecto" -#: twitter.php:368 -msgid "Mirror all posts from twitter that are no replies" -msgstr "Refleje todas las publicaciones de Twitter que no sean respuestas" +#: twitter.php:131 +msgid "API Key" +msgstr "" -#: twitter.php:371 -msgid "Import the remote timeline" -msgstr "Importar la línea de tiempo remota" +#: twitter.php:132 +msgid "API Secret" +msgstr "" -#: twitter.php:374 -msgid "Automatically create contacts" -msgstr "Crea contactos automáticamente" +#: twitter.php:133 +msgid "Access Token" +msgstr "" -#: twitter.php:374 +#: twitter.php:134 +msgid "Access Secret" +msgstr "" + +#: twitter.php:135 msgid "" -"This will automatically create a contact in Friendica as soon as you receive" -" a message from an existing contact via the Twitter network. If you do not " -"enable this, you need to manually add those Twitter contacts in Friendica " -"from whom you would like to see posts here. However if enabled, you cannot " -"merely remove a twitter contact from the Friendica contact list, as it will " -"recreate this contact when they post again." -msgstr "Esto creará automáticamente un contacto en Friendica tan pronto como reciba un mensaje de un contacto existente a través de la red de Twitter. Si no habilita esto, debe agregar manualmente los contactos de Twitter en Friendica de los que le gustaría ver las publicaciones aquí. Sin embargo, si está habilitado, no puede simplemente eliminar un contacto de Twitter de la lista de contactos de Friendica, ya que volverá a crear este contacto cuando vuelva a publicar." +"Each user needs to register their own app to be able to post to Twitter. " +"Please visit https://developer.twitter.com/en/portal/projects-and-apps to " +"register a project. Inside the project you then have to register an app. You" +" will find the needed data for the connector on the page \"Keys and token\" " +"in the app settings." +msgstr "" -#: twitter.php:770 -msgid "Consumer key" -msgstr "Clave de consumidor" +#: twitter.php:136 +msgid "Last Status Summary" +msgstr "" -#: twitter.php:771 -msgid "Consumer secret" -msgstr "Secreto de consumidor" +#: twitter.php:137 +msgid "Last Status Content" +msgstr "" -#: twitter.php:967 -#, php-format -msgid "%s on Twitter" -msgstr "%s en Twitter" +#: twitter.php:142 +msgid "Twitter Export" +msgstr "" diff --git a/twitter/lang/es/strings.php b/twitter/lang/es/strings.php index 1aa0cd142..368c871c1 100644 --- a/twitter/lang/es/strings.php +++ b/twitter/lang/es/strings.php @@ -3,27 +3,9 @@ if(! function_exists("string_plural_select_es")) { function string_plural_select_es($n){ $n = intval($n); - return intval($n != 1); + if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } }} $a->strings['Post to Twitter'] = 'Entrada para Twitter'; -$a->strings['You submitted an empty PIN, please Sign In with Twitter again to get a new one.'] = 'Envió un PIN vacío, inicie sesión con Twitter nuevamente para obtener uno nuevo.'; -$a->strings['Twitter Import/Export/Mirror'] = 'Importación / Exportación / Espejo de Twitter'; -$a->strings['No consumer key pair for Twitter found. Please contact your site administrator.'] = 'No se ha encontrado ningún par de claves de consumidor para Twitter. Por favor, póngase en contacto con el administrador de su sitio. '; -$a->strings['At this Friendica instance the Twitter addon was enabled but you have not yet connected your account to your Twitter account. To do so click the button below to get a PIN from Twitter which you have to copy into the input box below and submit the form. Only your public posts will be posted to Twitter.'] = 'En esta instancia de Friendica, se habilitó el complemento de Twitter, pero aún no ha conectado su cuenta a su cuenta de Twitter. Para hacerlo, haga clic en el botón de abajo para obtener un PIN de Twitter que debe copiar en el cuadro de entrada a continuación y enviar el formulario. Solo sus publicaciones de public se publicarán en Twitter.'; -$a->strings['Log in with Twitter'] = 'Iniciar sesión con Twitter'; -$a->strings['Copy the PIN from Twitter here'] = 'Copie el PIN de Twitter aquí'; -$a->strings['Save Settings'] = 'Guardar ajustes'; -$a->strings['An error occured: '] = 'Ocurrió un error:'; -$a->strings['Currently connected to: '] = 'Moneda conectada a:'; -$a->strings['Disconnect'] = 'Desconectar'; $a->strings['Allow posting to Twitter'] = 'Permitir publicar en Twitter'; $a->strings['If enabled all your public postings can be posted to the associated Twitter account. You can choose to do so by default (here) or for every posting separately in the posting options when writing the entry.'] = 'Si habilita todas sus publicaciones públicas pueden ser publicadas en la cuenta de Twitter asociada. Puede elegir hacer eso por defecto (aquí) o por cada publicación por separado en las opciones de entrada cuando escriba la entrada.'; -$a->strings['Note: Due to your privacy settings (Hide your profile details from unknown viewers?) the link potentially included in public postings relayed to Twitter will lead the visitor to a blank page informing the visitor that the access to your profile has been restricted.'] = 'Nota: Debido a tu privacidad (Ocultar tu perfil de desconocidos?) el enlace potencialmente incluido en publicaciones públicas retransmitidas a Twitter llevará al visitante a una página en blanco que le informa que el acceso a su perfil ha sido restringido.'; $a->strings['Send public postings to Twitter by default'] = 'Enviar publicaciones públicas a Twitter por defecto'; -$a->strings['Mirror all posts from twitter that are no replies'] = 'Refleje todas las publicaciones de Twitter que no sean respuestas'; -$a->strings['Import the remote timeline'] = 'Importar la línea de tiempo remota'; -$a->strings['Automatically create contacts'] = 'Crea contactos automáticamente'; -$a->strings['This will automatically create a contact in Friendica as soon as you receive a message from an existing contact via the Twitter network. If you do not enable this, you need to manually add those Twitter contacts in Friendica from whom you would like to see posts here. However if enabled, you cannot merely remove a twitter contact from the Friendica contact list, as it will recreate this contact when they post again.'] = 'Esto creará automáticamente un contacto en Friendica tan pronto como reciba un mensaje de un contacto existente a través de la red de Twitter. Si no habilita esto, debe agregar manualmente los contactos de Twitter en Friendica de los que le gustaría ver las publicaciones aquí. Sin embargo, si está habilitado, no puede simplemente eliminar un contacto de Twitter de la lista de contactos de Friendica, ya que volverá a crear este contacto cuando vuelva a publicar.'; -$a->strings['Consumer key'] = 'Clave de consumidor'; -$a->strings['Consumer secret'] = 'Secreto de consumidor'; -$a->strings['%s on Twitter'] = '%s en Twitter'; diff --git a/twitter/lang/fr/messages.po b/twitter/lang/fr/messages.po index f6afa0a6d..b510d6d8d 100644 --- a/twitter/lang/fr/messages.po +++ b/twitter/lang/fr/messages.po @@ -4,6 +4,7 @@ # # # Translators: +# Florent C., 2023 # Nicolas Derive, 2022 # ea1cd8241cb389ffb6f92bc6891eff5d_dc12308 <70dced5587d47e18d88f9298024d96f8_93383>, 2015 # StefOfficiel , 2015 @@ -11,153 +12,72 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-11-13 10:15+0000\n" +"POT-Creation-Date: 2023-08-16 03:27+0000\n" "PO-Revision-Date: 2014-06-23 12:58+0000\n" -"Last-Translator: Nicolas Derive, 2022\n" -"Language-Team: French (http://www.transifex.com/Friendica/friendica/language/fr/)\n" +"Last-Translator: Florent C., 2023\n" +"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: fr\n" "Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" -#: twitter.php:216 +#: twitter.php:84 msgid "Post to Twitter" msgstr "Publier sur Twitter" -#: twitter.php:263 -msgid "" -"You submitted an empty PIN, please Sign In with Twitter again to get a new " -"one." -msgstr "Vous avez envoyé un PIN vide, veuillez vous connecter à Twitter à nouveau pour en avoir un autre." +#: twitter.php:123 +msgid "No status." +msgstr "Aucun statut" -#: twitter.php:330 -msgid "" -"No consumer key pair for Twitter found. Please contact your site " -"administrator." -msgstr "Aucune clé d'application pour Twitter n'a été trouvée. Merci de contacter l'administrateur de votre site." - -#: twitter.php:343 -msgid "" -"At this Friendica instance the Twitter addon was enabled but you have not " -"yet connected your account to your Twitter account. To do so click the " -"button below to get a PIN from Twitter which you have to copy into the input" -" box below and submit the form. Only your public posts will" -" be posted to Twitter." -msgstr "Sur cette instance de Friendica, le connecteur Twitter a été activé, mais vous n'avez pas encore connecté votre compte local à votre compte Twitter. Pour ce faire, cliquer sur le bouton ci-dessous. Vous obtiendrez alors un 'PIN' de Twitter, que vous devrez copier dans le champ ci-dessous, puis soumettre le formulaire. Seules vos publications publiques seront transmises à Twitter." - -#: twitter.php:344 -msgid "Log in with Twitter" -msgstr "Se connecter avec Twitter" - -#: twitter.php:346 -msgid "Copy the PIN from Twitter here" -msgstr "Copier le PIN de Twitter ici" - -#: twitter.php:354 twitter.php:399 -msgid "An error occured: " -msgstr "Une erreur est survenue :" - -#: twitter.php:368 -#, php-format -msgid "" -"Currently connected to: %1$s" -msgstr "Actuellement connecté à : %1$s" - -#: twitter.php:374 -msgid "" -"Note: Due to your privacy settings (Hide your profile " -"details from unknown viewers?) the link potentially included in public " -"postings relayed to Twitter will lead the visitor to a blank page informing " -"the visitor that the access to your profile has been restricted." -msgstr "Note: Du fait de vos paramètres de vie privée (Cacher les détails de votre profil des visiteurs inconnus?), le lien potentiellement inclus dans les publications publiques relayées vers Twitter conduira les visiteurs vers une page blanche les informant que leur accès à votre profil a été restreint." - -#: twitter.php:381 -msgid "Invalid Twitter info" -msgstr "Informations Twitter invalides" - -#: twitter.php:382 -msgid "Disconnect" -msgstr "Se déconnecter" - -#: twitter.php:387 +#: twitter.php:129 msgid "Allow posting to Twitter" msgstr "Autoriser la publication sur Twitter" -#: twitter.php:387 +#: twitter.php:129 msgid "" "If enabled all your public postings can be posted to the " "associated Twitter account. You can choose to do so by default (here) or for" " every posting separately in the posting options when writing the entry." msgstr "En cas d'activation, toutes vos publications publiques seront transmises au compte Twitter associé. Vous pourrez choisir de le faire par défaut (ici), ou bien pour chaque publication séparément lors de sa rédaction." -#: twitter.php:388 +#: twitter.php:130 msgid "Send public postings to Twitter by default" msgstr "Envoyer par défaut les publications publiques sur Twitter" -#: twitter.php:389 -msgid "Use threads instead of truncating the content" -msgstr "Utiliser des fils de discussion (threads) au lieu de tronquer le contenu" +#: twitter.php:131 +msgid "API Key" +msgstr "Clé API" -#: twitter.php:390 -msgid "Mirror all posts from twitter that are no replies" -msgstr "Synchroniser toutes les publications de Twitter qui ne sont pas des réponses" +#: twitter.php:132 +msgid "API Secret" +msgstr "Secret API" -#: twitter.php:391 -msgid "Import the remote timeline" -msgstr "Importer la Timeline distante" +#: twitter.php:133 +msgid "Access Token" +msgstr "Token Accès" -#: twitter.php:392 -msgid "Automatically create contacts" -msgstr "Créer automatiquement les contacts" +#: twitter.php:134 +msgid "Access Secret" +msgstr "Secret Accès" -#: twitter.php:392 +#: twitter.php:135 msgid "" -"This will automatically create a contact in Friendica as soon as you receive" -" a message from an existing contact via the Twitter network. If you do not " -"enable this, you need to manually add those Twitter contacts in Friendica " -"from whom you would like to see posts here." -msgstr "Cela va automatiquement créer un contact dans Friendica dès qu'une publication d'un contact existant est reçue de Twitter. Si vous n'activez pas ceci, vous devrez ajouter manuellement ces contacts dans Friendica afin d'y voir leurs publications." +"Each user needs to register their own app to be able to post to Twitter. " +"Please visit https://developer.twitter.com/en/portal/projects-and-apps to " +"register a project. Inside the project you then have to register an app. You" +" will find the needed data for the connector on the page \"Keys and token\" " +"in the app settings." +msgstr "Chaque utilisateur doit enregistrer sa propre application pour pouvoir publier des messages sur Twitter. Allez sur https://developer.twitter.com/en/portal/projects-and-apps pour enregistrer un projet. Dans le projet, vous devez ensuite enregistrer une application. Vous trouverez les données nécessaires pour le connecteur sur la page \"Keys and token\" dans les paramètres de l'application." -#: twitter.php:393 -msgid "Follow in fediverse" -msgstr "Suivre dans le fediverse" +#: twitter.php:136 +msgid "Last Status Summary" +msgstr "Résumé du dernier statut" -#: twitter.php:393 -msgid "" -"Automatically subscribe to the contact in the fediverse, when a fediverse " -"account is mentioned in name or description and we are following the Twitter" -" contact." -msgstr "Suivre automatiquement le contact dans le fediverse, quand un compte fediverse est mentionné dans le nom ou la description et que le contact Twitter est suivi." +#: twitter.php:137 +msgid "Last Status Content" +msgstr "Contenu du dernier statut" -#: twitter.php:406 -msgid "Twitter Import/Export/Mirror" -msgstr "Importation/Exportation/Synchronisation avec Twitter" - -#: twitter.php:558 -msgid "" -"Please connect a Twitter account in your Social Network settings to import " -"Twitter posts." -msgstr "Merci de connecter un compte Twitter depuis vos Paramètres de réseaux sociaux afin d'importer les publications Twitter." - -#: twitter.php:565 -msgid "Twitter post not found." -msgstr "Publication Twitter non trouvée." - -#: twitter.php:965 -msgid "Save Settings" -msgstr "Sauvegarder les paramètres" - -#: twitter.php:967 -msgid "Consumer key" -msgstr "Consumer key" - -#: twitter.php:968 -msgid "Consumer secret" -msgstr "Consumer secret" - -#: twitter.php:1167 -#, php-format -msgid "%s on Twitter" -msgstr "%s sur Twitter" +#: twitter.php:142 +msgid "Twitter Export" +msgstr "Export Twitter" diff --git a/twitter/lang/fr/strings.php b/twitter/lang/fr/strings.php index ff46a3866..d75116e9a 100644 --- a/twitter/lang/fr/strings.php +++ b/twitter/lang/fr/strings.php @@ -6,30 +6,15 @@ function string_plural_select_fr($n){ if (($n == 0 || $n == 1)) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } }} $a->strings['Post to Twitter'] = 'Publier sur Twitter'; -$a->strings['You submitted an empty PIN, please Sign In with Twitter again to get a new one.'] = 'Vous avez envoyé un PIN vide, veuillez vous connecter à Twitter à nouveau pour en avoir un autre.'; -$a->strings['No consumer key pair for Twitter found. Please contact your site administrator.'] = 'Aucune clé d\'application pour Twitter n\'a été trouvée. Merci de contacter l\'administrateur de votre site.'; -$a->strings['At this Friendica instance the Twitter addon was enabled but you have not yet connected your account to your Twitter account. To do so click the button below to get a PIN from Twitter which you have to copy into the input box below and submit the form. Only your public posts will be posted to Twitter.'] = 'Sur cette instance de Friendica, le connecteur Twitter a été activé, mais vous n\'avez pas encore connecté votre compte local à votre compte Twitter. Pour ce faire, cliquer sur le bouton ci-dessous. Vous obtiendrez alors un \'PIN\' de Twitter, que vous devrez copier dans le champ ci-dessous, puis soumettre le formulaire. Seules vos publications publiques seront transmises à Twitter.'; -$a->strings['Log in with Twitter'] = 'Se connecter avec Twitter'; -$a->strings['Copy the PIN from Twitter here'] = 'Copier le PIN de Twitter ici'; -$a->strings['An error occured: '] = 'Une erreur est survenue :'; -$a->strings['Currently connected to: %1$s'] = 'Actuellement connecté à : %1$s'; -$a->strings['Note: Due to your privacy settings (Hide your profile details from unknown viewers?) the link potentially included in public postings relayed to Twitter will lead the visitor to a blank page informing the visitor that the access to your profile has been restricted.'] = 'Note: Du fait de vos paramètres de vie privée (Cacher les détails de votre profil des visiteurs inconnus?), le lien potentiellement inclus dans les publications publiques relayées vers Twitter conduira les visiteurs vers une page blanche les informant que leur accès à votre profil a été restreint.'; -$a->strings['Invalid Twitter info'] = 'Informations Twitter invalides'; -$a->strings['Disconnect'] = 'Se déconnecter'; +$a->strings['No status.'] = 'Aucun statut'; $a->strings['Allow posting to Twitter'] = 'Autoriser la publication sur Twitter'; $a->strings['If enabled all your public postings can be posted to the associated Twitter account. You can choose to do so by default (here) or for every posting separately in the posting options when writing the entry.'] = 'En cas d\'activation, toutes vos publications publiques seront transmises au compte Twitter associé. Vous pourrez choisir de le faire par défaut (ici), ou bien pour chaque publication séparément lors de sa rédaction.'; $a->strings['Send public postings to Twitter by default'] = 'Envoyer par défaut les publications publiques sur Twitter'; -$a->strings['Use threads instead of truncating the content'] = 'Utiliser des fils de discussion (threads) au lieu de tronquer le contenu'; -$a->strings['Mirror all posts from twitter that are no replies'] = 'Synchroniser toutes les publications de Twitter qui ne sont pas des réponses'; -$a->strings['Import the remote timeline'] = 'Importer la Timeline distante'; -$a->strings['Automatically create contacts'] = 'Créer automatiquement les contacts'; -$a->strings['This will automatically create a contact in Friendica as soon as you receive a message from an existing contact via the Twitter network. If you do not enable this, you need to manually add those Twitter contacts in Friendica from whom you would like to see posts here.'] = 'Cela va automatiquement créer un contact dans Friendica dès qu\'une publication d\'un contact existant est reçue de Twitter. Si vous n\'activez pas ceci, vous devrez ajouter manuellement ces contacts dans Friendica afin d\'y voir leurs publications.'; -$a->strings['Follow in fediverse'] = 'Suivre dans le fediverse'; -$a->strings['Automatically subscribe to the contact in the fediverse, when a fediverse account is mentioned in name or description and we are following the Twitter contact.'] = 'Suivre automatiquement le contact dans le fediverse, quand un compte fediverse est mentionné dans le nom ou la description et que le contact Twitter est suivi.'; -$a->strings['Twitter Import/Export/Mirror'] = 'Importation/Exportation/Synchronisation avec Twitter'; -$a->strings['Please connect a Twitter account in your Social Network settings to import Twitter posts.'] = 'Merci de connecter un compte Twitter depuis vos Paramètres de réseaux sociaux afin d\'importer les publications Twitter.'; -$a->strings['Twitter post not found.'] = 'Publication Twitter non trouvée.'; -$a->strings['Save Settings'] = 'Sauvegarder les paramètres'; -$a->strings['Consumer key'] = 'Consumer key'; -$a->strings['Consumer secret'] = 'Consumer secret'; -$a->strings['%s on Twitter'] = '%s sur Twitter'; +$a->strings['API Key'] = 'Clé API'; +$a->strings['API Secret'] = 'Secret API'; +$a->strings['Access Token'] = 'Token Accès'; +$a->strings['Access Secret'] = 'Secret Accès'; +$a->strings['Each user needs to register their own app to be able to post to Twitter. Please visit https://developer.twitter.com/en/portal/projects-and-apps to register a project. Inside the project you then have to register an app. You will find the needed data for the connector on the page "Keys and token" in the app settings.'] = 'Chaque utilisateur doit enregistrer sa propre application pour pouvoir publier des messages sur Twitter. Allez sur https://developer.twitter.com/en/portal/projects-and-apps pour enregistrer un projet. Dans le projet, vous devez ensuite enregistrer une application. Vous trouverez les données nécessaires pour le connecteur sur la page "Keys and token" dans les paramètres de l\'application.'; +$a->strings['Last Status Summary'] = 'Résumé du dernier statut'; +$a->strings['Last Status Content'] = 'Contenu du dernier statut'; +$a->strings['Twitter Export'] = 'Export Twitter'; diff --git a/twitter/lang/hu/messages.po b/twitter/lang/hu/messages.po index 7ff281017..a42e3327d 100644 --- a/twitter/lang/hu/messages.po +++ b/twitter/lang/hu/messages.po @@ -4,158 +4,77 @@ # # # Translators: -# Balázs Úr, 2020-2022 +# Balázs Úr, 2020-2023 msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-11-13 10:15+0000\n" +"POT-Creation-Date: 2023-08-16 03:27+0000\n" "PO-Revision-Date: 2014-06-23 12:58+0000\n" -"Last-Translator: Balázs Úr, 2020-2022\n" -"Language-Team: Hungarian (http://www.transifex.com/Friendica/friendica/language/hu/)\n" +"Last-Translator: Balázs Úr, 2020-2023\n" +"Language-Team: Hungarian (http://app.transifex.com/Friendica/friendica/language/hu/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: hu\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: twitter.php:216 +#: twitter.php:84 msgid "Post to Twitter" msgstr "Beküldés a Twitterre" -#: twitter.php:263 -msgid "" -"You submitted an empty PIN, please Sign In with Twitter again to get a new " -"one." -msgstr "Üres PIN-kódot küldött be. Jelentkezzen be a Twitter használatával újra, hogy egy újat kapjon." +#: twitter.php:123 +msgid "No status." +msgstr "Nincs állapot." -#: twitter.php:330 -msgid "" -"No consumer key pair for Twitter found. Please contact your site " -"administrator." -msgstr "Nem találhatók felhasználói kulcspárok a Twitterhez. Vegye fel a kapcsolatot az oldal adminisztrátorával." - -#: twitter.php:343 -msgid "" -"At this Friendica instance the Twitter addon was enabled but you have not " -"yet connected your account to your Twitter account. To do so click the " -"button below to get a PIN from Twitter which you have to copy into the input" -" box below and submit the form. Only your public posts will" -" be posted to Twitter." -msgstr "Ennél a Friendica példánynál a Twitter bővítmény engedélyezve lett, de még nem kapcsolta hozzá a fiókját a Twitter-fiókjához. Ehhez kattintson a lenti gombra, hogy kapjon egy PIN-kódot a Twittertől, amelyet a lenti beviteli mezőbe kell bemásolnia, majd el kell küldenie az űrlapot. Csak a nyilvános bejegyzései lesznek beküldve a Twitterre." - -#: twitter.php:344 -msgid "Log in with Twitter" -msgstr "Bejelentkezés Twitter használatával" - -#: twitter.php:346 -msgid "Copy the PIN from Twitter here" -msgstr "Másolja be ide a Twittertől kapott PIN-kódot" - -#: twitter.php:354 twitter.php:399 -msgid "An error occured: " -msgstr "Hiba történt: " - -#: twitter.php:368 -#, php-format -msgid "" -"Currently connected to: %1$s" -msgstr "Jelenleg ehhez kapcsolódott: %1$s" - -#: twitter.php:374 -msgid "" -"Note: Due to your privacy settings (Hide your profile " -"details from unknown viewers?) the link potentially included in public " -"postings relayed to Twitter will lead the visitor to a blank page informing " -"the visitor that the access to your profile has been restricted." -msgstr "Megjegyzés: az adatvédelmi beállításai miatt (Elrejti a profilja részleteit az ismeretlen megtekintők elől?) a Twitterre továbbított nyilvános beküldésekben vélhetően tartalmazott hivatkozás a látogatót egy üres oldalra fogja vezetni, amely arról tájékoztatja a látogatót, hogy a profiljához való hozzáférés korlátozva lett." - -#: twitter.php:381 -msgid "Invalid Twitter info" -msgstr "Érvénytelen Twitter-információk" - -#: twitter.php:382 -msgid "Disconnect" -msgstr "Leválasztás" - -#: twitter.php:387 +#: twitter.php:129 msgid "Allow posting to Twitter" msgstr "Beküldés engedélyezése a Twitterre" -#: twitter.php:387 +#: twitter.php:129 msgid "" "If enabled all your public postings can be posted to the " "associated Twitter account. You can choose to do so by default (here) or for" " every posting separately in the posting options when writing the entry." msgstr "Ha engedélyezve van, akkor az összes nyilvános beküldés beküldhető a hozzárendelt Twitter-fiókba. Kiválaszthatja, hogy ezt alapértelmezetten szeretné-e (itt), vagy minden egyes beküldésnél különállóan a beküldési beállításokban, amikor megírja a bejegyzést." -#: twitter.php:388 +#: twitter.php:130 msgid "Send public postings to Twitter by default" msgstr "Nyilvános beküldések küldése a Twitterre alapértelmezetten" -#: twitter.php:389 -msgid "Use threads instead of truncating the content" -msgstr "Szálak használata a tartalom csonkítása helyett" +#: twitter.php:131 +msgid "API Key" +msgstr "API-kulcs" -#: twitter.php:390 -msgid "Mirror all posts from twitter that are no replies" -msgstr "A Twittertől származó összes bejegyzés tükrözése, amelyek nem válaszok" +#: twitter.php:132 +msgid "API Secret" +msgstr "API-titok" -#: twitter.php:391 -msgid "Import the remote timeline" -msgstr "A távoli idővonal importálása" +#: twitter.php:133 +msgid "Access Token" +msgstr "Hozzáférési token" -#: twitter.php:392 -msgid "Automatically create contacts" -msgstr "Partnerek automatikus létrehozása" +#: twitter.php:134 +msgid "Access Secret" +msgstr "Hozzáférési titok" -#: twitter.php:392 +#: twitter.php:135 msgid "" -"This will automatically create a contact in Friendica as soon as you receive" -" a message from an existing contact via the Twitter network. If you do not " -"enable this, you need to manually add those Twitter contacts in Friendica " -"from whom you would like to see posts here." -msgstr "Ez automatikusan létre fog hozni egy partnert a Friendicán, amint üzenetet fogad egy meglévő partnertől a Twitter hálózaton keresztül. Ha ezt nem engedélyezi, akkor kézzel kell hozzáadnia azokat a Twitter-partnereket a Friendicában, akiktől bejegyzéseket szeretne látni itt." +"Each user needs to register their own app to be able to post to Twitter. " +"Please visit https://developer.twitter.com/en/portal/projects-and-apps to " +"register a project. Inside the project you then have to register an app. You" +" will find the needed data for the connector on the page \"Keys and token\" " +"in the app settings." +msgstr "Minden felhasználónak regisztrálnia kell a saját alkalmazását, hogy bejegyzést küldhessen a Twitterre. Látogassa meg a https://developer.twitter.com/en/portal/projects-and-apps oldalt egy projekt regisztrálásához. A projekten belül ezután regisztrálnia kell egy alkalmazást. A csatlakozóhoz szükséges adatokat a „Kulcsok és token” oldalon találja az alkalmazás beállításaiban." -#: twitter.php:393 -msgid "Follow in fediverse" -msgstr "Követés a födiverzumban" +#: twitter.php:136 +msgid "Last Status Summary" +msgstr "Utolsó állapot összegzése" -#: twitter.php:393 -msgid "" -"Automatically subscribe to the contact in the fediverse, when a fediverse " -"account is mentioned in name or description and we are following the Twitter" -" contact." -msgstr "Automatikus feliratkozás a födiverzumban lévő partnerre, ha egy födiverzumfiókot említenek a névben vagy a leírásban, és követjük a Twitter-partnert." +#: twitter.php:137 +msgid "Last Status Content" +msgstr "Utolsó állapot tartalma" -#: twitter.php:406 -msgid "Twitter Import/Export/Mirror" -msgstr "Twitter importálás, exportálás vagy tükrözés" - -#: twitter.php:558 -msgid "" -"Please connect a Twitter account in your Social Network settings to import " -"Twitter posts." -msgstr "Kapcsoljon hozzá egy Twitter-fiókot a közösségi hálózatok beállításában a Twitter-bejegyzések importálásához." - -#: twitter.php:565 -msgid "Twitter post not found." -msgstr "A Twitter-bejegyzés nem található." - -#: twitter.php:965 -msgid "Save Settings" -msgstr "Beállítások mentése" - -#: twitter.php:967 -msgid "Consumer key" -msgstr "Felhasználói kulcs" - -#: twitter.php:968 -msgid "Consumer secret" -msgstr "Felhasználói titok" - -#: twitter.php:1167 -#, php-format -msgid "%s on Twitter" -msgstr "%s a Twitteren" +#: twitter.php:142 +msgid "Twitter Export" +msgstr "Twitter exportálás" diff --git a/twitter/lang/hu/strings.php b/twitter/lang/hu/strings.php index 552ebb3ef..8e2a5084c 100644 --- a/twitter/lang/hu/strings.php +++ b/twitter/lang/hu/strings.php @@ -6,30 +6,15 @@ function string_plural_select_hu($n){ return intval($n != 1); }} $a->strings['Post to Twitter'] = 'Beküldés a Twitterre'; -$a->strings['You submitted an empty PIN, please Sign In with Twitter again to get a new one.'] = 'Üres PIN-kódot küldött be. Jelentkezzen be a Twitter használatával újra, hogy egy újat kapjon.'; -$a->strings['No consumer key pair for Twitter found. Please contact your site administrator.'] = 'Nem találhatók felhasználói kulcspárok a Twitterhez. Vegye fel a kapcsolatot az oldal adminisztrátorával.'; -$a->strings['At this Friendica instance the Twitter addon was enabled but you have not yet connected your account to your Twitter account. To do so click the button below to get a PIN from Twitter which you have to copy into the input box below and submit the form. Only your public posts will be posted to Twitter.'] = 'Ennél a Friendica példánynál a Twitter bővítmény engedélyezve lett, de még nem kapcsolta hozzá a fiókját a Twitter-fiókjához. Ehhez kattintson a lenti gombra, hogy kapjon egy PIN-kódot a Twittertől, amelyet a lenti beviteli mezőbe kell bemásolnia, majd el kell küldenie az űrlapot. Csak a nyilvános bejegyzései lesznek beküldve a Twitterre.'; -$a->strings['Log in with Twitter'] = 'Bejelentkezés Twitter használatával'; -$a->strings['Copy the PIN from Twitter here'] = 'Másolja be ide a Twittertől kapott PIN-kódot'; -$a->strings['An error occured: '] = 'Hiba történt: '; -$a->strings['Currently connected to: %1$s'] = 'Jelenleg ehhez kapcsolódott: %1$s'; -$a->strings['Note: Due to your privacy settings (Hide your profile details from unknown viewers?) the link potentially included in public postings relayed to Twitter will lead the visitor to a blank page informing the visitor that the access to your profile has been restricted.'] = 'Megjegyzés: az adatvédelmi beállításai miatt (Elrejti a profilja részleteit az ismeretlen megtekintők elől?) a Twitterre továbbított nyilvános beküldésekben vélhetően tartalmazott hivatkozás a látogatót egy üres oldalra fogja vezetni, amely arról tájékoztatja a látogatót, hogy a profiljához való hozzáférés korlátozva lett.'; -$a->strings['Invalid Twitter info'] = 'Érvénytelen Twitter-információk'; -$a->strings['Disconnect'] = 'Leválasztás'; +$a->strings['No status.'] = 'Nincs állapot.'; $a->strings['Allow posting to Twitter'] = 'Beküldés engedélyezése a Twitterre'; $a->strings['If enabled all your public postings can be posted to the associated Twitter account. You can choose to do so by default (here) or for every posting separately in the posting options when writing the entry.'] = 'Ha engedélyezve van, akkor az összes nyilvános beküldés beküldhető a hozzárendelt Twitter-fiókba. Kiválaszthatja, hogy ezt alapértelmezetten szeretné-e (itt), vagy minden egyes beküldésnél különállóan a beküldési beállításokban, amikor megírja a bejegyzést.'; $a->strings['Send public postings to Twitter by default'] = 'Nyilvános beküldések küldése a Twitterre alapértelmezetten'; -$a->strings['Use threads instead of truncating the content'] = 'Szálak használata a tartalom csonkítása helyett'; -$a->strings['Mirror all posts from twitter that are no replies'] = 'A Twittertől származó összes bejegyzés tükrözése, amelyek nem válaszok'; -$a->strings['Import the remote timeline'] = 'A távoli idővonal importálása'; -$a->strings['Automatically create contacts'] = 'Partnerek automatikus létrehozása'; -$a->strings['This will automatically create a contact in Friendica as soon as you receive a message from an existing contact via the Twitter network. If you do not enable this, you need to manually add those Twitter contacts in Friendica from whom you would like to see posts here.'] = 'Ez automatikusan létre fog hozni egy partnert a Friendicán, amint üzenetet fogad egy meglévő partnertől a Twitter hálózaton keresztül. Ha ezt nem engedélyezi, akkor kézzel kell hozzáadnia azokat a Twitter-partnereket a Friendicában, akiktől bejegyzéseket szeretne látni itt.'; -$a->strings['Follow in fediverse'] = 'Követés a födiverzumban'; -$a->strings['Automatically subscribe to the contact in the fediverse, when a fediverse account is mentioned in name or description and we are following the Twitter contact.'] = 'Automatikus feliratkozás a födiverzumban lévő partnerre, ha egy födiverzumfiókot említenek a névben vagy a leírásban, és követjük a Twitter-partnert.'; -$a->strings['Twitter Import/Export/Mirror'] = 'Twitter importálás, exportálás vagy tükrözés'; -$a->strings['Please connect a Twitter account in your Social Network settings to import Twitter posts.'] = 'Kapcsoljon hozzá egy Twitter-fiókot a közösségi hálózatok beállításában a Twitter-bejegyzések importálásához.'; -$a->strings['Twitter post not found.'] = 'A Twitter-bejegyzés nem található.'; -$a->strings['Save Settings'] = 'Beállítások mentése'; -$a->strings['Consumer key'] = 'Felhasználói kulcs'; -$a->strings['Consumer secret'] = 'Felhasználói titok'; -$a->strings['%s on Twitter'] = '%s a Twitteren'; +$a->strings['API Key'] = 'API-kulcs'; +$a->strings['API Secret'] = 'API-titok'; +$a->strings['Access Token'] = 'Hozzáférési token'; +$a->strings['Access Secret'] = 'Hozzáférési titok'; +$a->strings['Each user needs to register their own app to be able to post to Twitter. Please visit https://developer.twitter.com/en/portal/projects-and-apps to register a project. Inside the project you then have to register an app. You will find the needed data for the connector on the page "Keys and token" in the app settings.'] = 'Minden felhasználónak regisztrálnia kell a saját alkalmazását, hogy bejegyzést küldhessen a Twitterre. Látogassa meg a https://developer.twitter.com/en/portal/projects-and-apps oldalt egy projekt regisztrálásához. A projekten belül ezután regisztrálnia kell egy alkalmazást. A csatlakozóhoz szükséges adatokat a „Kulcsok és token” oldalon találja az alkalmazás beállításaiban.'; +$a->strings['Last Status Summary'] = 'Utolsó állapot összegzése'; +$a->strings['Last Status Content'] = 'Utolsó állapot tartalma'; +$a->strings['Twitter Export'] = 'Twitter exportálás'; diff --git a/twitter/lang/it/messages.po b/twitter/lang/it/messages.po index 998059b61..dfb7adb22 100644 --- a/twitter/lang/it/messages.po +++ b/twitter/lang/it/messages.po @@ -10,7 +10,7 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-11-13 10:15+0000\n" +"POT-Creation-Date: 2023-08-16 03:27+0000\n" "PO-Revision-Date: 2014-06-23 12:58+0000\n" "Last-Translator: Sylke Vicious , 2020\n" "Language-Team: Italian (http://app.transifex.com/Friendica/friendica/language/it/)\n" @@ -20,143 +20,62 @@ msgstr "" "Language: it\n" "Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" -#: twitter.php:216 +#: twitter.php:84 msgid "Post to Twitter" msgstr "Invia a Twitter" -#: twitter.php:263 -msgid "" -"You submitted an empty PIN, please Sign In with Twitter again to get a new " -"one." -msgstr "Hai inserito un PIN vuoto, autenticati con Twitter nuovamente per averne uno nuovo." - -#: twitter.php:330 -msgid "" -"No consumer key pair for Twitter found. Please contact your site " -"administrator." -msgstr "Nessuna coppia di chiavi per Twitter trovata. Contatta l'amministratore del sito." - -#: twitter.php:343 -msgid "" -"At this Friendica instance the Twitter addon was enabled but you have not " -"yet connected your account to your Twitter account. To do so click the " -"button below to get a PIN from Twitter which you have to copy into the input" -" box below and submit the form. Only your public posts will" -" be posted to Twitter." -msgstr "Il componente aggiuntivo Twitter è abilitato ma non hai ancora collegato i tuoi account Friendica e Twitter. Per farlo, clicca il bottone qui sotto per ricevere un PIN da Twitter che dovrai copiare nel campo qui sotto. Solo i tuoi messaggi pubblici saranno inviati a Twitter." - -#: twitter.php:344 -msgid "Log in with Twitter" -msgstr "Accedi con Twitter" - -#: twitter.php:346 -msgid "Copy the PIN from Twitter here" -msgstr "Copia il PIN da Twitter qui" - -#: twitter.php:354 twitter.php:399 -msgid "An error occured: " -msgstr "Si è verificato un errore:" - -#: twitter.php:368 -#, php-format -msgid "" -"Currently connected to: %1$s" +#: twitter.php:123 +msgid "No status." msgstr "" -#: twitter.php:374 -msgid "" -"Note: Due to your privacy settings (Hide your profile " -"details from unknown viewers?) the link potentially included in public " -"postings relayed to Twitter will lead the visitor to a blank page informing " -"the visitor that the access to your profile has been restricted." -msgstr "Nota: A causa delle tue impostazioni di privacy(Nascondi i dettagli del tuo profilo ai visitatori sconosciuti?) il collegamento potenzialmente incluso nei messaggi pubblici inviati a Twitter porterà i visitatori a una pagina bianca con una nota che li informa che l'accesso al tuo profilo è stato limitato." - -#: twitter.php:381 -msgid "Invalid Twitter info" -msgstr "" - -#: twitter.php:382 -msgid "Disconnect" -msgstr "Disconnetti" - -#: twitter.php:387 +#: twitter.php:129 msgid "Allow posting to Twitter" msgstr "Permetti l'invio a Twitter" -#: twitter.php:387 +#: twitter.php:129 msgid "" "If enabled all your public postings can be posted to the " "associated Twitter account. You can choose to do so by default (here) or for" " every posting separately in the posting options when writing the entry." msgstr "Se abilitato tutti i tuoi messaggi pubblici possono essere inviati all'account Twitter associato. Puoi scegliere di farlo sempre (qui) o ogni volta che invii, nelle impostazioni di privacy del messaggio." -#: twitter.php:388 +#: twitter.php:130 msgid "Send public postings to Twitter by default" msgstr "Invia sempre i messaggi pubblici a Twitter" -#: twitter.php:389 -msgid "Use threads instead of truncating the content" +#: twitter.php:131 +msgid "API Key" msgstr "" -#: twitter.php:390 -msgid "Mirror all posts from twitter that are no replies" -msgstr "Clona tutti i messaggi da Twitter che non sono risposte" +#: twitter.php:132 +msgid "API Secret" +msgstr "" -#: twitter.php:391 -msgid "Import the remote timeline" -msgstr "Importa la timeline remota" +#: twitter.php:133 +msgid "Access Token" +msgstr "" -#: twitter.php:392 -msgid "Automatically create contacts" -msgstr "Crea automaticamente i contatti" +#: twitter.php:134 +msgid "Access Secret" +msgstr "" -#: twitter.php:392 +#: twitter.php:135 msgid "" -"This will automatically create a contact in Friendica as soon as you receive" -" a message from an existing contact via the Twitter network. If you do not " -"enable this, you need to manually add those Twitter contacts in Friendica " -"from whom you would like to see posts here." +"Each user needs to register their own app to be able to post to Twitter. " +"Please visit https://developer.twitter.com/en/portal/projects-and-apps to " +"register a project. Inside the project you then have to register an app. You" +" will find the needed data for the connector on the page \"Keys and token\" " +"in the app settings." msgstr "" -#: twitter.php:393 -msgid "Follow in fediverse" +#: twitter.php:136 +msgid "Last Status Summary" msgstr "" -#: twitter.php:393 -msgid "" -"Automatically subscribe to the contact in the fediverse, when a fediverse " -"account is mentioned in name or description and we are following the Twitter" -" contact." +#: twitter.php:137 +msgid "Last Status Content" msgstr "" -#: twitter.php:406 -msgid "Twitter Import/Export/Mirror" -msgstr "Importa/Esporta/Clona Twitter" - -#: twitter.php:558 -msgid "" -"Please connect a Twitter account in your Social Network settings to import " -"Twitter posts." +#: twitter.php:142 +msgid "Twitter Export" msgstr "" - -#: twitter.php:565 -msgid "Twitter post not found." -msgstr "" - -#: twitter.php:965 -msgid "Save Settings" -msgstr "Salva Impostazioni" - -#: twitter.php:967 -msgid "Consumer key" -msgstr "Consumer key" - -#: twitter.php:968 -msgid "Consumer secret" -msgstr "Consumer secret" - -#: twitter.php:1167 -#, php-format -msgid "%s on Twitter" -msgstr "%s su Twitter" diff --git a/twitter/lang/it/strings.php b/twitter/lang/it/strings.php index 954e4bdee..f744c2428 100644 --- a/twitter/lang/it/strings.php +++ b/twitter/lang/it/strings.php @@ -6,22 +6,6 @@ function string_plural_select_it($n){ if ($n == 1) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } }} $a->strings['Post to Twitter'] = 'Invia a Twitter'; -$a->strings['You submitted an empty PIN, please Sign In with Twitter again to get a new one.'] = 'Hai inserito un PIN vuoto, autenticati con Twitter nuovamente per averne uno nuovo.'; -$a->strings['No consumer key pair for Twitter found. Please contact your site administrator.'] = 'Nessuna coppia di chiavi per Twitter trovata. Contatta l\'amministratore del sito.'; -$a->strings['At this Friendica instance the Twitter addon was enabled but you have not yet connected your account to your Twitter account. To do so click the button below to get a PIN from Twitter which you have to copy into the input box below and submit the form. Only your public posts will be posted to Twitter.'] = 'Il componente aggiuntivo Twitter è abilitato ma non hai ancora collegato i tuoi account Friendica e Twitter. Per farlo, clicca il bottone qui sotto per ricevere un PIN da Twitter che dovrai copiare nel campo qui sotto. Solo i tuoi messaggi pubblici saranno inviati a Twitter.'; -$a->strings['Log in with Twitter'] = 'Accedi con Twitter'; -$a->strings['Copy the PIN from Twitter here'] = 'Copia il PIN da Twitter qui'; -$a->strings['An error occured: '] = 'Si è verificato un errore:'; -$a->strings['Note: Due to your privacy settings (Hide your profile details from unknown viewers?) the link potentially included in public postings relayed to Twitter will lead the visitor to a blank page informing the visitor that the access to your profile has been restricted.'] = 'Nota: A causa delle tue impostazioni di privacy(Nascondi i dettagli del tuo profilo ai visitatori sconosciuti?) il collegamento potenzialmente incluso nei messaggi pubblici inviati a Twitter porterà i visitatori a una pagina bianca con una nota che li informa che l\'accesso al tuo profilo è stato limitato.'; -$a->strings['Disconnect'] = 'Disconnetti'; $a->strings['Allow posting to Twitter'] = 'Permetti l\'invio a Twitter'; $a->strings['If enabled all your public postings can be posted to the associated Twitter account. You can choose to do so by default (here) or for every posting separately in the posting options when writing the entry.'] = 'Se abilitato tutti i tuoi messaggi pubblici possono essere inviati all\'account Twitter associato. Puoi scegliere di farlo sempre (qui) o ogni volta che invii, nelle impostazioni di privacy del messaggio.'; $a->strings['Send public postings to Twitter by default'] = 'Invia sempre i messaggi pubblici a Twitter'; -$a->strings['Mirror all posts from twitter that are no replies'] = 'Clona tutti i messaggi da Twitter che non sono risposte'; -$a->strings['Import the remote timeline'] = 'Importa la timeline remota'; -$a->strings['Automatically create contacts'] = 'Crea automaticamente i contatti'; -$a->strings['Twitter Import/Export/Mirror'] = 'Importa/Esporta/Clona Twitter'; -$a->strings['Save Settings'] = 'Salva Impostazioni'; -$a->strings['Consumer key'] = 'Consumer key'; -$a->strings['Consumer secret'] = 'Consumer secret'; -$a->strings['%s on Twitter'] = '%s su Twitter'; diff --git a/twitter/lang/ja/messages.po b/twitter/lang/ja/messages.po index bc0d4360e..f65c86c1f 100644 --- a/twitter/lang/ja/messages.po +++ b/twitter/lang/ja/messages.po @@ -4,128 +4,77 @@ # # # Translators: -# XMPPはいいぞ, 2021 +# daingewuvzeevisiddfddd, 2021 msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-02-01 18:16+0100\n" -"PO-Revision-Date: 2021-05-19 00:39+0000\n" -"Last-Translator: XMPPはいいぞ\n" -"Language-Team: Japanese (http://www.transifex.com/Friendica/friendica/language/ja/)\n" +"POT-Creation-Date: 2023-08-16 03:27+0000\n" +"PO-Revision-Date: 2014-06-23 12:58+0000\n" +"Last-Translator: daingewuvzeevisiddfddd, 2021\n" +"Language-Team: Japanese (http://app.transifex.com/Friendica/friendica/language/ja/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ja\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: twitter.php:189 +#: twitter.php:84 msgid "Post to Twitter" msgstr "Twitterに投稿" -#: twitter.php:234 -msgid "" -"You submitted an empty PIN, please Sign In with Twitter again to get a new " -"one." -msgstr "空のPINを送信しました。もう一度Twitterでサインインして新しいPINを取得してください。" +#: twitter.php:123 +msgid "No status." +msgstr "" -#: twitter.php:291 twitter.php:295 -msgid "Twitter Import/Export/Mirror" -msgstr "Twitterインポート/エクスポート/ミラー" - -#: twitter.php:302 -msgid "" -"No consumer key pair for Twitter found. Please contact your site " -"administrator." -msgstr "Twitterのコンシューマキーペアが見つかりません。サイト管理者に連絡してください。" - -#: twitter.php:314 -msgid "" -"At this Friendica instance the Twitter addon was enabled but you have not " -"yet connected your account to your Twitter account. To do so click the " -"button below to get a PIN from Twitter which you have to copy into the input" -" box below and submit the form. Only your public posts will" -" be posted to Twitter." -msgstr "このFriendicaインスタンスでは、Twitterアドオンは有効になっていますが、アカウントをTwitterアカウントにまだ接続していません。これを行うには、下のボタンをクリックしてTwitterからPINを取得し、それを下の入力ボックスにコピーしてフォームを送信する必要があります。 一般公開投稿のみがTwitterに投稿されます。" - -#: twitter.php:315 -msgid "Log in with Twitter" -msgstr "Twitterでログイン" - -#: twitter.php:317 -msgid "Copy the PIN from Twitter here" -msgstr "ここからTwitterからPINをコピーします" - -#: twitter.php:322 twitter.php:377 twitter.php:768 -msgid "Save Settings" -msgstr "設定を保存する" - -#: twitter.php:324 twitter.php:379 -msgid "An error occured: " -msgstr "エラーが発生しました:" - -#: twitter.php:341 -msgid "Currently connected to: " -msgstr "現在接続中:" - -#: twitter.php:342 twitter.php:352 -msgid "Disconnect" -msgstr "切断する" - -#: twitter.php:359 +#: twitter.php:129 msgid "Allow posting to Twitter" msgstr "Twitterへの投稿を許可する" -#: twitter.php:359 +#: twitter.php:129 msgid "" "If enabled all your public postings can be posted to the " "associated Twitter account. You can choose to do so by default (here) or for" " every posting separately in the posting options when writing the entry." msgstr "有効にすると、すべての一般公開投稿を、関連づけたTwitterアカウントに投稿できます。デフォルト(ここ)で行うか、エントリを書き込む際に投稿オプションですべての投稿を個別に行うかを選択できます。" -#: twitter.php:362 -msgid "" -"Note: Due to your privacy settings (Hide your profile " -"details from unknown viewers?) the link potentially included in public " -"postings relayed to Twitter will lead the visitor to a blank page informing " -"the visitor that the access to your profile has been restricted." -msgstr ":プライバシー設定(未知の視聴者からプロフィールの詳細を非表示にしますか?)により、Twitterに中継・公開される投稿内のリンクは、プロフィールへのアクセスが制限されている訪問者に対して空白ページを表示します。" - -#: twitter.php:365 +#: twitter.php:130 msgid "Send public postings to Twitter by default" msgstr "デフォルトでTwitterに一般公開投稿を送信する" -#: twitter.php:368 -msgid "Mirror all posts from twitter that are no replies" -msgstr "返信がないTwitterのすべての投稿をミラーリングする" - -#: twitter.php:371 -msgid "Import the remote timeline" -msgstr "リモートタイムラインをインポートする" - -#: twitter.php:374 -msgid "Automatically create contacts" -msgstr "連絡先を自動的に作成する" - -#: twitter.php:374 -msgid "" -"This will automatically create a contact in Friendica as soon as you receive" -" a message from an existing contact via the Twitter network. If you do not " -"enable this, you need to manually add those Twitter contacts in Friendica " -"from whom you would like to see posts here. However if enabled, you cannot " -"merely remove a twitter contact from the Friendica contact list, as it will " -"recreate this contact when they post again." -msgstr "これにより、Twitterネットワーク経由で既存の連絡先からメッセージを受信するとすぐに、Friendicaに連絡先が自動的に作成されます。これを有効にしない場合、ここで投稿を表示するFriendicaのTwitter連絡先を手動で追加する必要があります。ただし、有効にした場合、Twitterの連絡先をFriendicaの連絡先リストから単に削除することはできません。再送信するとこの連絡先が再作成されるためです。" - -#: twitter.php:770 -msgid "Consumer key" -msgstr "コンシューマ キー" - -#: twitter.php:771 -msgid "Consumer secret" -msgstr "コンシューマ シークレット" - -#: twitter.php:967 -#, php-format -msgid "%s on Twitter" +#: twitter.php:131 +msgid "API Key" +msgstr "" + +#: twitter.php:132 +msgid "API Secret" +msgstr "" + +#: twitter.php:133 +msgid "Access Token" +msgstr "" + +#: twitter.php:134 +msgid "Access Secret" +msgstr "" + +#: twitter.php:135 +msgid "" +"Each user needs to register their own app to be able to post to Twitter. " +"Please visit https://developer.twitter.com/en/portal/projects-and-apps to " +"register a project. Inside the project you then have to register an app. You" +" will find the needed data for the connector on the page \"Keys and token\" " +"in the app settings." +msgstr "" + +#: twitter.php:136 +msgid "Last Status Summary" +msgstr "" + +#: twitter.php:137 +msgid "Last Status Content" +msgstr "" + +#: twitter.php:142 +msgid "Twitter Export" msgstr "" diff --git a/twitter/lang/ja/strings.php b/twitter/lang/ja/strings.php index 935058fbb..9fda41066 100644 --- a/twitter/lang/ja/strings.php +++ b/twitter/lang/ja/strings.php @@ -6,23 +6,6 @@ function string_plural_select_ja($n){ return intval(0); }} $a->strings['Post to Twitter'] = 'Twitterに投稿'; -$a->strings['You submitted an empty PIN, please Sign In with Twitter again to get a new one.'] = '空のPINを送信しました。もう一度Twitterでサインインして新しいPINを取得してください。'; -$a->strings['Twitter Import/Export/Mirror'] = 'Twitterインポート/エクスポート/ミラー'; -$a->strings['No consumer key pair for Twitter found. Please contact your site administrator.'] = 'Twitterのコンシューマキーペアが見つかりません。サイト管理者に連絡してください。'; -$a->strings['At this Friendica instance the Twitter addon was enabled but you have not yet connected your account to your Twitter account. To do so click the button below to get a PIN from Twitter which you have to copy into the input box below and submit the form. Only your public posts will be posted to Twitter.'] = 'このFriendicaインスタンスでは、Twitterアドオンは有効になっていますが、アカウントをTwitterアカウントにまだ接続していません。これを行うには、下のボタンをクリックしてTwitterからPINを取得し、それを下の入力ボックスにコピーしてフォームを送信する必要があります。 一般公開投稿のみがTwitterに投稿されます。'; -$a->strings['Log in with Twitter'] = 'Twitterでログイン'; -$a->strings['Copy the PIN from Twitter here'] = 'ここからTwitterからPINをコピーします'; -$a->strings['Save Settings'] = '設定を保存する'; -$a->strings['An error occured: '] = 'エラーが発生しました:'; -$a->strings['Currently connected to: '] = '現在接続中:'; -$a->strings['Disconnect'] = '切断する'; $a->strings['Allow posting to Twitter'] = 'Twitterへの投稿を許可する'; $a->strings['If enabled all your public postings can be posted to the associated Twitter account. You can choose to do so by default (here) or for every posting separately in the posting options when writing the entry.'] = '有効にすると、すべての一般公開投稿を、関連づけたTwitterアカウントに投稿できます。デフォルト(ここ)で行うか、エントリを書き込む際に投稿オプションですべての投稿を個別に行うかを選択できます。'; -$a->strings['Note: Due to your privacy settings (Hide your profile details from unknown viewers?) the link potentially included in public postings relayed to Twitter will lead the visitor to a blank page informing the visitor that the access to your profile has been restricted.'] = ':プライバシー設定(未知の視聴者からプロフィールの詳細を非表示にしますか?)により、Twitterに中継・公開される投稿内のリンクは、プロフィールへのアクセスが制限されている訪問者に対して空白ページを表示します。'; $a->strings['Send public postings to Twitter by default'] = 'デフォルトでTwitterに一般公開投稿を送信する'; -$a->strings['Mirror all posts from twitter that are no replies'] = '返信がないTwitterのすべての投稿をミラーリングする'; -$a->strings['Import the remote timeline'] = 'リモートタイムラインをインポートする'; -$a->strings['Automatically create contacts'] = '連絡先を自動的に作成する'; -$a->strings['This will automatically create a contact in Friendica as soon as you receive a message from an existing contact via the Twitter network. If you do not enable this, you need to manually add those Twitter contacts in Friendica from whom you would like to see posts here. However if enabled, you cannot merely remove a twitter contact from the Friendica contact list, as it will recreate this contact when they post again.'] = 'これにより、Twitterネットワーク経由で既存の連絡先からメッセージを受信するとすぐに、Friendicaに連絡先が自動的に作成されます。これを有効にしない場合、ここで投稿を表示するFriendicaのTwitter連絡先を手動で追加する必要があります。ただし、有効にした場合、Twitterの連絡先をFriendicaの連絡先リストから単に削除することはできません。再送信するとこの連絡先が再作成されるためです。'; -$a->strings['Consumer key'] = 'コンシューマ キー'; -$a->strings['Consumer secret'] = 'コンシューマ シークレット'; diff --git a/twitter/lang/nl/messages.po b/twitter/lang/nl/messages.po index b0af4dc9f..d1f397ae5 100644 --- a/twitter/lang/nl/messages.po +++ b/twitter/lang/nl/messages.po @@ -9,126 +9,72 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-06-02 10:25+0700\n" -"PO-Revision-Date: 2018-08-24 13:56+0000\n" -"Last-Translator: Jeroen De Meerleer \n" -"Language-Team: Dutch (http://www.transifex.com/Friendica/friendica/language/nl/)\n" +"POT-Creation-Date: 2023-08-16 03:27+0000\n" +"PO-Revision-Date: 2014-06-23 12:58+0000\n" +"Last-Translator: Jeroen De Meerleer , 2018\n" +"Language-Team: Dutch (http://app.transifex.com/Friendica/friendica/language/nl/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: nl\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: twitter.php:195 +#: twitter.php:84 msgid "Post to Twitter" msgstr "Plaatsen op Twitter" -#: twitter.php:236 -msgid "" -"You submitted an empty PIN, please Sign In with Twitter again to get a new " -"one." +#: twitter.php:123 +msgid "No status." msgstr "" -#: twitter.php:263 -msgid "Twitter settings updated." -msgstr "Twitter instellingen opgeslagen" - -#: twitter.php:293 twitter.php:297 -msgid "Twitter Import/Export/Mirror" -msgstr "Twitter Import/Exporteren/Spiegelen" - -#: twitter.php:304 -msgid "" -"No consumer key pair for Twitter found. Please contact your site " -"administrator." -msgstr "" - -#: twitter.php:316 -msgid "" -"At this Friendica instance the Twitter addon was enabled but you have not " -"yet connected your account to your Twitter account. To do so click the " -"button below to get a PIN from Twitter which you have to copy into the input" -" box below and submit the form. Only your public posts will" -" be posted to Twitter." -msgstr "" - -#: twitter.php:317 -msgid "Log in with Twitter" -msgstr "" - -#: twitter.php:319 -msgid "Copy the PIN from Twitter here" -msgstr "" - -#: twitter.php:324 twitter.php:366 twitter.php:636 -msgid "Save Settings" -msgstr "Instellingen opslaan" - -#: twitter.php:336 -msgid "Currently connected to: " -msgstr "" - -#: twitter.php:337 -msgid "Disconnect" -msgstr "" - -#: twitter.php:347 +#: twitter.php:129 msgid "Allow posting to Twitter" msgstr "Plaatsen op Twitter toestaan" -#: twitter.php:347 +#: twitter.php:129 msgid "" "If enabled all your public postings can be posted to the " "associated Twitter account. You can choose to do so by default (here) or for" " every posting separately in the posting options when writing the entry." msgstr "" -#: twitter.php:350 -msgid "" -"Note: Due to your privacy settings (Hide your profile " -"details from unknown viewers?) the link potentially included in public " -"postings relayed to Twitter will lead the visitor to a blank page informing " -"the visitor that the access to your profile has been restricted." -msgstr "" - -#: twitter.php:353 +#: twitter.php:130 msgid "Send public postings to Twitter by default" msgstr "Verzend publieke berichten naar Twitter als standaard instellen " -#: twitter.php:356 -msgid "Mirror all posts from twitter that are no replies" +#: twitter.php:131 +msgid "API Key" msgstr "" -#: twitter.php:359 -msgid "Import the remote timeline" +#: twitter.php:132 +msgid "API Secret" msgstr "" -#: twitter.php:362 -msgid "Automatically create contacts" +#: twitter.php:133 +msgid "Access Token" msgstr "" -#: twitter.php:362 +#: twitter.php:134 +msgid "Access Secret" +msgstr "" + +#: twitter.php:135 msgid "" -"This will automatically create a contact in Friendica as soon as you receive" -" a message from an existing contact via the Twitter network. If you do not " -"enable this, you need to manually add those Twitter contacts in Friendica " -"from whom you would like to see posts here. However if enabled, you cannot " -"merely remove a twitter contact from the Friendica contact list, as it will " -"recreate this contact when they post again." +"Each user needs to register their own app to be able to post to Twitter. " +"Please visit https://developer.twitter.com/en/portal/projects-and-apps to " +"register a project. Inside the project you then have to register an app. You" +" will find the needed data for the connector on the page \"Keys and token\" " +"in the app settings." msgstr "" -#: twitter.php:614 -msgid "Twitter post failed. Queued for retry." +#: twitter.php:136 +msgid "Last Status Summary" msgstr "" -#: twitter.php:628 -msgid "Settings updated." -msgstr "Instellingen opgeslagen" - -#: twitter.php:638 -msgid "Consumer key" +#: twitter.php:137 +msgid "Last Status Content" msgstr "" -#: twitter.php:639 -msgid "Consumer secret" +#: twitter.php:142 +msgid "Twitter Export" msgstr "" diff --git a/twitter/lang/nl/strings.php b/twitter/lang/nl/strings.php index 60a1d4abb..41c44f255 100644 --- a/twitter/lang/nl/strings.php +++ b/twitter/lang/nl/strings.php @@ -6,9 +6,5 @@ function string_plural_select_nl($n){ return intval($n != 1); }} $a->strings['Post to Twitter'] = 'Plaatsen op Twitter'; -$a->strings['Twitter settings updated.'] = 'Twitter instellingen opgeslagen'; -$a->strings['Twitter Import/Export/Mirror'] = 'Twitter Import/Exporteren/Spiegelen'; -$a->strings['Save Settings'] = 'Instellingen opslaan'; $a->strings['Allow posting to Twitter'] = 'Plaatsen op Twitter toestaan'; $a->strings['Send public postings to Twitter by default'] = 'Verzend publieke berichten naar Twitter als standaard instellen '; -$a->strings['Settings updated.'] = 'Instellingen opgeslagen'; diff --git a/twitter/lang/pl/messages.po b/twitter/lang/pl/messages.po index adf3809c6..11aaef7cc 100644 --- a/twitter/lang/pl/messages.po +++ b/twitter/lang/pl/messages.po @@ -10,153 +10,72 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-11-13 10:15+0000\n" +"POT-Creation-Date: 2023-08-16 03:27+0000\n" "PO-Revision-Date: 2014-06-23 12:58+0000\n" "Last-Translator: Piotr Strębski , 2022\n" -"Language-Team: Polish (http://www.transifex.com/Friendica/friendica/language/pl/)\n" +"Language-Team: Polish (http://app.transifex.com/Friendica/friendica/language/pl/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: pl\n" "Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n" -#: twitter.php:216 +#: twitter.php:84 msgid "Post to Twitter" msgstr "Opublikuj na Twitterze" -#: twitter.php:263 -msgid "" -"You submitted an empty PIN, please Sign In with Twitter again to get a new " -"one." -msgstr "Przesłałeś pusty kod PIN, zaloguj się ponownie na Twitterze, aby otrzymać nowy." +#: twitter.php:123 +msgid "No status." +msgstr "" -#: twitter.php:330 -msgid "" -"No consumer key pair for Twitter found. Please contact your site " -"administrator." -msgstr "Nie znaleziono pary kluczy konsumpcyjnych dla Twittera. Skontaktuj się z administratorem witryny." - -#: twitter.php:343 -msgid "" -"At this Friendica instance the Twitter addon was enabled but you have not " -"yet connected your account to your Twitter account. To do so click the " -"button below to get a PIN from Twitter which you have to copy into the input" -" box below and submit the form. Only your public posts will" -" be posted to Twitter." -msgstr "W tej instancji Friendica dodatek do Twittera został włączony, ale jeszcze nie podłączyłeś swojego konta do konta na Twitterze. Aby to zrobić, kliknij przycisk poniżej, aby uzyskać numer PIN z Twittera, który musisz skopiować do poniższego pola wprowadzania i przesłać formularz. Tylko Twoje publiczne posty będą publikowane na Twitterze." - -#: twitter.php:344 -msgid "Log in with Twitter" -msgstr "Zaloguj się przez Twitter" - -#: twitter.php:346 -msgid "Copy the PIN from Twitter here" -msgstr "Skopiuj tutaj kod PIN z Twittera" - -#: twitter.php:354 twitter.php:399 -msgid "An error occured: " -msgstr "Wystąpił błąd:" - -#: twitter.php:368 -#, php-format -msgid "" -"Currently connected to: %1$s" -msgstr "Obecnie połączony z: %1$s" - -#: twitter.php:374 -msgid "" -"Note: Due to your privacy settings (Hide your profile " -"details from unknown viewers?) the link potentially included in public " -"postings relayed to Twitter will lead the visitor to a blank page informing " -"the visitor that the access to your profile has been restricted." -msgstr "Uwaga: Ze względu na ustawienia prywatności (Ukryć szczegóły Twojego profilu, przed nieznanymi użytkownikami?) link potencjalnie zawarty w publicznych komentarzach do Twitter doprowadzi użytkownika do pustej strony informowania odwiedzających, że dostęp do Twojego profilu został ograniczony." - -#: twitter.php:381 -msgid "Invalid Twitter info" -msgstr "Nieprawidłowe informacje Twittera" - -#: twitter.php:382 -msgid "Disconnect" -msgstr "Rozłączony" - -#: twitter.php:387 +#: twitter.php:129 msgid "Allow posting to Twitter" msgstr "Zezwalaj na publikowanie na Twitterze" -#: twitter.php:387 +#: twitter.php:129 msgid "" "If enabled all your public postings can be posted to the " "associated Twitter account. You can choose to do so by default (here) or for" " every posting separately in the posting options when writing the entry." msgstr "Jeśli ta opcja jest włączona, wszystkie twoje publiczne ogłoszenia mogą być wysyłane na powiązane konto Twitter. Możesz to zrobić domyślnie (tutaj) lub dla każdego komentarza osobno w opcjach komentarza podczas pisania wpisu." -#: twitter.php:388 +#: twitter.php:130 msgid "Send public postings to Twitter by default" msgstr "Wyślij domyślnie komentarze publiczne do Twitter" -#: twitter.php:389 -msgid "Use threads instead of truncating the content" -msgstr "Używaj wątków zamiast obcinania treści" +#: twitter.php:131 +msgid "API Key" +msgstr "" -#: twitter.php:390 -msgid "Mirror all posts from twitter that are no replies" -msgstr "Lustro wszystkich postów Twitter, które są bez odpowiedzi" +#: twitter.php:132 +msgid "API Secret" +msgstr "" -#: twitter.php:391 -msgid "Import the remote timeline" -msgstr "Zaimportuj zdalną oś czasu" +#: twitter.php:133 +msgid "Access Token" +msgstr "" -#: twitter.php:392 -msgid "Automatically create contacts" -msgstr "Automatycznie twórz kontakty" +#: twitter.php:134 +msgid "Access Secret" +msgstr "" -#: twitter.php:392 +#: twitter.php:135 msgid "" -"This will automatically create a contact in Friendica as soon as you receive" -" a message from an existing contact via the Twitter network. If you do not " -"enable this, you need to manually add those Twitter contacts in Friendica " -"from whom you would like to see posts here." -msgstr "Spowoduje to automatyczne utworzenie kontaktu w Friendica, gdy tylko otrzymasz wiadomość od istniejącego kontaktu za pośrednictwem sieci Twitter. Jeśli nie włączysz tej opcji, musisz ręcznie dodać te kontakty z Twittera w Friendica, od których chciałbyś widzieć tutaj wpisy." +"Each user needs to register their own app to be able to post to Twitter. " +"Please visit https://developer.twitter.com/en/portal/projects-and-apps to " +"register a project. Inside the project you then have to register an app. You" +" will find the needed data for the connector on the page \"Keys and token\" " +"in the app settings." +msgstr "" -#: twitter.php:393 -msgid "Follow in fediverse" -msgstr "Śledź w fediverse" +#: twitter.php:136 +msgid "Last Status Summary" +msgstr "" -#: twitter.php:393 -msgid "" -"Automatically subscribe to the contact in the fediverse, when a fediverse " -"account is mentioned in name or description and we are following the Twitter" -" contact." -msgstr "Automatycznie subskrybuj kontakt w fediverse, gdy konto fediverse jest wymienione w nazwie lub opisie i obserwujesz kontakt na Twitterze." +#: twitter.php:137 +msgid "Last Status Content" +msgstr "" -#: twitter.php:406 -msgid "Twitter Import/Export/Mirror" -msgstr "Twitter Import/Export/Mirror" - -#: twitter.php:558 -msgid "" -"Please connect a Twitter account in your Social Network settings to import " -"Twitter posts." -msgstr "Aby zaimportować wpisy z Twittera, połącz konto Twitter w ustawieniach sieci społecznościowej." - -#: twitter.php:565 -msgid "Twitter post not found." -msgstr "Nie odnaleziono wpisu Twittera." - -#: twitter.php:965 -msgid "Save Settings" -msgstr "Zapisz ustawienia" - -#: twitter.php:967 -msgid "Consumer key" -msgstr "Klucz klienta" - -#: twitter.php:968 -msgid "Consumer secret" -msgstr "Tajny klucz klienta" - -#: twitter.php:1167 -#, php-format -msgid "%s on Twitter" -msgstr "%s na Twitterze" +#: twitter.php:142 +msgid "Twitter Export" +msgstr "" diff --git a/twitter/lang/pl/strings.php b/twitter/lang/pl/strings.php index 3d44c3e5e..d160fa3b3 100644 --- a/twitter/lang/pl/strings.php +++ b/twitter/lang/pl/strings.php @@ -6,30 +6,6 @@ function string_plural_select_pl($n){ if ($n==1) { return 0; } else if (($n%10>=2 && $n%10<=4) && ($n%100<12 || $n%100>14)) { return 1; } else if ($n!=1 && ($n%10>=0 && $n%10<=1) || ($n%10>=5 && $n%10<=9) || ($n%100>=12 && $n%100<=14)) { return 2; } else { return 3; } }} $a->strings['Post to Twitter'] = 'Opublikuj na Twitterze'; -$a->strings['You submitted an empty PIN, please Sign In with Twitter again to get a new one.'] = 'Przesłałeś pusty kod PIN, zaloguj się ponownie na Twitterze, aby otrzymać nowy.'; -$a->strings['No consumer key pair for Twitter found. Please contact your site administrator.'] = 'Nie znaleziono pary kluczy konsumpcyjnych dla Twittera. Skontaktuj się z administratorem witryny.'; -$a->strings['At this Friendica instance the Twitter addon was enabled but you have not yet connected your account to your Twitter account. To do so click the button below to get a PIN from Twitter which you have to copy into the input box below and submit the form. Only your public posts will be posted to Twitter.'] = 'W tej instancji Friendica dodatek do Twittera został włączony, ale jeszcze nie podłączyłeś swojego konta do konta na Twitterze. Aby to zrobić, kliknij przycisk poniżej, aby uzyskać numer PIN z Twittera, który musisz skopiować do poniższego pola wprowadzania i przesłać formularz. Tylko Twoje publiczne posty będą publikowane na Twitterze.'; -$a->strings['Log in with Twitter'] = 'Zaloguj się przez Twitter'; -$a->strings['Copy the PIN from Twitter here'] = 'Skopiuj tutaj kod PIN z Twittera'; -$a->strings['An error occured: '] = 'Wystąpił błąd:'; -$a->strings['Currently connected to: %1$s'] = 'Obecnie połączony z: %1$s'; -$a->strings['Note: Due to your privacy settings (Hide your profile details from unknown viewers?) the link potentially included in public postings relayed to Twitter will lead the visitor to a blank page informing the visitor that the access to your profile has been restricted.'] = 'Uwaga: Ze względu na ustawienia prywatności (Ukryć szczegóły Twojego profilu, przed nieznanymi użytkownikami?) link potencjalnie zawarty w publicznych komentarzach do Twitter doprowadzi użytkownika do pustej strony informowania odwiedzających, że dostęp do Twojego profilu został ograniczony.'; -$a->strings['Invalid Twitter info'] = 'Nieprawidłowe informacje Twittera'; -$a->strings['Disconnect'] = 'Rozłączony'; $a->strings['Allow posting to Twitter'] = 'Zezwalaj na publikowanie na Twitterze'; $a->strings['If enabled all your public postings can be posted to the associated Twitter account. You can choose to do so by default (here) or for every posting separately in the posting options when writing the entry.'] = 'Jeśli ta opcja jest włączona, wszystkie twoje publiczne ogłoszenia mogą być wysyłane na powiązane konto Twitter. Możesz to zrobić domyślnie (tutaj) lub dla każdego komentarza osobno w opcjach komentarza podczas pisania wpisu.'; $a->strings['Send public postings to Twitter by default'] = 'Wyślij domyślnie komentarze publiczne do Twitter'; -$a->strings['Use threads instead of truncating the content'] = 'Używaj wątków zamiast obcinania treści'; -$a->strings['Mirror all posts from twitter that are no replies'] = 'Lustro wszystkich postów Twitter, które są bez odpowiedzi'; -$a->strings['Import the remote timeline'] = 'Zaimportuj zdalną oś czasu'; -$a->strings['Automatically create contacts'] = 'Automatycznie twórz kontakty'; -$a->strings['This will automatically create a contact in Friendica as soon as you receive a message from an existing contact via the Twitter network. If you do not enable this, you need to manually add those Twitter contacts in Friendica from whom you would like to see posts here.'] = 'Spowoduje to automatyczne utworzenie kontaktu w Friendica, gdy tylko otrzymasz wiadomość od istniejącego kontaktu za pośrednictwem sieci Twitter. Jeśli nie włączysz tej opcji, musisz ręcznie dodać te kontakty z Twittera w Friendica, od których chciałbyś widzieć tutaj wpisy.'; -$a->strings['Follow in fediverse'] = 'Śledź w fediverse'; -$a->strings['Automatically subscribe to the contact in the fediverse, when a fediverse account is mentioned in name or description and we are following the Twitter contact.'] = 'Automatycznie subskrybuj kontakt w fediverse, gdy konto fediverse jest wymienione w nazwie lub opisie i obserwujesz kontakt na Twitterze.'; -$a->strings['Twitter Import/Export/Mirror'] = 'Twitter Import/Export/Mirror'; -$a->strings['Please connect a Twitter account in your Social Network settings to import Twitter posts.'] = 'Aby zaimportować wpisy z Twittera, połącz konto Twitter w ustawieniach sieci społecznościowej.'; -$a->strings['Twitter post not found.'] = 'Nie odnaleziono wpisu Twittera.'; -$a->strings['Save Settings'] = 'Zapisz ustawienia'; -$a->strings['Consumer key'] = 'Klucz klienta'; -$a->strings['Consumer secret'] = 'Tajny klucz klienta'; -$a->strings['%s on Twitter'] = '%s na Twitterze'; diff --git a/twitter/lang/ru/messages.po b/twitter/lang/ru/messages.po index 911b2e083..d6b4b442d 100644 --- a/twitter/lang/ru/messages.po +++ b/twitter/lang/ru/messages.po @@ -9,115 +9,72 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-02-27 05:01-0500\n" -"PO-Revision-Date: 2017-04-08 05:49+0000\n" -"Last-Translator: Stanislav N. \n" -"Language-Team: Russian (http://www.transifex.com/Friendica/friendica/language/ru/)\n" +"POT-Creation-Date: 2023-08-16 03:27+0000\n" +"PO-Revision-Date: 2014-06-23 12:58+0000\n" +"Last-Translator: Stanislav N. , 2017\n" +"Language-Team: Russian (http://app.transifex.com/Friendica/friendica/language/ru/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ru\n" "Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);\n" -#: twitter.php:77 +#: twitter.php:84 msgid "Post to Twitter" msgstr "Отправить в Twitter" +#: twitter.php:123 +msgid "No status." +msgstr "" + #: twitter.php:129 -msgid "Twitter settings updated." -msgstr "Настройки Twitter обновлены." +msgid "Allow posting to Twitter" +msgstr "Разрешить отправку сообщений на Twitter" -#: twitter.php:157 -msgid "Twitter Posting Settings" -msgstr "Настройка отправки сообщений в Twitter" - -#: twitter.php:164 -msgid "" -"No consumer key pair for Twitter found. Please contact your site " -"administrator." -msgstr "Не найдено пары потребительских ключей для Twitter. Пожалуйста, обратитесь к администратору сайта." - -#: twitter.php:183 -msgid "" -"At this Friendica instance the Twitter addon was enabled but you have not " -"yet connected your account to your Twitter account. To do so click the " -"button below to get a PIN from Twitter which you have to copy into the input" -" box below and submit the form. Only your public posts will" -" be posted to Twitter." -msgstr "Чтобы подключиться к Twitter аккаунту, нажмите на кнопку ниже, чтобы получить код безопасности от Twitter, который нужно скопировать в поле ввода ниже, и отправить форму. Только ваши публичные сообщения будут отправляться на Twitter." - -#: twitter.php:184 -msgid "Log in with Twitter" -msgstr "Войдите через Twitter" - -#: twitter.php:186 -msgid "Copy the PIN from Twitter here" -msgstr "Скопируйте PIN с Twitter сюда" - -#: twitter.php:191 twitter.php:229 twitter.php:556 -msgid "Submit" -msgstr "Подтвердить" - -#: twitter.php:200 -msgid "Currently connected to: " -msgstr "В настоящее время соединены с: " - -#: twitter.php:201 +#: twitter.php:129 msgid "" "If enabled all your public postings can be posted to the " "associated Twitter account. You can choose to do so by default (here) or for" " every posting separately in the posting options when writing the entry." msgstr "Если включено, то все ваши общественные сообщения могут быть отправлены на связанный аккаунт Twitter. Вы можете сделать это по умолчанию (здесь) или для каждого сообщения отдельно при написании записи." -#: twitter.php:203 -msgid "" -"Note: Due your privacy settings (Hide your profile " -"details from unknown viewers?) the link potentially included in public " -"postings relayed to Twitter will lead the visitor to a blank page informing " -"the visitor that the access to your profile has been restricted." -msgstr "Внимание: Из-за настроек приватности (Hide your profile details from unknown viewers?) ссылка, которая может быть включена в твит, будет вести посетителя на пустую страницу с информированием о том, что доступ к профилю запрещен." - -#: twitter.php:206 -msgid "Allow posting to Twitter" -msgstr "Разрешить отправку сообщений на Twitter" - -#: twitter.php:209 +#: twitter.php:130 msgid "Send public postings to Twitter by default" msgstr "Отправлять сообщения для всех в Twitter по умолчанию" -#: twitter.php:213 -msgid "Mirror all posts from twitter that are no replies or retweets" -msgstr "Получать посты с Twitter у которых нет ответов и ретвитов" +#: twitter.php:131 +msgid "API Key" +msgstr "" -#: twitter.php:217 -msgid "Shortening method that optimizes the tweet" -msgstr "Метод сокращения ссылок для оптимизации твита" +#: twitter.php:132 +msgid "API Secret" +msgstr "" -#: twitter.php:221 -msgid "Send linked #-tags and @-names to Twitter" -msgstr "Отправлять #-теги и @-имена в Twitter ссылками" +#: twitter.php:133 +msgid "Access Token" +msgstr "" -#: twitter.php:226 -msgid "Clear OAuth configuration" -msgstr "Удалить конфигурацию OAuth" +#: twitter.php:134 +msgid "Access Secret" +msgstr "" -#: twitter.php:550 -msgid "Settings updated." -msgstr "Настройки обновлены." - -#: twitter.php:558 -msgid "Consumer key" -msgstr "Consumer key" - -#: twitter.php:559 -msgid "Consumer secret" -msgstr "Consumer secret" - -#: twitter.php:560 -msgid "Name of the Twitter Application" -msgstr "Имя приложения для Twitter" - -#: twitter.php:560 +#: twitter.php:135 msgid "" -"set this to avoid mirroring postings from ~friendica back to ~friendica" -msgstr "установите это для избежания отправки сообщений из Friendica обратно в Friendica" +"Each user needs to register their own app to be able to post to Twitter. " +"Please visit https://developer.twitter.com/en/portal/projects-and-apps to " +"register a project. Inside the project you then have to register an app. You" +" will find the needed data for the connector on the page \"Keys and token\" " +"in the app settings." +msgstr "" + +#: twitter.php:136 +msgid "Last Status Summary" +msgstr "" + +#: twitter.php:137 +msgid "Last Status Content" +msgstr "" + +#: twitter.php:142 +msgid "Twitter Export" +msgstr "" diff --git a/twitter/lang/ru/strings.php b/twitter/lang/ru/strings.php index 237d68bb6..94582c116 100644 --- a/twitter/lang/ru/strings.php +++ b/twitter/lang/ru/strings.php @@ -6,24 +6,6 @@ function string_plural_select_ru($n){ if ($n%10==1 && $n%100!=11) { return 0; } else if ($n%10>=2 && $n%10<=4 && ($n%100<12 || $n%100>14)) { return 1; } else if ($n%10==0 || ($n%10>=5 && $n%10<=9) || ($n%100>=11 && $n%100<=14)) { return 2; } else { return 3; } }} $a->strings['Post to Twitter'] = 'Отправить в Twitter'; -$a->strings['Twitter settings updated.'] = 'Настройки Twitter обновлены.'; -$a->strings['Twitter Posting Settings'] = 'Настройка отправки сообщений в Twitter'; -$a->strings['No consumer key pair for Twitter found. Please contact your site administrator.'] = 'Не найдено пары потребительских ключей для Twitter. Пожалуйста, обратитесь к администратору сайта.'; -$a->strings['At this Friendica instance the Twitter addon was enabled but you have not yet connected your account to your Twitter account. To do so click the button below to get a PIN from Twitter which you have to copy into the input box below and submit the form. Only your public posts will be posted to Twitter.'] = 'Чтобы подключиться к Twitter аккаунту, нажмите на кнопку ниже, чтобы получить код безопасности от Twitter, который нужно скопировать в поле ввода ниже, и отправить форму. Только ваши публичные сообщения будут отправляться на Twitter.'; -$a->strings['Log in with Twitter'] = 'Войдите через Twitter'; -$a->strings['Copy the PIN from Twitter here'] = 'Скопируйте PIN с Twitter сюда'; -$a->strings['Submit'] = 'Подтвердить'; -$a->strings['Currently connected to: '] = 'В настоящее время соединены с: '; -$a->strings['If enabled all your public postings can be posted to the associated Twitter account. You can choose to do so by default (here) or for every posting separately in the posting options when writing the entry.'] = 'Если включено, то все ваши общественные сообщения могут быть отправлены на связанный аккаунт Twitter. Вы можете сделать это по умолчанию (здесь) или для каждого сообщения отдельно при написании записи.'; -$a->strings['Note: Due your privacy settings (Hide your profile details from unknown viewers?) the link potentially included in public postings relayed to Twitter will lead the visitor to a blank page informing the visitor that the access to your profile has been restricted.'] = 'Внимание: Из-за настроек приватности (Hide your profile details from unknown viewers?) ссылка, которая может быть включена в твит, будет вести посетителя на пустую страницу с информированием о том, что доступ к профилю запрещен.'; $a->strings['Allow posting to Twitter'] = 'Разрешить отправку сообщений на Twitter'; +$a->strings['If enabled all your public postings can be posted to the associated Twitter account. You can choose to do so by default (here) or for every posting separately in the posting options when writing the entry.'] = 'Если включено, то все ваши общественные сообщения могут быть отправлены на связанный аккаунт Twitter. Вы можете сделать это по умолчанию (здесь) или для каждого сообщения отдельно при написании записи.'; $a->strings['Send public postings to Twitter by default'] = 'Отправлять сообщения для всех в Twitter по умолчанию'; -$a->strings['Mirror all posts from twitter that are no replies or retweets'] = 'Получать посты с Twitter у которых нет ответов и ретвитов'; -$a->strings['Shortening method that optimizes the tweet'] = 'Метод сокращения ссылок для оптимизации твита'; -$a->strings['Send linked #-tags and @-names to Twitter'] = 'Отправлять #-теги и @-имена в Twitter ссылками'; -$a->strings['Clear OAuth configuration'] = 'Удалить конфигурацию OAuth'; -$a->strings['Settings updated.'] = 'Настройки обновлены.'; -$a->strings['Consumer key'] = 'Consumer key'; -$a->strings['Consumer secret'] = 'Consumer secret'; -$a->strings['Name of the Twitter Application'] = 'Имя приложения для Twitter'; -$a->strings['set this to avoid mirroring postings from ~friendica back to ~friendica'] = 'установите это для избежания отправки сообщений из Friendica обратно в Friendica'; diff --git a/twitter/lang/sv/messages.po b/twitter/lang/sv/messages.po index ccbfe7a79..df5c8ac12 100644 --- a/twitter/lang/sv/messages.po +++ b/twitter/lang/sv/messages.po @@ -10,138 +10,72 @@ msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-27 10:25-0500\n" -"PO-Revision-Date: 2022-01-16 00:56+0000\n" -"Last-Translator: Kristoffer Grundström \n" -"Language-Team: Swedish (http://www.transifex.com/Friendica/friendica/language/sv/)\n" +"POT-Creation-Date: 2023-08-16 03:27+0000\n" +"PO-Revision-Date: 2014-06-23 12:58+0000\n" +"Last-Translator: Kristoffer Grundström , 2022\n" +"Language-Team: Swedish (http://app.transifex.com/Friendica/friendica/language/sv/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: sv\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: twitter.php:213 +#: twitter.php:84 msgid "Post to Twitter" msgstr "" -#: twitter.php:258 -msgid "" -"You submitted an empty PIN, please Sign In with Twitter again to get a new " -"one." +#: twitter.php:123 +msgid "No status." msgstr "" -#: twitter.php:321 -msgid "" -"No consumer key pair for Twitter found. Please contact your site " -"administrator." -msgstr "" - -#: twitter.php:334 -msgid "" -"At this Friendica instance the Twitter addon was enabled but you have not " -"yet connected your account to your Twitter account. To do so click the " -"button below to get a PIN from Twitter which you have to copy into the input" -" box below and submit the form. Only your public posts will" -" be posted to Twitter." -msgstr "" - -#: twitter.php:335 -msgid "Log in with Twitter" -msgstr "Logga in med Twitter" - -#: twitter.php:337 -msgid "Copy the PIN from Twitter here" -msgstr "Kopiera PIN-koden från Twitter här" - -#: twitter.php:345 twitter.php:388 -msgid "An error occured: " -msgstr "" - -#: twitter.php:359 -#, php-format -msgid "" -"Currently connected to: %1$s" -msgstr "" - -#: twitter.php:365 -msgid "" -"Note: Due to your privacy settings (Hide your profile " -"details from unknown viewers?) the link potentially included in public " -"postings relayed to Twitter will lead the visitor to a blank page informing " -"the visitor that the access to your profile has been restricted." -msgstr "" - -#: twitter.php:372 -msgid "Invalid Twitter info" -msgstr "" - -#: twitter.php:373 -msgid "Disconnect" -msgstr "" - -#: twitter.php:378 +#: twitter.php:129 msgid "Allow posting to Twitter" msgstr "" -#: twitter.php:378 +#: twitter.php:129 msgid "" "If enabled all your public postings can be posted to the " "associated Twitter account. You can choose to do so by default (here) or for" " every posting separately in the posting options when writing the entry." msgstr "" -#: twitter.php:379 +#: twitter.php:130 msgid "Send public postings to Twitter by default" msgstr "" -#: twitter.php:380 -msgid "Mirror all posts from twitter that are no replies" +#: twitter.php:131 +msgid "API Key" msgstr "" -#: twitter.php:381 -msgid "Import the remote timeline" +#: twitter.php:132 +msgid "API Secret" msgstr "" -#: twitter.php:382 -msgid "Automatically create contacts" +#: twitter.php:133 +msgid "Access Token" msgstr "" -#: twitter.php:382 +#: twitter.php:134 +msgid "Access Secret" +msgstr "" + +#: twitter.php:135 msgid "" -"This will automatically create a contact in Friendica as soon as you receive" -" a message from an existing contact via the Twitter network. If you do not " -"enable this, you need to manually add those Twitter contacts in Friendica " -"from whom you would like to see posts here." +"Each user needs to register their own app to be able to post to Twitter. " +"Please visit https://developer.twitter.com/en/portal/projects-and-apps to " +"register a project. Inside the project you then have to register an app. You" +" will find the needed data for the connector on the page \"Keys and token\" " +"in the app settings." msgstr "" -#: twitter.php:395 -msgid "Twitter Import/Export/Mirror" +#: twitter.php:136 +msgid "Last Status Summary" msgstr "" -#: twitter.php:547 -msgid "" -"Please connect a Twitter account in your Social Network settings to import " -"Twitter posts." +#: twitter.php:137 +msgid "Last Status Content" msgstr "" -#: twitter.php:554 -msgid "Twitter post not found." -msgstr "" - -#: twitter.php:914 -msgid "Save Settings" -msgstr "" - -#: twitter.php:916 -msgid "Consumer key" -msgstr "Kundnyckel" - -#: twitter.php:917 -msgid "Consumer secret" -msgstr "Kundhemlighet" - -#: twitter.php:1113 -#, php-format -msgid "%s on Twitter" +#: twitter.php:142 +msgid "Twitter Export" msgstr "" diff --git a/twitter/lang/sv/strings.php b/twitter/lang/sv/strings.php index 132001747..72e9772ff 100644 --- a/twitter/lang/sv/strings.php +++ b/twitter/lang/sv/strings.php @@ -5,7 +5,3 @@ function string_plural_select_sv($n){ $n = intval($n); return intval($n != 1); }} -$a->strings['Log in with Twitter'] = 'Logga in med Twitter'; -$a->strings['Copy the PIN from Twitter here'] = 'Kopiera PIN-koden från Twitter här'; -$a->strings['Consumer key'] = 'Kundnyckel'; -$a->strings['Consumer secret'] = 'Kundhemlighet'; From 8ba44cf5c67b7b99107b66a92429a0a1907feb2c Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 18 Dec 2023 17:47:19 +0000 Subject: [PATCH 089/388] Invidious: The addon is now user definable --- invidious/invidious.php | 78 +++++++++++++++++++++++++------- invidious/lang/C/messages.po | 32 ++++++++++--- invidious/templates/settings.tpl | 2 + 3 files changed, 89 insertions(+), 23 deletions(-) create mode 100644 invidious/templates/settings.tpl diff --git a/invidious/invidious.php b/invidious/invidious.php index 7692229db..d6152ce47 100644 --- a/invidious/invidious.php +++ b/invidious/invidious.php @@ -2,26 +2,30 @@ /* * Name: invidious * Description: Replaces links to youtube.com to an invidious instance in all displays of postings on a node. - * Version: 0.2 + * Version: 0.3 * Author: Matthias Ebers + * Author: Michael Vogel * */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\Core\Renderer; use Friendica\DI; +CONST INVIDIOUS_DEFAULT = 'https://invidio.us'; + function invidious_install() { - Hook::register('prepare_body_final', 'addon/invidious/invidious.php', 'invidious_render'); + Hook::register('prepare_body_final', __FILE__, 'invidious_render'); + Hook::register('addon_settings', __FILE__, 'invidious_settings'); + Hook::register('addon_settings_post', __FILE__, 'invidious_settings_post'); } /* Handle the send data from the admin settings */ function invidious_addon_admin_post() { - DI::config()->set('invidious', 'server', rtrim(trim($_POST['invidiousserver']), '/')); + DI::config()->set('invidious', 'server', trim($_POST['invidiousserver'], " \n\r\t\v\x00/")); } /* Hook into the admin settings to let the admin choose an @@ -29,29 +33,71 @@ function invidious_addon_admin_post() */ function invidious_addon_admin(string &$o) { - $invidiousserver = DI::config()->get('invidious', 'server'); + $invidiousserver = DI::config()->get('invidious', 'server', INVIDIOUS_DEFAULT); $t = Renderer::getMarkupTemplate('admin.tpl', 'addon/invidious/'); $o = Renderer::replaceMacros($t, [ '$settingdescription' => DI::l10n()->t('Which Invidious server shall be used for the replacements in the post bodies? Use the URL with servername and protocol. See %s for a list of available public Invidious servers.', 'https://redirect.invidious.io'), - '$invidiousserver' => ['invidiousserver', DI::l10n()->t('Invidious server'), $invidiousserver, 'https://example.com'], - '$submit' => DI::l10n()->t('Save Settings'), + '$invidiousserver' => ['invidiousserver', DI::l10n()->t('Invidious server'), $invidiousserver, DI::l10n()->t('See %s for a list of available Invidious servers.', 'https://api.invidious.io/')], + '$submit' => DI::l10n()->t('Save Settings'), ]); } +function invidious_settings(array &$data) +{ + if (!DI::userSession()->getLocalUserId()) { + return; + } + + $enabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'invidious', 'enabled'); + $server = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'invidious', 'server', DI::config()->get('invidious', 'server', INVIDIOUS_DEFAULT)); + + $t = Renderer::getMarkupTemplate('settings.tpl', 'addon/invidious/'); + $html = Renderer::replaceMacros($t, [ + '$enabled' => ['enabled', DI::l10n()->t('Replace Youtube links with links to an Invidious server'), $enabled, DI::l10n()->t('If enabled, Youtube links are replaced with the links to the specified Invidious server.')], + '$server' => ['server', DI::l10n()->t('Invidious server'), $server, DI::l10n()->t('See %s for a list of available Invidious servers.', 'https://api.invidious.io/')], + ]); + + $data = [ + 'addon' => 'invidious', + 'title' => DI::l10n()->t('Invidious Settings'), + 'html' => $html, + ]; +} + +function invidious_settings_post(array &$b) +{ + if (!DI::userSession()->getLocalUserId() || empty($_POST['invidious-submit'])) { + return; + } + + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'invidious', 'enabled', (bool)$_POST['enabled']); + + $server = trim($_POST['server'], " \n\r\t\v\x00/"); + if ($server != DI::config()->get('invidious', 'server', INVIDIOUS_DEFAULT) && !empty($server)) { + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'invidious', 'server', $server); + } else { + DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'invidious', 'server'); + } +} + /* * replace "youtube.com" with the chosen Invidious instance */ function invidious_render(array &$b) { - // this needs to be a system setting - $replaced = false; - $invidious = DI::config()->get('invidious', 'server', 'https://invidio.us'); - if (strpos($b['html'], 'https://www.youtube.com/') !== false || strpos($b['html'], 'https://youtube.com/') !== false || strpos($b['html'], 'https://youtu.be/') !== false) { - $b['html'] = str_replace('https://youtu.be/', $invidious . '/watch?v=', $b['html']); - $b['html'] = str_replace(['https://www.youtube.com/', 'https://youtube.com/'], $invidious . '/', $b['html']); - $replaced = true; + if (!DI::userSession()->getLocalUserId() || !DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'invidious', 'enabled')) { + return; } - if ($replaced) { - $b['html'] .= '

' . DI::l10n()->t('(Invidious addon enabled: YouTube links via %s)', $invidious) . '

'; + + $original = $b['html']; + $server = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'invidious', 'server', DI::config()->get('invidious', 'server', INVIDIOUS_DEFAULT)); + + $b['html'] = preg_replace("/https?:\/\/www.youtube.com\/watch\?v\=(.*?)/ism", $server . '/watch?v=$1', $b['html']); + $b['html'] = preg_replace("/https?:\/\/www.youtube.com\/embed\/(.*?)/ism", $server . '/embed/$1', $b['html']); + $b['html'] = preg_replace("/https?:\/\/www.youtube.com\/shorts\/(.*?)/ism", $server . '/shorts/$1', $b['html']); + $b['html'] = preg_replace("/https?:\/\/youtu.be\/(.*?)/ism", $server . '/watch?v=$1', $b['html']); + + if ($original != $b['html']) { + $b['html'] .= '

' . DI::l10n()->t('(Invidious addon enabled: YouTube links via %s)', $server) . '

'; } } diff --git a/invidious/lang/C/messages.po b/invidious/lang/C/messages.po index f93a87d6d..b9de496c0 100644 --- a/invidious/lang/C/messages.po +++ b/invidious/lang/C/messages.po @@ -1,4 +1,4 @@ - # ADDON invidious +# ADDON invidious # Copyright (C) # This file is distributed under the same license as the Friendica invidious addon package. # @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-12-03 20:21+0100\n" +"POT-Creation-Date: 2023-12-18 17:23+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,7 +17,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: invidious.php:35 +#: invidious.php:39 #, php-format msgid "" "Which Invidious server shall be used for the replacements in the post " @@ -25,16 +25,34 @@ msgid "" "available public Invidious servers." msgstr "" -#: invidious.php:36 +#: invidious.php:40 invidious.php:57 msgid "Invidious server" msgstr "" -#: invidious.php:37 +#: invidious.php:40 invidious.php:57 +#, php-format +msgid "See %s for a list of available Invidious servers." +msgstr "" + +#: invidious.php:41 msgid "Save Settings" msgstr "" -#: invidious.php:64 +#: invidious.php:56 +msgid "Replace Youtube links with links to an Invidious server" +msgstr "" + +#: invidious.php:56 +msgid "" +"If enabled, Youtube links are replaced with the links to the specified " +"Invidious server." +msgstr "" + +#: invidious.php:62 +msgid "Invidious Settings" +msgstr "" + +#: invidious.php:101 #, php-format msgid "(Invidious addon enabled: YouTube links via %s)" msgstr "" - diff --git a/invidious/templates/settings.tpl b/invidious/templates/settings.tpl new file mode 100644 index 000000000..387286ef3 --- /dev/null +++ b/invidious/templates/settings.tpl @@ -0,0 +1,2 @@ +{{include file="field_checkbox.tpl" field=$enabled}} +{{include file="field_input.tpl" field=$server}} From cabdd924d0defc728860418a23a8bc7796041d54 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 18 Dec 2023 17:51:34 +0000 Subject: [PATCH 090/388] Fix white spaces --- invidious/invidious.php | 60 ++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/invidious/invidious.php b/invidious/invidious.php index d6152ce47..ec16b4dca 100644 --- a/invidious/invidious.php +++ b/invidious/invidious.php @@ -16,7 +16,7 @@ CONST INVIDIOUS_DEFAULT = 'https://invidio.us'; function invidious_install() { - Hook::register('prepare_body_final', __FILE__, 'invidious_render'); + Hook::register('prepare_body_final', __FILE__, 'invidious_render'); Hook::register('addon_settings', __FILE__, 'invidious_settings'); Hook::register('addon_settings_post', __FILE__, 'invidious_settings_post'); } @@ -25,7 +25,7 @@ function invidious_install() */ function invidious_addon_admin_post() { - DI::config()->set('invidious', 'server', trim($_POST['invidiousserver'], " \n\r\t\v\x00/")); + DI::config()->set('invidious', 'server', trim($_POST['invidiousserver'], " \n\r\t\v\x00/")); } /* Hook into the admin settings to let the admin choose an @@ -33,13 +33,13 @@ function invidious_addon_admin_post() */ function invidious_addon_admin(string &$o) { - $invidiousserver = DI::config()->get('invidious', 'server', INVIDIOUS_DEFAULT); - $t = Renderer::getMarkupTemplate('admin.tpl', 'addon/invidious/'); - $o = Renderer::replaceMacros($t, [ - '$settingdescription' => DI::l10n()->t('Which Invidious server shall be used for the replacements in the post bodies? Use the URL with servername and protocol. See %s for a list of available public Invidious servers.', 'https://redirect.invidious.io'), - '$invidiousserver' => ['invidiousserver', DI::l10n()->t('Invidious server'), $invidiousserver, DI::l10n()->t('See %s for a list of available Invidious servers.', 'https://api.invidious.io/')], - '$submit' => DI::l10n()->t('Save Settings'), - ]); + $invidiousserver = DI::config()->get('invidious', 'server', INVIDIOUS_DEFAULT); + $t = Renderer::getMarkupTemplate('admin.tpl', 'addon/invidious/'); + $o = Renderer::replaceMacros($t, [ + '$settingdescription' => DI::l10n()->t('Which Invidious server shall be used for the replacements in the post bodies? Use the URL with servername and protocol. See %s for a list of available public Invidious servers.', 'https://redirect.invidious.io'), + '$invidiousserver' => ['invidiousserver', DI::l10n()->t('Invidious server'), $invidiousserver, DI::l10n()->t('See %s for a list of available Invidious servers.', 'https://api.invidious.io/')], + '$submit' => DI::l10n()->t('Save Settings'), + ]); } function invidious_settings(array &$data) @@ -54,7 +54,7 @@ function invidious_settings(array &$data) $t = Renderer::getMarkupTemplate('settings.tpl', 'addon/invidious/'); $html = Renderer::replaceMacros($t, [ '$enabled' => ['enabled', DI::l10n()->t('Replace Youtube links with links to an Invidious server'), $enabled, DI::l10n()->t('If enabled, Youtube links are replaced with the links to the specified Invidious server.')], - '$server' => ['server', DI::l10n()->t('Invidious server'), $server, DI::l10n()->t('See %s for a list of available Invidious servers.', 'https://api.invidious.io/')], + '$server' => ['server', DI::l10n()->t('Invidious server'), $server, DI::l10n()->t('See %s for a list of available Invidious servers.', 'https://api.invidious.io/')], ]); $data = [ @@ -70,14 +70,14 @@ function invidious_settings_post(array &$b) return; } - DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'invidious', 'enabled', (bool)$_POST['enabled']); + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'invidious', 'enabled', (bool)$_POST['enabled']); - $server = trim($_POST['server'], " \n\r\t\v\x00/"); - if ($server != DI::config()->get('invidious', 'server', INVIDIOUS_DEFAULT) && !empty($server)) { - DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'invidious', 'server', $server); - } else { - DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'invidious', 'server'); - } + $server = trim($_POST['server'], " \n\r\t\v\x00/"); + if ($server != DI::config()->get('invidious', 'server', INVIDIOUS_DEFAULT) && !empty($server)) { + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'invidious', 'server', $server); + } else { + DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'invidious', 'server'); + } } /* @@ -85,19 +85,19 @@ function invidious_settings_post(array &$b) */ function invidious_render(array &$b) { - if (!DI::userSession()->getLocalUserId() || !DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'invidious', 'enabled')) { - return; - } + if (!DI::userSession()->getLocalUserId() || !DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'invidious', 'enabled')) { + return; + } - $original = $b['html']; - $server = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'invidious', 'server', DI::config()->get('invidious', 'server', INVIDIOUS_DEFAULT)); - - $b['html'] = preg_replace("/https?:\/\/www.youtube.com\/watch\?v\=(.*?)/ism", $server . '/watch?v=$1', $b['html']); - $b['html'] = preg_replace("/https?:\/\/www.youtube.com\/embed\/(.*?)/ism", $server . '/embed/$1', $b['html']); - $b['html'] = preg_replace("/https?:\/\/www.youtube.com\/shorts\/(.*?)/ism", $server . '/shorts/$1', $b['html']); - $b['html'] = preg_replace("/https?:\/\/youtu.be\/(.*?)/ism", $server . '/watch?v=$1', $b['html']); + $original = $b['html']; + $server = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'invidious', 'server', DI::config()->get('invidious', 'server', INVIDIOUS_DEFAULT)); + + $b['html'] = preg_replace("/https?:\/\/www.youtube.com\/watch\?v\=(.*?)/ism", $server . '/watch?v=$1', $b['html']); + $b['html'] = preg_replace("/https?:\/\/www.youtube.com\/embed\/(.*?)/ism", $server . '/embed/$1', $b['html']); + $b['html'] = preg_replace("/https?:\/\/www.youtube.com\/shorts\/(.*?)/ism", $server . '/shorts/$1', $b['html']); + $b['html'] = preg_replace("/https?:\/\/youtu.be\/(.*?)/ism", $server . '/watch?v=$1', $b['html']); - if ($original != $b['html']) { - $b['html'] .= '

' . DI::l10n()->t('(Invidious addon enabled: YouTube links via %s)', $server) . '

'; - } + if ($original != $b['html']) { + $b['html'] .= '

' . DI::l10n()->t('(Invidious addon enabled: YouTube links via %s)', $server) . '

'; + } } From 9daa11eb108ff8e82e63816d371939d0415c1247 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Mon, 18 Dec 2023 21:27:36 -0500 Subject: [PATCH 091/388] [woodpecker] Remove PHP 7.3 PHPUnit instance - Friendica now supports at least PHP 7.4 --- .woodpecker/.phpunit.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.woodpecker/.phpunit.yml b/.woodpecker/.phpunit.yml index f198ba2af..a6c5db09a 100644 --- a/.woodpecker/.phpunit.yml +++ b/.woodpecker/.phpunit.yml @@ -1,7 +1,5 @@ matrix: include: - - PHP_MAJOR_VERSION: 7.3 - PHP_VERSION: 7.3.33 - PHP_MAJOR_VERSION: 7.4 PHP_VERSION: 7.4.33 - PHP_MAJOR_VERSION: 8.0 From 3e74af9775ac9863c559422275e6322345a2b73a Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Mon, 18 Dec 2023 21:28:16 -0500 Subject: [PATCH 092/388] [s3_storage] Bump version of akeeba/s3 to version 2.3.1 - Address https://github.com/friendica/friendica/issues/12011#issuecomment-1854681792 --- s3_storage/composer.lock | 19 +- s3_storage/vendor/akeeba/s3/.gitignore | 3 +- s3_storage/vendor/akeeba/s3/README.md | 87 +++-- s3_storage/vendor/akeeba/s3/TODO.md | 13 - s3_storage/vendor/akeeba/s3/composer.json | 17 +- s3_storage/vendor/akeeba/s3/composer.lock | 37 +- s3_storage/vendor/akeeba/s3/minitest/NOTES.md | 62 +++ .../akeeba/s3/minitest/Test/AbstractTest.php | 16 +- .../akeeba/s3/minitest/Test/BigFiles.php | 46 +-- .../s3/minitest/Test/BucketLocation.php | 6 +- .../akeeba/s3/minitest/Test/BucketsList.php | 22 +- .../akeeba/s3/minitest/Test/HeadObject.php | 67 ++++ .../akeeba/s3/minitest/Test/ListFiles.php | 214 +++++----- .../s3/minitest/Test/ListThousandsOfFiles.php | 111 ++++++ .../akeeba/s3/minitest/Test/Multipart.php | 28 +- .../akeeba/s3/minitest/Test/SignedURLs.php | 16 +- .../s3/minitest/Test/SingleSmallFile.php | 43 ++ .../akeeba/s3/minitest/Test/SmallFiles.php | 28 +- .../s3/minitest/Test/SmallFilesNoDelete.php | 6 +- .../s3/minitest/Test/SmallFilesOnlyUpload.php | 8 +- .../s3/minitest/Test/SmallInlineFiles.php | 15 +- .../Test/SmallInlineFilesNoDelete.php | 6 +- .../Test/SmallInlineFilesOnlyUpload.php | 8 +- .../s3/minitest/Test/SmallInlineXMLFiles.php | 131 +++++++ .../s3/minitest/Test/StorageClasses.php | 22 +- .../vendor/akeeba/s3/minitest/config.dist.php | 8 +- .../vendor/akeeba/s3/minitest/minitest.php | 22 +- s3_storage/vendor/akeeba/s3/src/Acl.php | 18 +- .../vendor/akeeba/s3/src/Configuration.php | 14 +- s3_storage/vendor/akeeba/s3/src/Connector.php | 367 ++++++++++-------- .../s3/src/Exception/CannotDeleteFile.php | 6 +- .../s3/src/Exception/CannotGetBucket.php | 6 +- .../akeeba/s3/src/Exception/CannotGetFile.php | 6 +- .../s3/src/Exception/CannotListBuckets.php | 6 +- .../src/Exception/CannotOpenFileForRead.php | 6 +- .../src/Exception/CannotOpenFileForWrite.php | 6 +- .../akeeba/s3/src/Exception/CannotPutFile.php | 6 +- .../s3/src/Exception/ConfigurationError.php | 6 +- .../s3/src/Exception/InvalidAccessKey.php | 6 +- .../akeeba/s3/src/Exception/InvalidBody.php | 6 +- .../s3/src/Exception/InvalidEndpoint.php | 6 +- .../s3/src/Exception/InvalidFilePointer.php | 6 +- .../akeeba/s3/src/Exception/InvalidRegion.php | 6 +- .../s3/src/Exception/InvalidSecretKey.php | 6 +- .../src/Exception/InvalidSignatureMethod.php | 6 +- .../s3/src/Exception/PropertyNotFound.php | 6 +- s3_storage/vendor/akeeba/s3/src/Input.php | 52 ++- s3_storage/vendor/akeeba/s3/src/Request.php | 124 ++++-- s3_storage/vendor/akeeba/s3/src/Response.php | 30 +- .../vendor/akeeba/s3/src/Response/Error.php | 6 +- s3_storage/vendor/akeeba/s3/src/Signature.php | 8 +- .../vendor/akeeba/s3/src/Signature/V2.php | 14 +- .../vendor/akeeba/s3/src/Signature/V4.php | 170 ++++++-- .../vendor/akeeba/s3/src/StorageClass.php | 18 +- s3_storage/vendor/akeeba/s3/src/aliasing.php | 35 ++ .../vendor/composer/autoload_classmap.php | 54 +-- s3_storage/vendor/composer/autoload_files.php | 10 + s3_storage/vendor/composer/autoload_psr4.php | 2 +- s3_storage/vendor/composer/autoload_real.php | 18 + .../vendor/composer/autoload_static.php | 62 +-- s3_storage/vendor/composer/installed.json | 21 +- 61 files changed, 1472 insertions(+), 708 deletions(-) delete mode 100644 s3_storage/vendor/akeeba/s3/TODO.md create mode 100644 s3_storage/vendor/akeeba/s3/minitest/NOTES.md create mode 100644 s3_storage/vendor/akeeba/s3/minitest/Test/HeadObject.php create mode 100644 s3_storage/vendor/akeeba/s3/minitest/Test/ListThousandsOfFiles.php create mode 100644 s3_storage/vendor/akeeba/s3/minitest/Test/SingleSmallFile.php create mode 100644 s3_storage/vendor/akeeba/s3/minitest/Test/SmallInlineXMLFiles.php create mode 100644 s3_storage/vendor/akeeba/s3/src/aliasing.php create mode 100644 s3_storage/vendor/composer/autoload_files.php diff --git a/s3_storage/composer.lock b/s3_storage/composer.lock index 78b10dd9a..992e5a9e3 100644 --- a/s3_storage/composer.lock +++ b/s3_storage/composer.lock @@ -8,32 +8,35 @@ "packages": [ { "name": "akeeba/s3", - "version": "2.0.0", + "version": "2.3.1", "source": { "type": "git", "url": "https://github.com/akeeba/s3.git", - "reference": "01520dae1f736555e08efda0ddc1044701bd340a" + "reference": "7f5b3e929c93eb02ba24472560c0cbbef735aed9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/akeeba/s3/zipball/01520dae1f736555e08efda0ddc1044701bd340a", - "reference": "01520dae1f736555e08efda0ddc1044701bd340a", + "url": "https://api.github.com/repos/akeeba/s3/zipball/7f5b3e929c93eb02ba24472560c0cbbef735aed9", + "reference": "7f5b3e929c93eb02ba24472560c0cbbef735aed9", "shasum": "" }, "require": { "ext-curl": "*", "ext-simplexml": "*", - "php": ">=7.1.0 <8.1" + "php": ">=7.1.0 <8.4" }, "type": "library", "autoload": { + "files": [ + "src/aliasing.php" + ], "psr-4": { - "Akeeba\\Engine\\Postproc\\Connector\\S3v4\\": "src" + "Akeeba\\S3\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "GPL-3.0+" + "GPL-3.0-or-later" ], "authors": [ { @@ -48,7 +51,7 @@ "keywords": [ "s3" ], - "time": "2020-11-30T14:03:55+00:00" + "time": "2023-09-26T11:40:10+00:00" } ], "packages-dev": [], diff --git a/s3_storage/vendor/akeeba/s3/.gitignore b/s3_storage/vendor/akeeba/s3/.gitignore index 54f46f287..09e75c298 100644 --- a/s3_storage/vendor/akeeba/s3/.gitignore +++ b/s3_storage/vendor/akeeba/s3/.gitignore @@ -1,5 +1,6 @@ /.idea/ /000/ -/minitest/config.php +/minitest/config.* +!/minitest/config.dist.php /minitest/tmp /vendor/ diff --git a/s3_storage/vendor/akeeba/s3/README.md b/s3_storage/vendor/akeeba/s3/README.md index d082720c2..eb3c5b531 100644 --- a/s3_storage/vendor/akeeba/s3/README.md +++ b/s3_storage/vendor/akeeba/s3/README.md @@ -4,29 +4,53 @@ A compact, dependency-less Amazon S3 API client implementing the most commonly u ## Why reinvent the wheel -After having a lot of impossible to debug problems with Amazon's Guzzle-based AWS SDK we decided to roll our own connector for Amazon S3. This is by no means a complete implementation, just a small subset of S3's features which are required by our software. The design goals are simplicity, no external dependencies and low memory footprint. +After having a lot of impossible to debug problems with Amazon's Guzzle-based AWS SDK we decided to roll our own connector for Amazon S3. This is by no means a complete implementation, just a small subset of S3's features which are required by our software. The design goals are simplicity, no external dependencies and a low memory footprint. This code was originally based on [S3.php written by Donovan Schonknecht](http://undesigned.org.za/2007/10/22/amazon-s3-php-class) which is available under a BSD-like license. This repository no longer reflects the original author's work and should not be confused with it. -This software is distributed under the GNU General Public License version 3 or, at your option, any later version published by the Free Software Foundation (FSF). In short, it's "GPLv3+". +This software is distributed under the GNU General Public License version 3 or, at your option, any later version published by the Free Software Foundation (FSF). In short, it's GPL-3.0-or-later, as noted in composer.json. -## Important note about version 2 +## Important notes about version 2 -Akeeba Amazon S3 Connector version 2 has dropped support for PPH 5.3 to 7.0 inclusive. It is only compatible with PHP 7.1 or later, up to and including PHP 8.0. +### PHP version support since 2.0 -The most significant change in this version is that all methods use scalar type hints for parameters and return values. This _may_ break existing consumers which relied on implicit type conversion e.g. passing strings containing integer values instead of _actual_ integer values. +Akeeba Amazon S3 Connector version 2 has dropped support for PHP 5.3 to 7.0 inclusive. + +The most significant change in this version is that all methods use scalar type hints for parameters and return values. This _may_ break existing consumers which relied on implicit type conversion. + +### Namespace change since 2.3 + +Up to and including version 2.2 of the library, the namespace was `\Akeeba\Engine\Postproc\Connector\S3v4`. From version 2.3 of the library the namespace has changed to `\Akeeba\S3`. + +The library automatically registers aliases of the old classes to the new ones, thus ensuring updating the library will not introduce backwards incompatible changes. This is why it's not a major version update. Aliases will remain in place until at least version 3.0 of the library. ## Using the connector +You need to define a constant before using or referencing any class in the library: + +```php +defined('AKEEBAENGINE') or define('AKEEBAENGINE', 1); +``` + +All library files have a line similar to + +```php +defined('AKEEBAENGINE') or die(); +``` + +to prevent direct access to the libraries files. This is intentional. The primary use case for this library is mass-distributed software which gets installed in a publicly accessible subdirectory of the web root. This line prevents any accidental path disclosure from PHP error messages if someone were to access these files directly on misconfigured servers. + +If you are writing a Joomla extension, especially a plugin or module, please _always_ check if the constant has already been defined before defining it yourself. Thank you! + ### Get a connector object ```php -$configuration = new \Akeeba\Engine\Postproc\Connector\S3v4\Configuration( +$configuration = new \Akeeba\S3\Configuration( 'YourAmazonAccessKey', 'YourAmazonSecretKey' ); -$connector = new \Akeeba\Engine\Postproc\Connector\S3v4\Connector($configuration); +$connector = new \Akeeba\S3\Connector($configuration); ``` If you are running inside an Amazon EC2 instance you can fetch temporary credentials from the instance's metadata @@ -37,7 +61,7 @@ IP hosting the instance's metadata cache service): $role = file_get_contents('http://169.254.169.254/latest/meta-data/iam/security-credentials/'); $jsonCredentials = file_get_contents('http://169.254.169.254/latest/meta-data/iam/security-credentials/' . $role); $credentials = json_decode($jsonCredentials, true); -$configuration = new \Akeeba\Engine\Postproc\Connector\S3v4\Configuration( +$configuration = new \Akeeba\S3\Configuration( $credentials['AccessKeyId'], $credentials['SecretAccessKey'], 'v4', @@ -45,14 +69,14 @@ $configuration = new \Akeeba\Engine\Postproc\Connector\S3v4\Configuration( ); $configuration->setToken($credentials['Token']); -$connector = new \Akeeba\Engine\Postproc\Connector\S3v4\Connector($configuration); +$connector = new \Akeeba\S3\Connector($configuration); ``` where `$yourRegion` is the AWS region of your bucket, e.g. `us-east-1`. Please note that we are passing the security token (`$credentials['Token']`) to the Configuration object. This is REQUIRED. The temporary credentials returned by the metadata service won't work without it. -Also worth noting is that the temporary credentials don't last forever. Check the `$credentials['Expiration']` to see +Another point worth noting is that the temporary credentials don't last forever. Check the `$credentials['Expiration']` to see when they are about to expire. Amazon recommends that you retry fetching new credentials from the metadata service 10 minutes before your cached credentials are set to expire. The metadata service is guaranteed to provision fresh temporary credentials by that time. @@ -120,21 +144,21 @@ The last parameter (common prefixes) controls the listing of "subdirectories" From a file: ```php -$input = \Akeeba\Engine\Postproc\Connector\S3v4\Input::createFromFile($sourceFile); +$input = \Akeeba\S3\Input::createFromFile($sourceFile); $connector->putObject($input, 'mybucket', 'path/to/myfile.txt'); ``` From a string: ```php -$input = \Akeeba\Engine\Postproc\Connector\S3v4\Input::createFromData($sourceString); +$input = \Akeeba\S3\Input::createFromData($sourceString); $connector->putObject($input, 'mybucket', 'path/to/myfile.txt'); ``` From a stream resource: ```php -$input = \Akeeba\Engine\Postproc\Connector\S3v4\Input::createFromResource($streamHandle, false); +$input = \Akeeba\S3\Input::createFromResource($streamHandle, false); $connector->putObject($input, 'mybucket', 'path/to/myfile.txt'); ``` @@ -145,7 +169,7 @@ In all cases the entirety of the file has to be loaded in memory. Files are uploaded in 5Mb chunks. ```php -$input = \Akeeba\Engine\Postproc\Connector\S3v4\Input::createFromFile($sourceFile); +$input = \Akeeba\S3\Input::createFromFile($sourceFile); $uploadId = $connector->startMultipart($input, 'mybucket', 'mypath/movie.mov'); $eTags = array(); @@ -155,7 +179,7 @@ $partNumber = 0; do { // IMPORTANT: You MUST create the input afresh before each uploadMultipart call - $input = \Akeeba\Engine\Postproc\Connector\S3v4\Input::createFromFile($sourceFile); + $input = \Akeeba\S3\Input::createFromFile($sourceFile); $input->setUploadID($uploadId); $input->setPartNumber(++$partNumber); @@ -169,7 +193,7 @@ do while (!is_null($eTag)); // IMPORTANT: You MUST create the input afresh before finalising the multipart upload -$input = \Akeeba\Engine\Postproc\Connector\S3v4\Input::createFromFile($sourceFile); +$input = \Akeeba\S3\Input::createFromFile($sourceFile); $input->setUploadID($uploadId); $input->setEtags($eTags); @@ -209,6 +233,23 @@ $content = $connector->getObject('mybucket', 'path/to/file.jpg', false); $connector->deleteObject('mybucket', 'path/to/file.jpg'); ``` +### Test if an object exists + +```php +try +{ + $headers = $connector->headObject('mybucket', 'path/to/file.jpg'); + $exists = true; +} +catch (\Akeeba\S3\Exception\CannotGetFile $e) +{ + $headers = []; + $exists = false; +} +``` + +The `$headers` variable contains an array with the S3 headers returned by the [HeadObject(https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadObject.html) API call. The header keys are always in lowercase. Please note that _not all_ of the headers Amazon describes in their documentation are returned in every request. + ## Configuration options The Configuration option has optional methods which can be used to enable some useful features in the connector. @@ -216,7 +257,7 @@ The Configuration option has optional methods which can be used to enable some u You need to execute these methods against the Configuration object before passing it to the Connector's constructor. For example: ```php -$configuration = new \Akeeba\Engine\Postproc\Connector\S3v4\Configuration( +$configuration = new \Akeeba\S3\Configuration( 'YourAmazonAccessKey', 'YourAmazonSecretKey' ); @@ -225,7 +266,7 @@ $configuration = new \Akeeba\Engine\Postproc\Connector\S3v4\Configuration( $configuration->setSignatureMethod('v4'); $configuration->setUseDualstackUrl(true); -$connector = new \Akeeba\Engine\Postproc\Connector\S3v4\Connector($configuration); +$connector = new \Akeeba\S3\Connector($configuration); ``` ### HTTPS vs plain HTTP @@ -245,7 +286,7 @@ Please note that if the S3-compatible APi uses v4 signatures you need to enter t ```php // DigitalOcean Spaces using v4 signatures // The access credentials are those used in the example at https://developers.digitalocean.com/documentation/spaces/ -$configuration = new \Akeeba\Engine\Postproc\Connector\S3v4\Configuration( +$configuration = new \Akeeba\S3\Configuration( '532SZONTQ6ALKBCU94OU', 'zCkY83KVDXD8u83RouEYPKEm/dhPSPB45XsfnWj8fxQ', 'v4', @@ -253,7 +294,7 @@ $configuration = new \Akeeba\Engine\Postproc\Connector\S3v4\Configuration( ); $configuration->setEndpoint('nyc3.digitaloceanspaces.com'); -$connector = new \Akeeba\Engine\Postproc\Connector\S3v4\Connector($configuration); +$connector = new \Akeeba\S3\Connector($configuration); ``` If your S3-compatible API uses v2 signatures you do not need to specify a region. @@ -261,14 +302,14 @@ If your S3-compatible API uses v2 signatures you do not need to specify a region ```php // DigitalOcean Spaces using v2 signatures // The access credentials are those used in the example at https://developers.digitalocean.com/documentation/spaces/ -$configuration = new \Akeeba\Engine\Postproc\Connector\S3v4\Configuration( +$configuration = new \Akeeba\S3\Configuration( '532SZONTQ6ALKBCU94OU', 'zCkY83KVDXD8u83RouEYPKEm/dhPSPB45XsfnWj8fxQ', 'v2' ); $configuration->setEndpoint('nyc3.digitaloceanspaces.com'); -$connector = new \Akeeba\Engine\Postproc\Connector\S3v4\Connector($configuration); +$connector = new \Akeeba\S3\Connector($configuration); ``` ### Legacy path-style access @@ -282,7 +323,7 @@ You need to do: $configuration->setUseLegacyPathStyle(true); ``` -Caveat: this will not work with v2 signatures if you are using Amazon AWS S3 proper. It will work with the v2 signatures if you are using a custom endpoint, though. In fact, most S3-compatible APIs implementing V2 signatures _expect_ you to use path-style access. +Caveat: this will not work with v2 signatures if you are using Amazon AWS S3 proper. It will very likely work with the v2 signatures if you are using a custom endpoint, though. ### Dualstack (IPv4 and IPv6) support diff --git a/s3_storage/vendor/akeeba/s3/TODO.md b/s3_storage/vendor/akeeba/s3/TODO.md deleted file mode 100644 index e19fb64c5..000000000 --- a/s3_storage/vendor/akeeba/s3/TODO.md +++ /dev/null @@ -1,13 +0,0 @@ -Need to check: - -endpoint in [amazon, custom] -signature in [v2, v4] -path style in [true, false] - upload - download - presigned URL generation - presigned URL access - - -USING VIRTUAL HOSTING, v4 SIGNATURES - presigned URL must use s3.amazonaws.com i.e. path-style hosting (because who needs logic?) \ No newline at end of file diff --git a/s3_storage/vendor/akeeba/s3/composer.json b/s3_storage/vendor/akeeba/s3/composer.json index bfb1943c0..2d3ef59f5 100644 --- a/s3_storage/vendor/akeeba/s3/composer.json +++ b/s3_storage/vendor/akeeba/s3/composer.json @@ -3,7 +3,7 @@ "type": "library", "description": "A compact, dependency-less Amazon S3 API client implementing the most commonly used features", "require": { - "php": ">=7.1.0 <8.1", + "php": ">=7.1.0 <8.4", "ext-curl": "*", "ext-simplexml": "*" }, @@ -11,7 +11,7 @@ "s3" ], "homepage": "https://github.com/akeeba/s3", - "license": "GPL-3.0+", + "license": "GPL-3.0-or-later", "authors": [ { "name": "Nicholas K. Dionysopoulos", @@ -22,7 +22,16 @@ ], "autoload": { "psr-4": { - "Akeeba\\Engine\\Postproc\\Connector\\S3v4\\": "src" - } + "Akeeba\\S3\\": "src" + }, + "files": [ + "src/aliasing.php" + ] + }, + "archive": { + "exclude": [ + "minitest", + "TODO.md" + ] } } diff --git a/s3_storage/vendor/akeeba/s3/composer.lock b/s3_storage/vendor/akeeba/s3/composer.lock index e7cbd746b..a7e203f93 100644 --- a/s3_storage/vendor/akeeba/s3/composer.lock +++ b/s3_storage/vendor/akeeba/s3/composer.lock @@ -1,19 +1,22 @@ { - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", - "This file is @generated automatically" - ], - "content-hash": "1070071b351d45a80934e854f0725d64", - "packages": [], - "packages-dev": [], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": [], - "prefer-stable": false, - "prefer-lowest": false, - "platform": { - "php": ">=5.3.4" - }, - "platform-dev": [] + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "27f387a657b2784510b177f73c436346", + "packages": [], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": ">=7.1.0 <8.4", + "ext-curl": "*", + "ext-simplexml": "*" + }, + "platform-dev": [], + "plugin-api-version": "2.3.0" } diff --git a/s3_storage/vendor/akeeba/s3/minitest/NOTES.md b/s3_storage/vendor/akeeba/s3/minitest/NOTES.md new file mode 100644 index 000000000..b31f4f0ab --- /dev/null +++ b/s3_storage/vendor/akeeba/s3/minitest/NOTES.md @@ -0,0 +1,62 @@ +# Testing notes + +## Against Amazon S3 proper + +This is the _canonical_ method for testing this library since Amazon S3 proper is the canonical provider of the S3 API (and not all of its quirks are fully documented, we might add). + +Copy `config.dist.php` to `config.php` and enter the connection information to your Amazon S3 or compatible service. + +## Against [LocalStack](https://localstack.cloud) + +This method is very useful for development. + +Install LocalStack [as per their documentation](https://docs.localstack.cloud/getting-started/installation/). + +You will also need to install [`awslocal`](https://github.com/localstack/awscli-local) like so: +```php +pip install awscli +pip install awscli-local +``` + +Start LocalStack e.g. `localstack start -d` + +Create a new bucket called `test` i.e. `awslocal s3 mk s3://test` + +Copy `config.dist.php` to `config.php` and make the following changes: +```php + define('DEFAULT_ENDPOINT', 'localhost.localstack.cloud:4566'); + define('DEFAULT_ACCESS_KEY', 'ANYRANDOMSTRINGWILLDO'); + define('DEFAULT_SECRET_KEY', 'ThisIsAlwaysIgnoredByLocalStack'); + define('DEFAULT_REGION', 'us-east-1'); + define('DEFAULT_BUCKET', 'test'); + define('DEFAULT_SIGNATURE', 'v4'); + define('DEFAULT_PATH_ACCESS', true); +``` + +Note that single- and dualstack tests result in the same URLs for all S3-compatible services, including LocalStack. These tests are essentially duplicates in this use case. + +## Against Wasabi + +Wasabi nominally supports v4 signatures, but their implementation is actually _non-canonical_, as they only read the date from the optional `x-amz-date` header, without falling back to the standard HTTP `Date` header. We have added a workaround for this behaviour which necessitates testing with it. + +Just like with Amazon S3 proper, copy `config.dist.php` to `config.php` and enter the connection information to your Wasabi storage. You will also need to set up the custom endpoint like so: +```php +define('DEFAULT_ENDPOINT', 's3.eu-central-2.wasabisys.com'); +``` + +**IMPORTANT!** The above endpoint will be different, depending on which region you've created your bucket in. The example above assumes the `eu-central-2` region. If you use the wrong region the tests _will_ fail! + +## Against Synology C2 + +Synology C2 is an S3-“compatible” storage service. It is not very “compatible” though, since they implemented Amazon's documentation of the v4 signatures instead of how the v4 signatures work in the real world (yeah, there's a very big difference). While Amazon S3 _in reality_ expects all dates to be formatted as per RFC1123, they document that they expect them to be formatted as per “ISO 8601” and they give their _completely wrong_ interpretation of what the “ISO 8601” format is. Synology did not catch that discrepancy, and they only expect the wrongly formatted dates which is totally NOT what S3 itself expects. Luckily, most third party implementations expect either format because they've caught the discrepancy between documentation and reality, therefore making it possible for us to come up with a viable workaround. + +And that's why we need to test with C2 as well, folks. + +Copy `config.dist.php` to `config.php` and enter the connection information to your Synology S3 service. + +It is very important to note two things: +```php +define('DEFAULT_ENDPOINT', 'eu-002.s3.synologyc2.net'); +define('DEFAULT_REGION', 'eu-002'); +``` +The endpoint URL is given in the Synology C2 Object Manager, next to each bucket. Note the part before `.s3.`. This is the **region** you need to use with v4 signatures. They do not document this anywhere. \ No newline at end of file diff --git a/s3_storage/vendor/akeeba/s3/minitest/Test/AbstractTest.php b/s3_storage/vendor/akeeba/s3/minitest/Test/AbstractTest.php index 8470e2607..895259dd6 100644 --- a/s3_storage/vendor/akeeba/s3/minitest/Test/AbstractTest.php +++ b/s3_storage/vendor/akeeba/s3/minitest/Test/AbstractTest.php @@ -3,13 +3,13 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\MiniTest\Test; -use Akeeba\Engine\Postproc\Connector\S3v4\Connector; +use Akeeba\S3\Connector; use RuntimeException; abstract class AbstractTest @@ -58,24 +58,24 @@ abstract class AbstractTest */ protected static function createFile(int $size = AbstractTest::SIX_HUNDRED_KB, int $blockSize = self::BLOCK_SIZE, bool $reuseBlock = true) { - $tempFilePath = tempnam(self::getTempFolder(), 'as3'); + $tempFilePath = tempnam(static::getTempFolder(), 'as3'); if ($tempFilePath === false) { throw new RuntimeException("Cannot create a temporary file."); } - $fp = @fopen($tempFilePath, 'wb', false); + $fp = @fopen($tempFilePath, 'w', false); if ($fp === false) { throw new RuntimeException("Cannot write to the temporary file."); } - $blockSize = self::BLOCK_SIZE; + $blockSize = static::BLOCK_SIZE; $lastBlockSize = $size % $blockSize; $wholeBlocks = (int) (($size - $lastBlockSize) / $blockSize); - $blockData = self::getRandomData(); + $blockData = static::getRandomData(); for ($i = 0; $i < $wholeBlocks; $i++) { @@ -83,7 +83,7 @@ abstract class AbstractTest if (!$reuseBlock) { - $blockData = self::getRandomData($blockSize); + $blockData = static::getRandomData($blockSize); } } @@ -155,7 +155,7 @@ abstract class AbstractTest return false; } - return hash_file(self::FILE_HASHING_ALGORITHM, $referenceFilePath) === hash_file(self::FILE_HASHING_ALGORITHM, $unknownFilePath); + return hash_file(static::FILE_HASHING_ALGORITHM, $referenceFilePath) === hash_file(static::FILE_HASHING_ALGORITHM, $unknownFilePath); } /** diff --git a/s3_storage/vendor/akeeba/s3/minitest/Test/BigFiles.php b/s3_storage/vendor/akeeba/s3/minitest/Test/BigFiles.php index b7273bad7..437d73ed1 100644 --- a/s3_storage/vendor/akeeba/s3/minitest/Test/BigFiles.php +++ b/s3_storage/vendor/akeeba/s3/minitest/Test/BigFiles.php @@ -3,15 +3,15 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\MiniTest\Test; -use Akeeba\Engine\Postproc\Connector\S3v4\Connector; -use Akeeba\Engine\Postproc\Connector\S3v4\Input; +use Akeeba\S3\Connector; +use Akeeba\S3\Input; /** * Upload, download and delete big files (over 1MB), without multipart uploads. Uses string or file sources. @@ -51,7 +51,7 @@ class BigFiles extends AbstractTest /** * Number of uploaded chunks. * - * This is set by self::upload(). Zero for single part uploads, non-zero for multipart uploads. + * This is set by static::upload(). Zero for single part uploads, non-zero for multipart uploads. * * @var int */ @@ -59,42 +59,42 @@ class BigFiles extends AbstractTest public static function upload5MBString(Connector $s3, array $options): bool { - return self::upload($s3, $options, self::FIVE_MB, 'bigtest_5mb.dat'); + return static::upload($s3, $options, static::FIVE_MB, 'bigtest_5mb.dat'); } public static function upload6MBString(Connector $s3, array $options): bool { - return self::upload($s3, $options, self::SIX_MB, 'bigtest_6mb.dat'); + return static::upload($s3, $options, static::SIX_MB, 'bigtest_6mb.dat'); } public static function upload10MBString(Connector $s3, array $options): bool { - return self::upload($s3, $options, self::TEN_MB, 'bigtest_10mb.dat'); + return static::upload($s3, $options, static::TEN_MB, 'bigtest_10mb.dat'); } public static function upload11MBString(Connector $s3, array $options): bool { - return self::upload($s3, $options, self::ELEVEN_MB, 'bigtest_11mb.dat'); + return static::upload($s3, $options, static::ELEVEN_MB, 'bigtest_11mb.dat'); } public static function upload5MBFile(Connector $s3, array $options): bool { - return self::upload($s3, $options, self::FIVE_MB, 'bigtest_5mb.dat', false); + return static::upload($s3, $options, static::FIVE_MB, 'bigtest_5mb.dat', false); } public static function upload6MBFile(Connector $s3, array $options): bool { - return self::upload($s3, $options, self::SIX_MB, 'bigtest_6mb.dat', false); + return static::upload($s3, $options, static::SIX_MB, 'bigtest_6mb.dat', false); } public static function upload10MBFile(Connector $s3, array $options): bool { - return self::upload($s3, $options, self::TEN_MB, 'bigtest_10mb.dat', false); + return static::upload($s3, $options, static::TEN_MB, 'bigtest_10mb.dat', false); } public static function upload11MBFile(Connector $s3, array $options): bool { - return self::upload($s3, $options, self::ELEVEN_MB, 'bigtest_11mb.dat', false); + return static::upload($s3, $options, static::ELEVEN_MB, 'bigtest_11mb.dat', false); } protected static function upload(Connector $s3, array $options, int $size, string $uri, bool $useString = true): bool @@ -103,24 +103,24 @@ class BigFiles extends AbstractTest $dotPos = strrpos($uri, '.'); $uri = substr($uri, 0, $dotPos) . '.' . md5(microtime(false)) . substr($uri, $dotPos); - self::$numberOfChunks = 0; + static::$numberOfChunks = 0; if ($useString) { - $sourceData = self::getRandomData($size); + $sourceData = static::getRandomData($size); $input = Input::createFromData($sourceData); } else { // Create a file with random data - $sourceFile = self::createFile($size); + $sourceFile = static::createFile($size); $input = Input::createFromFile($sourceFile); } // Upload the file. Throws exception if it fails. $bucket = $options['bucket']; - if (!self::$multipart) + if (!static::$multipart) { $s3->putObject($input, $bucket, $uri); } @@ -149,7 +149,7 @@ class BigFiles extends AbstractTest $input->setEtags($eTags); $input->setPartNumber($partNumber); - $etag = $s3->uploadMultipart($input, $bucket, $uri, [], self::$uploadChunkSize); + $etag = $s3->uploadMultipart($input, $bucket, $uri, [], static::$uploadChunkSize); // If the result was null we have no more file parts to process. if (is_null($etag)) @@ -166,7 +166,7 @@ class BigFiles extends AbstractTest $partNumber++; } - self::$numberOfChunks = count($eTags); + static::$numberOfChunks = count($eTags); // Finalize the multipart upload. Tells Amazon to construct the file from the uploaded parts. $s3->finalizeMultipart($input, $bucket, $uri); @@ -176,7 +176,7 @@ class BigFiles extends AbstractTest $result = true; // Should I download the file and compare its contents? - if (self::$downloadAfter) + if (static::$downloadAfter) { if ($useString) { @@ -184,16 +184,16 @@ class BigFiles extends AbstractTest $downloadedData = $s3->getObject($bucket, $uri); // Compare the file contents. - $result = self::areStringsEqual($sourceData, $downloadedData); + $result = static::areStringsEqual($sourceData, $downloadedData); } else { // Download the data. Throws exception if it fails. - $downloadedFile = tempnam(self::getTempFolder(), 'as3'); + $downloadedFile = tempnam(static::getTempFolder(), 'as3'); $s3->getObject($bucket, $uri, $downloadedFile); // Compare the file contents. - $result = self::areFilesEqual($sourceFile, $downloadedFile); + $result = static::areFilesEqual($sourceFile, $downloadedFile); @unlink($downloadedFile); } @@ -206,7 +206,7 @@ class BigFiles extends AbstractTest } // Should I delete the remotely stored file? - if (self::$deleteRemote) + if (static::$deleteRemote) { // Delete the remote file. Throws exception if it fails. $s3->deleteObject($bucket, $uri); diff --git a/s3_storage/vendor/akeeba/s3/minitest/Test/BucketLocation.php b/s3_storage/vendor/akeeba/s3/minitest/Test/BucketLocation.php index 6ba388b46..ff04f58a5 100644 --- a/s3_storage/vendor/akeeba/s3/minitest/Test/BucketLocation.php +++ b/s3_storage/vendor/akeeba/s3/minitest/Test/BucketLocation.php @@ -3,14 +3,14 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\MiniTest\Test; -use Akeeba\Engine\Postproc\Connector\S3v4\Connector; +use Akeeba\S3\Connector; class BucketLocation extends AbstractTest { @@ -18,7 +18,7 @@ class BucketLocation extends AbstractTest { $location = $s3->getBucketLocation($options['bucket']); - self::assert($location === $options['region'], "Bucket ‘{$options['bucket']}′ reports being in region ‘{$location}′ instead of expected ‘{$options['region']}′"); + static::assert($location === $options['region'], "Bucket ‘{$options['bucket']}′ reports being in region ‘{$location}′ instead of expected ‘{$options['region']}′"); return true; } diff --git a/s3_storage/vendor/akeeba/s3/minitest/Test/BucketsList.php b/s3_storage/vendor/akeeba/s3/minitest/Test/BucketsList.php index 33925cd2f..4dab491dd 100644 --- a/s3_storage/vendor/akeeba/s3/minitest/Test/BucketsList.php +++ b/s3_storage/vendor/akeeba/s3/minitest/Test/BucketsList.php @@ -3,14 +3,14 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\MiniTest\Test; -use Akeeba\Engine\Postproc\Connector\S3v4\Connector; +use Akeeba\S3\Connector; use RuntimeException; class BucketsList extends AbstractTest @@ -19,16 +19,16 @@ class BucketsList extends AbstractTest { $buckets = $s3->listBuckets(true); - self::assert(is_array($buckets), "Detailed buckets list is not an array"); - self::assert(isset($buckets['owner']), "Detailed buckets list does not list an owner"); - self::assert(isset($buckets['owner']['id']), "Detailed buckets list does not list an owner's id"); - self::assert(isset($buckets['owner']['name']), "Detailed buckets list does not list an owner's name"); - self::assert(isset($buckets['buckets']), "Detailed buckets list does not list any buckets"); + static::assert(is_array($buckets), "Detailed buckets list is not an array"); + static::assert(isset($buckets['owner']), "Detailed buckets list does not list an owner"); + static::assert(isset($buckets['owner']['id']), "Detailed buckets list does not list an owner's id"); + static::assert(isset($buckets['owner']['name']), "Detailed buckets list does not list an owner's name"); + static::assert(isset($buckets['buckets']), "Detailed buckets list does not list any buckets"); foreach ($buckets['buckets'] as $bucketInfo) { - self::assert(isset($bucketInfo['name']), "Bucket information does not list a name"); - self::assert(isset($bucketInfo['time']), "Bucket information does not list a created times"); + static::assert(isset($bucketInfo['name']), "Bucket information does not list a name"); + static::assert(isset($bucketInfo['time']), "Bucket information does not list a created times"); if ($bucketInfo['name'] === $options['bucket']) { @@ -43,8 +43,8 @@ class BucketsList extends AbstractTest { $buckets = $s3->listBuckets(false); - self::assert(is_array($buckets), "Simple buckets list is not an array"); - self::assert(in_array($options['bucket'], $buckets), "Simple buckets list does not include configured bucket ‘{$options['bucket']}′"); + static::assert(is_array($buckets), "Simple buckets list is not an array"); + static::assert(in_array($options['bucket'], $buckets), "Simple buckets list does not include configured bucket ‘{$options['bucket']}′"); return true; } diff --git a/s3_storage/vendor/akeeba/s3/minitest/Test/HeadObject.php b/s3_storage/vendor/akeeba/s3/minitest/Test/HeadObject.php new file mode 100644 index 000000000..535afdbda --- /dev/null +++ b/s3_storage/vendor/akeeba/s3/minitest/Test/HeadObject.php @@ -0,0 +1,67 @@ +putObject($input, $bucket, $uri); + + $headers = $s3->headObject($bucket, $uri); + + static::assert(isset($headers['size']), 'The returned headers do not contain the object size'); + static::assert($headers['size'] == AbstractTest::TEN_KB, 'The returned size does not match'); + + // Remove the local files + @unlink($sourceFile); + + // Delete the remote file. Throws exception if it fails. + $s3->deleteObject($bucket, $uri); + + return true; + } + + public static function testMissingFile(Connector $s3, array $options): bool + { + $bucket = $options['bucket']; + + try + { + $headers = $s3->headObject($bucket, md5(microtime(false)) . '_does_not_exist'); + } + catch (CannotGetFile $e) + { + return true; + } + + return false; + } +} \ No newline at end of file diff --git a/s3_storage/vendor/akeeba/s3/minitest/Test/ListFiles.php b/s3_storage/vendor/akeeba/s3/minitest/Test/ListFiles.php index 538939222..00b5fdbf0 100644 --- a/s3_storage/vendor/akeeba/s3/minitest/Test/ListFiles.php +++ b/s3_storage/vendor/akeeba/s3/minitest/Test/ListFiles.php @@ -3,16 +3,16 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\MiniTest\Test; -use Akeeba\Engine\Postproc\Connector\S3v4\Connector; -use Akeeba\Engine\Postproc\Connector\S3v4\Exception\CannotPutFile; -use Akeeba\Engine\Postproc\Connector\S3v4\Input; +use Akeeba\S3\Connector; +use Akeeba\S3\Exception\CannotPutFile; +use Akeeba\S3\Input; class ListFiles extends AbstractTest { @@ -34,9 +34,9 @@ class ListFiles extends AbstractTest public static function setup(Connector $s3, array $options): void { - $data = self::getRandomData(self::TEN_KB); + $data = static::getRandomData(static::TEN_KB); - foreach (self::$paths as $uri) + foreach (static::$paths as $uri) { $input = Input::createFromData($data); try @@ -52,7 +52,7 @@ class ListFiles extends AbstractTest public static function teardown(Connector $s3, array $options): void { - foreach (self::$paths as $uri) + foreach (static::$paths as $uri) { try { @@ -69,29 +69,29 @@ class ListFiles extends AbstractTest { $listing = $s3->getBucket($options['bucket'], 'listtest_'); - self::assert(is_array($listing), "The files listing must be an array"); - self::assert(count($listing) == 3, "I am expecting to see 3 files"); + static::assert(is_array($listing), "The files listing must be an array"); + static::assert(count($listing) == 3, "I am expecting to see 3 files"); // Make sure I have the expected files - self::assert(array_key_exists('listtest_one.dat', $listing), "File listtest_one.dat not in listing"); - self::assert(array_key_exists('listtest_two.dat', $listing), "File listtest_two.dat not in listing"); - self::assert(array_key_exists('listtest_three.dat', $listing), "File listtest_three.dat not in listing"); + static::assert(array_key_exists('listtest_one.dat', $listing), "File listtest_one.dat not in listing"); + static::assert(array_key_exists('listtest_two.dat', $listing), "File listtest_two.dat not in listing"); + static::assert(array_key_exists('listtest_three.dat', $listing), "File listtest_three.dat not in listing"); // I must not see the files in subdirectories - self::assert(!array_key_exists('listtest_four.dat', $listing), "File listtest_four.dat in listing"); - self::assert(!array_key_exists('listtest_five.dat', $listing), "File listtest_five.dat in listing"); - self::assert(!array_key_exists('listtest_six.dat', $listing), "File listtest_six.dat in listing"); + static::assert(!array_key_exists('listtest_four.dat', $listing), "File listtest_four.dat in listing"); + static::assert(!array_key_exists('listtest_five.dat', $listing), "File listtest_five.dat in listing"); + static::assert(!array_key_exists('listtest_six.dat', $listing), "File listtest_six.dat in listing"); // I must not see the files not matching the prefix I gave - self::assert(!array_key_exists('spam.dat', $listing), "File spam.dat in listing"); - self::assert(!array_key_exists('ham.dat', $listing), "File ham.dat in listing"); + static::assert(!array_key_exists('spam.dat', $listing), "File spam.dat in listing"); + static::assert(!array_key_exists('ham.dat', $listing), "File ham.dat in listing"); foreach ($listing as $fileName => $info) { - self::assert(isset($info['name']), "File entries must have a name"); - self::assert(isset($info['time']), "File entries must have a time"); - self::assert(isset($info['size']), "File entries must have a size"); - self::assert(isset($info['hash']), "File entries must have a hash"); + static::assert(isset($info['name']), "File entries must have a name"); + static::assert(isset($info['time']), "File entries must have a time"); + static::assert(isset($info['size']), "File entries must have a size"); + static::assert(isset($info['hash']), "File entries must have a hash"); } return true; @@ -101,37 +101,37 @@ class ListFiles extends AbstractTest { $listing = $s3->getBucket($options['bucket'], 'listtest_', null, 1); - self::assert(is_array($listing), "The files listing must be an array"); - self::assert(count($listing) == 1, sprintf("I am expecting to see 1 file, %s seen", count($listing))); + static::assert(is_array($listing), "The files listing must be an array"); + static::assert(count($listing) == 1, sprintf("I am expecting to see 1 file, %s seen", count($listing))); $files = array_keys($listing); $continued = $s3->getBucket($options['bucket'], 'listtest_', array_shift($files)); - self::assert(is_array($continued), "The continued files listing must be an array"); - self::assert(count($continued) == 2, sprintf("I am expecting to see 2 files, %s seen", count($continued))); + static::assert(is_array($continued), "The continued files listing must be an array"); + static::assert(count($continued) == 2, sprintf("I am expecting to see 2 files, %s seen", count($continued))); $listing = array_merge($listing, $continued); // Make sure I have the expected files - self::assert(array_key_exists('listtest_one.dat', $listing), "File listtest_one.dat not in listing"); - self::assert(array_key_exists('listtest_two.dat', $listing), "File listtest_two.dat not in listing"); - self::assert(array_key_exists('listtest_three.dat', $listing), "File listtest_three.dat not in listing"); + static::assert(array_key_exists('listtest_one.dat', $listing), "File listtest_one.dat not in listing"); + static::assert(array_key_exists('listtest_two.dat', $listing), "File listtest_two.dat not in listing"); + static::assert(array_key_exists('listtest_three.dat', $listing), "File listtest_three.dat not in listing"); // I must not see the files in subdirectories - self::assert(!array_key_exists('listtest_four.dat', $listing), "File listtest_four.dat in listing"); - self::assert(!array_key_exists('listtest_five.dat', $listing), "File listtest_five.dat in listing"); - self::assert(!array_key_exists('listtest_six.dat', $listing), "File listtest_six.dat in listing"); + static::assert(!array_key_exists('listtest_four.dat', $listing), "File listtest_four.dat in listing"); + static::assert(!array_key_exists('listtest_five.dat', $listing), "File listtest_five.dat in listing"); + static::assert(!array_key_exists('listtest_six.dat', $listing), "File listtest_six.dat in listing"); // I must not see the files not matching the prefix I gave - self::assert(!array_key_exists('spam.dat', $listing), "File spam.dat in listing"); - self::assert(!array_key_exists('ham.dat', $listing), "File ham.dat in listing"); + static::assert(!array_key_exists('spam.dat', $listing), "File spam.dat in listing"); + static::assert(!array_key_exists('ham.dat', $listing), "File ham.dat in listing"); foreach ($listing as $fileName => $info) { - self::assert(isset($info['name']), "File entries must have a name"); - self::assert(isset($info['time']), "File entries must have a time"); - self::assert(isset($info['size']), "File entries must have a size"); - self::assert(isset($info['hash']), "File entries must have a hash"); + static::assert(isset($info['name']), "File entries must have a name"); + static::assert(isset($info['time']), "File entries must have a time"); + static::assert(isset($info['size']), "File entries must have a size"); + static::assert(isset($info['hash']), "File entries must have a hash"); } return true; @@ -141,30 +141,30 @@ class ListFiles extends AbstractTest { $listing = $s3->getBucket($options['bucket'], 'list_deeper/test_'); - self::assert(is_array($listing), "The files listing must be an array"); - self::assert(count($listing) == 3, "I am expecting to see 3 files"); + static::assert(is_array($listing), "The files listing must be an array"); + static::assert(count($listing) == 3, "I am expecting to see 3 files"); // Make sure I have the expected files - self::assert(array_key_exists('list_deeper/test_one.dat', $listing), "File test_one.dat not in listing"); - self::assert(array_key_exists('list_deeper/test_two.dat', $listing), "File test_two.dat not in listing"); - self::assert(array_key_exists('list_deeper/test_three.dat', $listing), "File test_three.dat not in listing"); + static::assert(array_key_exists('list_deeper/test_one.dat', $listing), "File test_one.dat not in listing"); + static::assert(array_key_exists('list_deeper/test_two.dat', $listing), "File test_two.dat not in listing"); + static::assert(array_key_exists('list_deeper/test_three.dat', $listing), "File test_three.dat not in listing"); // I must not see the files with different prefix - self::assert(!array_key_exists('list_deeper/listtest_four.dat', $listing), "File listtest_four.dat in listing"); - self::assert(!array_key_exists('list_deeper/listtest_five.dat', $listing), "File listtest_five.dat in listing"); - self::assert(!array_key_exists('list_deeper/listtest_six.dat', $listing), "File listtest_six.dat in listing"); - self::assert(!array_key_exists('list_deeper/spam.dat', $listing), "File spam.dat in listing"); + static::assert(!array_key_exists('list_deeper/listtest_four.dat', $listing), "File listtest_four.dat in listing"); + static::assert(!array_key_exists('list_deeper/listtest_five.dat', $listing), "File listtest_five.dat in listing"); + static::assert(!array_key_exists('list_deeper/listtest_six.dat', $listing), "File listtest_six.dat in listing"); + static::assert(!array_key_exists('list_deeper/spam.dat', $listing), "File spam.dat in listing"); // I must not see the files in subdirectories - self::assert(!array_key_exists('list_deeper/listtest_deeper/seven.dat', $listing), "File spam.dat in listing"); - self::assert(!array_key_exists('list_deeper/listtest_deeper/eight.dat', $listing), "File spam.dat in listing"); + static::assert(!array_key_exists('list_deeper/listtest_deeper/seven.dat', $listing), "File spam.dat in listing"); + static::assert(!array_key_exists('list_deeper/listtest_deeper/eight.dat', $listing), "File spam.dat in listing"); foreach ($listing as $fileName => $info) { - self::assert(isset($info['name']), "File entries must have a name"); - self::assert(isset($info['time']), "File entries must have a time"); - self::assert(isset($info['size']), "File entries must have a size"); - self::assert(isset($info['hash']), "File entries must have a hash"); + static::assert(isset($info['name']), "File entries must have a name"); + static::assert(isset($info['time']), "File entries must have a time"); + static::assert(isset($info['size']), "File entries must have a size"); + static::assert(isset($info['hash']), "File entries must have a hash"); } return true; @@ -174,41 +174,41 @@ class ListFiles extends AbstractTest { $listing = $s3->getBucket($options['bucket'], 'list_deeper/test_', null, 1); - self::assert(is_array($listing), "The files listing must be an array"); - self::assert(count($listing) == 1, sprintf("I am expecting to see 1 file, %s seen", count($listing))); + static::assert(is_array($listing), "The files listing must be an array"); + static::assert(count($listing) == 1, sprintf("I am expecting to see 1 file, %s seen", count($listing))); $files = array_keys($listing); $continued = $s3->getBucket($options['bucket'], 'list_deeper/test_', array_shift($files)); - self::assert(is_array($continued), "The continued files listing must be an array"); - self::assert(count($continued) == 2, sprintf("I am expecting to see 2 files, %s seen", count($continued))); + static::assert(is_array($continued), "The continued files listing must be an array"); + static::assert(count($continued) == 2, sprintf("I am expecting to see 2 files, %s seen", count($continued))); $listing = array_merge($listing, $continued); - self::assert(is_array($listing), "The files listing must be an array"); - self::assert(count($listing) == 3, "I am expecting to see 3 files"); + static::assert(is_array($listing), "The files listing must be an array"); + static::assert(count($listing) == 3, "I am expecting to see 3 files"); // Make sure I have the expected files - self::assert(array_key_exists('list_deeper/test_one.dat', $listing), "File test_one.dat not in listing"); - self::assert(array_key_exists('list_deeper/test_two.dat', $listing), "File test_two.dat not in listing"); - self::assert(array_key_exists('list_deeper/test_three.dat', $listing), "File test_three.dat not in listing"); + static::assert(array_key_exists('list_deeper/test_one.dat', $listing), "File test_one.dat not in listing"); + static::assert(array_key_exists('list_deeper/test_two.dat', $listing), "File test_two.dat not in listing"); + static::assert(array_key_exists('list_deeper/test_three.dat', $listing), "File test_three.dat not in listing"); // I must not see the files with different prefix - self::assert(!array_key_exists('list_deeper/listtest_four.dat', $listing), "File listtest_four.dat in listing"); - self::assert(!array_key_exists('list_deeper/listtest_five.dat', $listing), "File listtest_five.dat in listing"); - self::assert(!array_key_exists('list_deeper/listtest_six.dat', $listing), "File listtest_six.dat in listing"); - self::assert(!array_key_exists('list_deeper/spam.dat', $listing), "File spam.dat in listing"); + static::assert(!array_key_exists('list_deeper/listtest_four.dat', $listing), "File listtest_four.dat in listing"); + static::assert(!array_key_exists('list_deeper/listtest_five.dat', $listing), "File listtest_five.dat in listing"); + static::assert(!array_key_exists('list_deeper/listtest_six.dat', $listing), "File listtest_six.dat in listing"); + static::assert(!array_key_exists('list_deeper/spam.dat', $listing), "File spam.dat in listing"); // I must not see the files in subdirectories - self::assert(!array_key_exists('list_deeper/listtest_deeper/seven.dat', $listing), "File spam.dat in listing"); - self::assert(!array_key_exists('list_deeper/listtest_deeper/eight.dat', $listing), "File spam.dat in listing"); + static::assert(!array_key_exists('list_deeper/listtest_deeper/seven.dat', $listing), "File spam.dat in listing"); + static::assert(!array_key_exists('list_deeper/listtest_deeper/eight.dat', $listing), "File spam.dat in listing"); foreach ($listing as $fileName => $info) { - self::assert(isset($info['name']), "File entries must have a name"); - self::assert(isset($info['time']), "File entries must have a time"); - self::assert(isset($info['size']), "File entries must have a size"); - self::assert(isset($info['hash']), "File entries must have a hash"); + static::assert(isset($info['name']), "File entries must have a name"); + static::assert(isset($info['time']), "File entries must have a time"); + static::assert(isset($info['size']), "File entries must have a size"); + static::assert(isset($info['hash']), "File entries must have a hash"); } return true; @@ -224,42 +224,42 @@ class ListFiles extends AbstractTest */ $listing = $s3->getBucket($options['bucket'], 'list_deeper/listtest_', null, 1); - self::assert(is_array($listing), "The files listing must be an array"); - self::assert(count($listing) == 1, sprintf("I am expecting to see 1 files, %s seen", count($listing))); + static::assert(is_array($listing), "The files listing must be an array"); + static::assert(count($listing) == 1, sprintf("I am expecting to see 1 files, %s seen", count($listing))); $files = array_keys($listing); $continued = $s3->getBucket($options['bucket'], 'list_deeper/listtest_', array_shift($files)); - self::assert(is_array($continued), "The continued files listing must be an array"); - self::assert(count($continued) == 2, sprintf("I am expecting to see 2 files, %s seen", count($continued))); + static::assert(is_array($continued), "The continued files listing must be an array"); + static::assert(count($continued) == 2, sprintf("I am expecting to see 2 files, %s seen", count($continued))); $listing = array_merge($listing, $continued); - self::assert(is_array($listing), "The files listing must be an array"); - self::assert(count($listing) == 3, "I am expecting to see 3 files"); + static::assert(is_array($listing), "The files listing must be an array"); + static::assert(count($listing) == 3, "I am expecting to see 3 files"); // Make sure I have the expected files - self::assert(array_key_exists('list_deeper/listtest_four.dat', $listing), "File listtest_four.dat not in listing"); - self::assert(array_key_exists('list_deeper/listtest_five.dat', $listing), "File listtest_five.dat not in listing"); - self::assert(array_key_exists('list_deeper/listtest_six.dat', $listing), "File listtest_six.dat not in listing"); + static::assert(array_key_exists('list_deeper/listtest_four.dat', $listing), "File listtest_four.dat not in listing"); + static::assert(array_key_exists('list_deeper/listtest_five.dat', $listing), "File listtest_five.dat not in listing"); + static::assert(array_key_exists('list_deeper/listtest_six.dat', $listing), "File listtest_six.dat not in listing"); // I must not see the files with different prefix - self::assert(!array_key_exists('list_deeper/test_one.dat', $listing), "File test_one.dat in listing"); - self::assert(!array_key_exists('list_deeper/test_two.dat', $listing), "File test_two.dat in listing"); - self::assert(!array_key_exists('list_deeper/test_three.dat', $listing), "File test_three.dat in listing"); - self::assert(!array_key_exists('list_deeper/spam.dat', $listing), "File spam.dat in listing"); + static::assert(!array_key_exists('list_deeper/test_one.dat', $listing), "File test_one.dat in listing"); + static::assert(!array_key_exists('list_deeper/test_two.dat', $listing), "File test_two.dat in listing"); + static::assert(!array_key_exists('list_deeper/test_three.dat', $listing), "File test_three.dat in listing"); + static::assert(!array_key_exists('list_deeper/spam.dat', $listing), "File spam.dat in listing"); // I must not see the files in subdirectories - self::assert(!array_key_exists('list_deeper/listtest_deeper/seven.dat', $listing), "File spam.dat in listing"); - self::assert(!array_key_exists('list_deeper/listtest_deeper/eight.dat', $listing), "File spam.dat in listing"); + static::assert(!array_key_exists('list_deeper/listtest_deeper/seven.dat', $listing), "File spam.dat in listing"); + static::assert(!array_key_exists('list_deeper/listtest_deeper/eight.dat', $listing), "File spam.dat in listing"); foreach ($listing as $fileName => $info) { - self::assert(isset($info['name']), "File entries must have a name"); - self::assert(isset($info['time']), "File entries must have a time"); - self::assert(isset($info['size']), "File entries must have a size"); - self::assert(isset($info['hash']), "File entries must have a hash"); + static::assert(isset($info['name']), "File entries must have a name"); + static::assert(isset($info['time']), "File entries must have a time"); + static::assert(isset($info['size']), "File entries must have a size"); + static::assert(isset($info['hash']), "File entries must have a hash"); } return true; @@ -269,37 +269,37 @@ class ListFiles extends AbstractTest { $listing = $s3->getBucket($options['bucket'], 'list_deeper/listtest_', null, null, '/', true); - self::assert(is_array($listing), "The files listing must be an array"); - self::assert(count($listing) == 4, sprintf("I am expecting to see 4 entries, %s entries seen.", count($listing))); + static::assert(is_array($listing), "The files listing must be an array"); + static::assert(count($listing) == 4, sprintf("I am expecting to see 4 entries, %s entries seen.", count($listing))); // Make sure I have the expected files - self::assert(array_key_exists('list_deeper/listtest_four.dat', $listing), "File listtest_four.dat not in listing"); - self::assert(array_key_exists('list_deeper/listtest_five.dat', $listing), "File listtest_five.dat not in listing"); - self::assert(array_key_exists('list_deeper/listtest_six.dat', $listing), "File listtest_six.dat not in listing"); - self::assert(array_key_exists('list_deeper/listtest_deeper/', $listing), "Folder listtest_deeper not in listing"); + static::assert(array_key_exists('list_deeper/listtest_four.dat', $listing), "File listtest_four.dat not in listing"); + static::assert(array_key_exists('list_deeper/listtest_five.dat', $listing), "File listtest_five.dat not in listing"); + static::assert(array_key_exists('list_deeper/listtest_six.dat', $listing), "File listtest_six.dat not in listing"); + static::assert(array_key_exists('list_deeper/listtest_deeper/', $listing), "Folder listtest_deeper not in listing"); // I must not see the files in subdirectories - self::assert(!array_key_exists('list_deeper/listtest_deeper/seven.dat', $listing), "File seven.dat in listing"); - self::assert(!array_key_exists('list_deeper/listtest_deeper/eight.dat', $listing), "File eight.dat in listing"); + static::assert(!array_key_exists('list_deeper/listtest_deeper/seven.dat', $listing), "File seven.dat in listing"); + static::assert(!array_key_exists('list_deeper/listtest_deeper/eight.dat', $listing), "File eight.dat in listing"); // I must not see the files with different prefix - self::assert(!array_key_exists('list_deeper/spam.dat', $listing), "File spam.dat in listing"); - self::assert(!array_key_exists('list_deeper/test_one.dat', $listing), "File test_one.dat not in listing"); - self::assert(!array_key_exists('list_deeper/test_two.dat', $listing), "File test_two.dat not in listing"); - self::assert(!array_key_exists('list_deeper/test_three.dat', $listing), "File test_three.dat not in listing"); + static::assert(!array_key_exists('list_deeper/spam.dat', $listing), "File spam.dat in listing"); + static::assert(!array_key_exists('list_deeper/test_one.dat', $listing), "File test_one.dat not in listing"); + static::assert(!array_key_exists('list_deeper/test_two.dat', $listing), "File test_two.dat not in listing"); + static::assert(!array_key_exists('list_deeper/test_three.dat', $listing), "File test_three.dat not in listing"); foreach ($listing as $fileName => $info) { if (substr($fileName, -1) !== '/') { - self::assert(isset($info['name']), "File entries must have a name"); - self::assert(isset($info['time']), "File entries must have a time"); - self::assert(isset($info['size']), "File entries must have a size"); - self::assert(isset($info['hash']), "File entries must have a hash"); + static::assert(isset($info['name']), "File entries must have a name"); + static::assert(isset($info['time']), "File entries must have a time"); + static::assert(isset($info['size']), "File entries must have a size"); + static::assert(isset($info['hash']), "File entries must have a hash"); } else { - self::assert(isset($info['prefix']), "Folder entries must return a prefix"); + static::assert(isset($info['prefix']), "Folder entries must return a prefix"); } } diff --git a/s3_storage/vendor/akeeba/s3/minitest/Test/ListThousandsOfFiles.php b/s3_storage/vendor/akeeba/s3/minitest/Test/ListThousandsOfFiles.php new file mode 100644 index 000000000..8146d4cde --- /dev/null +++ b/s3_storage/vendor/akeeba/s3/minitest/Test/ListThousandsOfFiles.php @@ -0,0 +1,111 @@ +putObject($input, $options['bucket'], $uri); + } + } + + public static function testGetAll(Connector $s3, array $options): bool + { + $listing = $s3->getBucket($options['bucket'], static::PATH_PREFIX); + + static::assert(is_array($listing), "The files listing must be an array"); + static::assert(count($listing) === 2100, "I am expecting to see 2100 files"); + + for ($i = 1; $i <= 2100; $i++) + { + $key = sprintf('%stest_%04u.dat', static::PATH_PREFIX, $i); + + static::assert(array_key_exists($key, $listing), sprintf('Results should list object %s', $key)); + } + + return true; + } + + public static function testGetHundred(Connector $s3, array $options): bool + { + $listing = $s3->getBucket($options['bucket'], static::PATH_PREFIX, null, 100); + + static::assert(is_array($listing), "The files listing must be an array"); + static::assert(count($listing) === 100, "I am expecting to see 100 files"); + + for ($i = 1; $i <= 100; $i++) + { + $key = sprintf('%stest_%04u.dat', static::PATH_PREFIX, $i); + + static::assert(array_key_exists($key, $listing), sprintf('Results should list object %s', $key)); + } + + return true; + } + + public static function testGetElevenHundred(Connector $s3, array $options): bool + { + $listing = $s3->getBucket($options['bucket'], static::PATH_PREFIX, null, 1100); + + static::assert(is_array($listing), "The files listing must be an array"); + static::assert(count($listing) === 1100, "I am expecting to see 1100 files"); + + for ($i = 1; $i <= 1100; $i++) + { + $key = sprintf('%stest_%04u.dat', static::PATH_PREFIX, $i); + + static::assert(array_key_exists($key, $listing), sprintf('Results should list object %s', $key)); + } + + return true; + } + + public static function testGetLastHundred(Connector $s3, array $options): bool + { + $listing = $s3->getBucket($options['bucket'], static::PATH_PREFIX . 'test_20', null); + + static::assert(is_array($listing), "The files listing must be an array"); + static::assert(count($listing) === 100, "I am expecting to see 100 files"); + + for ($i = 2000; $i <= 2099; $i++) + { + $key = sprintf('%stest_%04u.dat', static::PATH_PREFIX, $i); + + static::assert(array_key_exists($key, $listing), sprintf('Results should list object %s', $key)); + } + + return true; + } + +} \ No newline at end of file diff --git a/s3_storage/vendor/akeeba/s3/minitest/Test/Multipart.php b/s3_storage/vendor/akeeba/s3/minitest/Test/Multipart.php index e4c7c2846..df097e963 100644 --- a/s3_storage/vendor/akeeba/s3/minitest/Test/Multipart.php +++ b/s3_storage/vendor/akeeba/s3/minitest/Test/Multipart.php @@ -1,16 +1,22 @@ putObject($input, $bucket, $uri); + + $downloadedData = $s3->getObject($bucket, $uri); + $result = static::areStringsEqual($sourceData, $downloadedData); + + $s3->deleteObject($bucket, $uri); + + return $result ?? true; + } +} \ No newline at end of file diff --git a/s3_storage/vendor/akeeba/s3/minitest/Test/SmallFiles.php b/s3_storage/vendor/akeeba/s3/minitest/Test/SmallFiles.php index 52f49e587..82b2027f6 100644 --- a/s3_storage/vendor/akeeba/s3/minitest/Test/SmallFiles.php +++ b/s3_storage/vendor/akeeba/s3/minitest/Test/SmallFiles.php @@ -3,15 +3,15 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\MiniTest\Test; -use Akeeba\Engine\Postproc\Connector\S3v4\Connector; -use Akeeba\Engine\Postproc\Connector\S3v4\Input; +use Akeeba\S3\Connector; +use Akeeba\S3\Input; /** * Upload, download and delete small files (under 1MB) using a file source @@ -36,32 +36,32 @@ class SmallFiles extends AbstractTest public static function upload10KbRoot(Connector $s3, array $options): bool { - return self::upload($s3, $options, AbstractTest::TEN_KB, 'root_10kb.dat'); + return static::upload($s3, $options, AbstractTest::TEN_KB, 'root_10kb.dat'); } public static function upload10KbRootGreek(Connector $s3, array $options): bool { - return self::upload($s3, $options, AbstractTest::TEN_KB, 'δοκιμή_10kb.dat'); + return static::upload($s3, $options, AbstractTest::TEN_KB, 'δοκιμή_10kb.dat'); } public static function upload10KbFolderGreek(Connector $s3, array $options): bool { - return self::upload($s3, $options, AbstractTest::TEN_KB, 'ο_φάκελός_μου/δοκιμή_10kb.dat'); + return static::upload($s3, $options, AbstractTest::TEN_KB, 'ο_φάκελός_μου/δοκιμή_10kb.dat'); } public static function upload600KbRoot(Connector $s3, array $options): bool { - return self::upload($s3, $options, AbstractTest::SIX_HUNDRED_KB, 'root_600kb.dat'); + return static::upload($s3, $options, AbstractTest::SIX_HUNDRED_KB, 'root_600kb.dat'); } public static function upload10KbFolder(Connector $s3, array $options): bool { - return self::upload($s3, $options, AbstractTest::TEN_KB, 'my_folder/10kb.dat'); + return static::upload($s3, $options, AbstractTest::TEN_KB, 'my_folder/10kb.dat'); } public static function upload600KbFolder(Connector $s3, array $options): bool { - return self::upload($s3, $options, AbstractTest::SIX_HUNDRED_KB, 'my_folder/600kb.dat'); + return static::upload($s3, $options, AbstractTest::SIX_HUNDRED_KB, 'my_folder/600kb.dat'); } protected static function upload(Connector $s3, array $options, int $size, string $uri): bool @@ -71,7 +71,7 @@ class SmallFiles extends AbstractTest $uri = substr($uri, 0, $dotPos) . '.' . md5(microtime(false)) . substr($uri, $dotPos); // Create a file with random data - $sourceFile = self::createFile($size); + $sourceFile = static::createFile($size); // Upload the file. Throws exception if it fails. $bucket = $options['bucket']; @@ -83,14 +83,14 @@ class SmallFiles extends AbstractTest $result = true; // Should I download the file and compare its contents? - if (self::$downloadAfter) + if (static::$downloadAfter) { // Donwload the data. Throws exception if it fails. - $downloadedFile = tempnam(self::getTempFolder(), 'as3'); + $downloadedFile = tempnam(static::getTempFolder(), 'as3'); $s3->getObject($bucket, $uri, $downloadedFile); // Compare the file contents. - $result = self::areFilesEqual($sourceFile, $downloadedFile); + $result = static::areFilesEqual($sourceFile, $downloadedFile); } // Remove the local files @@ -98,7 +98,7 @@ class SmallFiles extends AbstractTest @unlink($downloadedFile); // Should I delete the remotely stored file? - if (self::$deleteRemote) + if (static::$deleteRemote) { // Delete the remote file. Throws exception if it fails. $s3->deleteObject($bucket, $uri); diff --git a/s3_storage/vendor/akeeba/s3/minitest/Test/SmallFilesNoDelete.php b/s3_storage/vendor/akeeba/s3/minitest/Test/SmallFilesNoDelete.php index 7ef9cf5b1..bdd3193b5 100644 --- a/s3_storage/vendor/akeeba/s3/minitest/Test/SmallFilesNoDelete.php +++ b/s3_storage/vendor/akeeba/s3/minitest/Test/SmallFilesNoDelete.php @@ -3,14 +3,14 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\MiniTest\Test; -use Akeeba\Engine\Postproc\Connector\S3v4\Connector; +use Akeeba\S3\Connector; /** * Upload and download small files (under 1MB) using a file source @@ -21,7 +21,7 @@ class SmallFilesNoDelete extends SmallFiles { public static function setup(Connector $s3, array $options): void { - self::$deleteRemote = false; + static::$deleteRemote = false; parent::setup($s3, $options); } diff --git a/s3_storage/vendor/akeeba/s3/minitest/Test/SmallFilesOnlyUpload.php b/s3_storage/vendor/akeeba/s3/minitest/Test/SmallFilesOnlyUpload.php index 1b6cdca74..e1aacafd1 100644 --- a/s3_storage/vendor/akeeba/s3/minitest/Test/SmallFilesOnlyUpload.php +++ b/s3_storage/vendor/akeeba/s3/minitest/Test/SmallFilesOnlyUpload.php @@ -3,14 +3,14 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\MiniTest\Test; -use Akeeba\Engine\Postproc\Connector\S3v4\Connector; +use Akeeba\S3\Connector; /** * Upload small files (under 1MB) using a file source @@ -21,8 +21,8 @@ class SmallFilesOnlyUpload extends SmallFiles { public static function setup(Connector $s3, array $options): void { - self::$deleteRemote = false; - self::$downloadAfter = false; + static::$deleteRemote = false; + static::$downloadAfter = false; parent::setup($s3, $options); } diff --git a/s3_storage/vendor/akeeba/s3/minitest/Test/SmallInlineFiles.php b/s3_storage/vendor/akeeba/s3/minitest/Test/SmallInlineFiles.php index 5cb942e75..d648d1062 100644 --- a/s3_storage/vendor/akeeba/s3/minitest/Test/SmallInlineFiles.php +++ b/s3_storage/vendor/akeeba/s3/minitest/Test/SmallInlineFiles.php @@ -3,15 +3,14 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\MiniTest\Test; - -use Akeeba\Engine\Postproc\Connector\S3v4\Connector; -use Akeeba\Engine\Postproc\Connector\S3v4\Input; +use Akeeba\S3\Connector; +use Akeeba\S3\Input; /** * Upload, download and delete small files (under 1MB) using a string source @@ -27,7 +26,7 @@ class SmallInlineFiles extends SmallFiles $uri = substr($uri, 0, $dotPos) . '.' . md5(microtime(false)) . substr($uri, $dotPos); // Create some random data to upload - $sourceData = self::getRandomData($size); + $sourceData = static::getRandomData($size); // Upload the data. Throws exception if it fails. $bucket = $options['bucket']; @@ -39,15 +38,15 @@ class SmallInlineFiles extends SmallFiles $result = true; // Should I download the file and compare its contents with my random data? - if (self::$downloadAfter) + if (static::$downloadAfter) { $downloadedData = $s3->getObject($bucket, $uri); - $result = self::areStringsEqual($sourceData, $downloadedData); + $result = static::areStringsEqual($sourceData, $downloadedData); } // Should I delete the remotely stored file? - if (self::$deleteRemote) + if (static::$deleteRemote) { // Delete the remote file. Throws exception if it fails. $s3->deleteObject($bucket, $uri); diff --git a/s3_storage/vendor/akeeba/s3/minitest/Test/SmallInlineFilesNoDelete.php b/s3_storage/vendor/akeeba/s3/minitest/Test/SmallInlineFilesNoDelete.php index 8ba99355d..d7e0d73ee 100644 --- a/s3_storage/vendor/akeeba/s3/minitest/Test/SmallInlineFilesNoDelete.php +++ b/s3_storage/vendor/akeeba/s3/minitest/Test/SmallInlineFilesNoDelete.php @@ -3,14 +3,14 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\MiniTest\Test; -use Akeeba\Engine\Postproc\Connector\S3v4\Connector; +use Akeeba\S3\Connector; /** * Upload and download small files (under 1MB) using a string source @@ -21,7 +21,7 @@ class SmallInlineFilesNoDelete extends SmallInlineFiles { public static function setup(Connector $s3, array $options): void { - self:: $deleteRemote = false; + static:: $deleteRemote = false; parent::setup($s3, $options); } diff --git a/s3_storage/vendor/akeeba/s3/minitest/Test/SmallInlineFilesOnlyUpload.php b/s3_storage/vendor/akeeba/s3/minitest/Test/SmallInlineFilesOnlyUpload.php index e41bf5ec1..890ecccd7 100644 --- a/s3_storage/vendor/akeeba/s3/minitest/Test/SmallInlineFilesOnlyUpload.php +++ b/s3_storage/vendor/akeeba/s3/minitest/Test/SmallInlineFilesOnlyUpload.php @@ -3,14 +3,14 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\MiniTest\Test; -use Akeeba\Engine\Postproc\Connector\S3v4\Connector; +use Akeeba\S3\Connector; /** * Upload small files (under 1MB) using a string source @@ -21,8 +21,8 @@ class SmallInlineFilesOnlyUpload extends SmallInlineFiles { public static function setup(Connector $s3, array $options): void { - self::$deleteRemote = false; - self::$downloadAfter = false; + static::$deleteRemote = false; + static::$downloadAfter = false; parent::setup($s3, $options); } diff --git a/s3_storage/vendor/akeeba/s3/minitest/Test/SmallInlineXMLFiles.php b/s3_storage/vendor/akeeba/s3/minitest/Test/SmallInlineXMLFiles.php new file mode 100644 index 000000000..5ab548936 --- /dev/null +++ b/s3_storage/vendor/akeeba/s3/minitest/Test/SmallInlineXMLFiles.php @@ -0,0 +1,131 @@ +putObject($input, $bucket, $uri); + + // Tentatively accept that this method succeeded. + $result = true; + + // Should I download the file and compare its contents with my random data? + if (static::$downloadAfter) + { + $downloadedData = $s3->getObject($bucket, $uri); + + $result = static::areStringsEqual($sourceData, $downloadedData); + } + + // Should I delete the remotely stored file? + if (static::$deleteRemote) + { + // Delete the remote file. Throws exception if it fails. + $s3->deleteObject($bucket, $uri); + } + + return $result; + } + + private static function createXMLFile(int $size): string + { + $out = <<< XML + + +XML; + + $chunks = floor(($size - 55) / 1024); + + for ($i = 1; $i <= $chunks; $i++) + { + $randomBlock = static::genRandomData(1024 - 63); + $out .= <<< XML + + $i + + +XML; + + } + + + $out .= <<< XML + +XML; + + return $out; + } + + private static function genRandomData(int $length): string + { + $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890'; + $maxLength = strlen($chars) - 1; + $salt = ''; + + for ($i = 0; $i < $length; $i++) + { + $salt .= substr($chars, random_int(0, $maxLength), 1); + } + + return $salt; + } +} \ No newline at end of file diff --git a/s3_storage/vendor/akeeba/s3/minitest/Test/StorageClasses.php b/s3_storage/vendor/akeeba/s3/minitest/Test/StorageClasses.php index 9e57ba7a7..42adce423 100644 --- a/s3_storage/vendor/akeeba/s3/minitest/Test/StorageClasses.php +++ b/s3_storage/vendor/akeeba/s3/minitest/Test/StorageClasses.php @@ -3,17 +3,17 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace Akeeba\MiniTest\Test; -use Akeeba\Engine\Postproc\Connector\S3v4\Acl; -use Akeeba\Engine\Postproc\Connector\S3v4\Connector; -use Akeeba\Engine\Postproc\Connector\S3v4\Input; -use Akeeba\Engine\Postproc\Connector\S3v4\StorageClass; +use Akeeba\S3\Acl; +use Akeeba\S3\Connector; +use Akeeba\S3\Input; +use Akeeba\S3\StorageClass; class StorageClasses extends AbstractTest { @@ -23,12 +23,12 @@ class StorageClasses extends AbstractTest public static function uploadRRS(Connector $s3, array $options): bool { - return self::upload($s3, $options, self::TEN_KB, 'rrs_test_10kb.dat', StorageClass::REDUCED_REDUNDANCY); + return static::upload($s3, $options, static::TEN_KB, 'rrs_test_10kb.dat', StorageClass::REDUCED_REDUNDANCY); } public static function uploadIntelligentTiering(Connector $s3, array $options): bool { - return self::upload($s3, $options, self::TEN_KB, 'rrs_test_10kb.dat', StorageClass::INTELLIGENT_TIERING); + return static::upload($s3, $options, static::TEN_KB, 'rrs_test_10kb.dat', StorageClass::INTELLIGENT_TIERING); } protected static function upload(Connector $s3, array $options, int $size, string $uri, string $storageClass = null) @@ -38,7 +38,7 @@ class StorageClasses extends AbstractTest $uri = substr($uri, 0, $dotPos) . '.' . md5(microtime(false)) . substr($uri, $dotPos); // Create some random data to upload - $sourceData = self::getRandomData($size); + $sourceData = static::getRandomData($size); // Upload the data. Throws exception if it fails. $bucket = $options['bucket']; @@ -54,15 +54,15 @@ class StorageClasses extends AbstractTest $result = true; // Should I download the file and compare its contents with my random data? - if (self::$downloadAfter) + if (static::$downloadAfter) { $downloadedData = $s3->getObject($bucket, $uri); - $result = self::areStringsEqual($sourceData, $downloadedData); + $result = static::areStringsEqual($sourceData, $downloadedData); } // Should I delete the remotely stored file? - if (self::$deleteRemote) + if (static::$deleteRemote) { // Delete the remote file. Throws exception if it fails. $s3->deleteObject($bucket, $uri); diff --git a/s3_storage/vendor/akeeba/s3/minitest/config.dist.php b/s3_storage/vendor/akeeba/s3/minitest/config.dist.php index 063934feb..b9124065f 100644 --- a/s3_storage/vendor/akeeba/s3/minitest/config.dist.php +++ b/s3_storage/vendor/akeeba/s3/minitest/config.dist.php @@ -3,10 +3,12 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ +// Custom Endpoint. The example below is for using LocalStack, see https://localstack.cloud/ +// define('DEFAULT_ENDPOINT', 'localhost.localstack.cloud:4566'); // Default Amazon S3 Access Key define('DEFAULT_ACCESS_KEY', 'your s3 access key'); // Default Amazon S3 Secret Key @@ -23,6 +25,8 @@ define('DEFAULT_DUALSTACK', false); define('DEFAULT_PATH_ACCESS', false); // Should I use SSL by default? define('DEFAULT_SSL', true); +// Create the 2100 test files in the bucket? +define('CREATE_2100_FILES', true); /** * Tests for standard key pairs allowing us to read, write and delete @@ -33,7 +37,9 @@ $standardTests = [ 'BucketsList', 'BucketLocation', 'SmallFiles', + 'HeadObject', 'SmallInlineFiles', + 'SmallInlineXMLFiles', 'SignedURLs', 'StorageClasses', 'ListFiles', diff --git a/s3_storage/vendor/akeeba/s3/minitest/minitest.php b/s3_storage/vendor/akeeba/s3/minitest/minitest.php index e9490321a..21e9dce1e 100644 --- a/s3_storage/vendor/akeeba/s3/minitest/minitest.php +++ b/s3_storage/vendor/akeeba/s3/minitest/minitest.php @@ -3,13 +3,13 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -use Akeeba\Engine\Postproc\Connector\S3v4\Configuration; -use Akeeba\Engine\Postproc\Connector\S3v4\Connector; -use Akeeba\Engine\Postproc\Connector\S3v4\Input; +use Akeeba\S3\Configuration; +use Akeeba\S3\Connector; +use Akeeba\S3\Input; // Necessary for including the library define('AKEEBAENGINE', 1); @@ -167,7 +167,7 @@ foreach ($testConfigurations as $description => $setup) 'dualstack' => DEFAULT_DUALSTACK, 'path_access' => DEFAULT_PATH_ACCESS, 'ssl' => DEFAULT_SSL, - 'endpoint' => null, + 'endpoint' => defined('DEFAULT_ENDPOINT') ? constant('DEFAULT_ENDPOINT') : null, ], $setup['configuration']); // Extract the test classes/methods to run @@ -185,15 +185,21 @@ foreach ($testConfigurations as $description => $setup) // Create the S3 configuration object $s3Configuration = new Configuration($configOptions['access'], $configOptions['secret'], $configOptions['signature'], $configOptions['region']); - $s3Configuration->setUseDualstackUrl($configOptions['dualstack']); - $s3Configuration->setUseLegacyPathStyle($configOptions['path_access']); - $s3Configuration->setSSL($configOptions['ssl']); + $s3Configuration->setRegion($configOptions['region']); + $s3Configuration->setSignatureMethod($configOptions['signature']); if (!is_null($configOptions['endpoint'])) { $s3Configuration->setEndpoint($configOptions['endpoint']); + // We need to redo this because setting the endpoint may reset these options + $s3Configuration->setRegion($configOptions['region']); + $s3Configuration->setSignatureMethod($configOptions['signature']); } + $s3Configuration->setUseDualstackUrl($configOptions['dualstack']); + $s3Configuration->setUseLegacyPathStyle($configOptions['path_access']); + $s3Configuration->setSSL($configOptions['ssl']); + // Create the connector object $s3Connector = new Connector($s3Configuration); diff --git a/s3_storage/vendor/akeeba/s3/src/Acl.php b/s3_storage/vendor/akeeba/s3/src/Acl.php index 36952cba3..3a58f5e8c 100644 --- a/s3_storage/vendor/akeeba/s3/src/Acl.php +++ b/s3_storage/vendor/akeeba/s3/src/Acl.php @@ -3,29 +3,29 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\Engine\Postproc\Connector\S3v4; +namespace Akeeba\S3; // Protection against direct access -defined('AKEEBAENGINE') or die(); +defined('AKEEBAENGINE') || die(); /** * Shortcuts to often used access control privileges */ class Acl { - const ACL_PRIVATE = 'private'; + public const ACL_PRIVATE = 'private'; - const ACL_PUBLIC_READ = 'public-read'; + public const ACL_PUBLIC_READ = 'public-read'; - const ACL_PUBLIC_READ_WRITE = 'public-read-write'; + public const ACL_PUBLIC_READ_WRITE = 'public-read-write'; - const ACL_AUTHENTICATED_READ = 'authenticated-read'; + public const ACL_AUTHENTICATED_READ = 'authenticated-read'; - const ACL_BUCKET_OWNER_READ = 'bucket-owner-read'; + public const ACL_BUCKET_OWNER_READ = 'bucket-owner-read'; - const ACL_BUCKET_OWNER_FULL_CONTROL = 'bucket-owner-full-control'; + public const ACL_BUCKET_OWNER_FULL_CONTROL = 'bucket-owner-full-control'; } diff --git a/s3_storage/vendor/akeeba/s3/src/Configuration.php b/s3_storage/vendor/akeeba/s3/src/Configuration.php index 13540dd0e..ca5fa19e2 100644 --- a/s3_storage/vendor/akeeba/s3/src/Configuration.php +++ b/s3_storage/vendor/akeeba/s3/src/Configuration.php @@ -3,14 +3,14 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\Engine\Postproc\Connector\S3v4; +namespace Akeeba\S3; // Protection against direct access -defined('AKEEBAENGINE') or die(); +defined('AKEEBAENGINE') || die(); /** * Holds the Amazon S3 confiugration credentials @@ -199,6 +199,8 @@ class Configuration throw new Exception\InvalidSignatureMethod; } + $this->signatureMethod = $signatureMethod; + // If you switch to v2 signatures we unset the region. if ($signatureMethod == 'v2') { @@ -214,13 +216,7 @@ class Configuration $this->setUseLegacyPathStyle(false); } - } else { - if (empty($this->getRegion())) { - $this->setRegion('us-east-1'); - } } - - $this->signatureMethod = $signatureMethod; } /** diff --git a/s3_storage/vendor/akeeba/s3/src/Connector.php b/s3_storage/vendor/akeeba/s3/src/Connector.php index 4bf52caae..54fdc3cc3 100644 --- a/s3_storage/vendor/akeeba/s3/src/Connector.php +++ b/s3_storage/vendor/akeeba/s3/src/Connector.php @@ -3,22 +3,22 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\Engine\Postproc\Connector\S3v4; +namespace Akeeba\S3; // Protection against direct access -use Akeeba\Engine\Postproc\Connector\S3v4\Exception\CannotDeleteFile; -use Akeeba\Engine\Postproc\Connector\S3v4\Exception\CannotGetBucket; -use Akeeba\Engine\Postproc\Connector\S3v4\Exception\CannotGetFile; -use Akeeba\Engine\Postproc\Connector\S3v4\Exception\CannotListBuckets; -use Akeeba\Engine\Postproc\Connector\S3v4\Exception\CannotOpenFileForWrite; -use Akeeba\Engine\Postproc\Connector\S3v4\Exception\CannotPutFile; -use Akeeba\Engine\Postproc\Connector\S3v4\Response\Error; +use Akeeba\S3\Exception\CannotDeleteFile; +use Akeeba\S3\Exception\CannotGetBucket; +use Akeeba\S3\Exception\CannotGetFile; +use Akeeba\S3\Exception\CannotListBuckets; +use Akeeba\S3\Exception\CannotOpenFileForWrite; +use Akeeba\S3\Exception\CannotPutFile; +use Akeeba\S3\Response\Error; -defined('AKEEBAENGINE') or die(); +defined('AKEEBAENGINE') || die(); class Connector { @@ -81,7 +81,10 @@ class Connector if (($input->getSize() <= 0) || (($input->getInputType() == Input::INPUT_DATA) && (!strlen($input->getDataReference())))) { - throw new CannotPutFile('Missing input parameters', 0); + if (substr($uri, -1) !== '/') + { + throw new CannotPutFile('Missing input parameters', 0); + } } // We need to post with Content-Length and Content-Type, MD5 is optional @@ -169,7 +172,7 @@ class Connector if (!is_resource($saveTo) && is_string($saveTo)) { - $fp = @fopen($saveTo, 'wb'); + $fp = @fopen($saveTo, 'w'); if ($fp === false) { @@ -193,6 +196,53 @@ class Connector $request->setHeader('Range', "bytes=$from-$to"); } + $response = $request->getResponse(true); + + if (!$response->error->isError() && (($response->code !== 200) && ($response->code !== 206))) + { + $response->error = new Error( + $response->code, + "Unexpected HTTP status {$response->code}" + ); + } + + if ($response->error->isError()) + { + throw new CannotGetFile( + sprintf( + __METHOD__ . "({%s}, {%s}): [%s] %s\n\nDebug info:\n%s", + $bucket, + $uri, + $response->error->getCode(), + $response->error->getMessage(), + print_r($response->body, true) + ) + ); + } + + if (!is_resource($fp)) + { + return $response->body; + } + + return null; + } + + /** + * Get information about an object. + * + * @param string $bucket Bucket name + * @param string $uri Object URI + * + * @return array The headers returned by Amazon S3 + * + * @throws CannotGetFile If the file does not exist + * @see https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadObject.html + */ + public function headObject(string $bucket, string $uri): array + { + $request = new Request('HEAD', $bucket, $uri, $this->configuration); + $response = $request->getResponse(); if (!$response->error->isError() && (($response->code !== 200) && ($response->code !== 206))) @@ -206,20 +256,21 @@ class Connector if ($response->error->isError()) { throw new CannotGetFile( - sprintf(__METHOD__ . "({$bucket}, {$uri}): [%s] %s\n\nDebug info:\n%s", - $response->error->getCode(), $response->error->getMessage(), print_r($response->body, true)), - $response->error->getCode() + sprintf( + __METHOD__ . "({%s}, {%s}): [%s] %s\n\nDebug info:\n%s", + $bucket, + $uri, + $response->error->getCode(), + $response->error->getMessage(), + print_r($response->body, true) + ) ); } - if (!is_resource($fp)) - { - return $response->body; - } - - return null; + return $response->getHeaders(); } + /** * Delete an object * @@ -244,9 +295,13 @@ class Connector if ($response->error->isError()) { throw new CannotDeleteFile( - sprintf(__METHOD__ . "({$bucket}, {$uri}): [%s] %s", - $response->error->getCode(), $response->error->getMessage()), - $response->error->getCode() + sprintf( + __METHOD__ . "({%s}, {%s}): [%s] %s", + $bucket, + $uri, + $response->error->getCode(), + $response->error->getMessage() + ) ); } } @@ -358,8 +413,7 @@ class Connector if ($response->error->isError()) { throw new CannotGetBucket( - sprintf(__METHOD__ . "(): [%s] %s", $response->error->getCode(), $response->error->getMessage()), - $response->error->getCode() + sprintf(__METHOD__ . "(): [%s] %s", $response->error->getCode(), $response->error->getMessage()) ); } @@ -403,168 +457,47 @@ class Connector */ public function getBucket(string $bucket, ?string $prefix = null, ?string $marker = null, ?int $maxKeys = null, string $delimiter = '/', bool $returnCommonPrefixes = false): array { - $request = new Request('GET', $bucket, '', $this->configuration); + $internalResult = $this->internalGetBucket($bucket, $prefix, $marker, $maxKeys, $delimiter, $returnCommonPrefixes); - if (!empty($prefix)) - { - $request->setParameter('prefix', $prefix); - } + /** + * @var array $objects + * @var ?string $nextMarker + */ + extract($internalResult); + unset($internalResult); - if (!empty($marker)) - { - $request->setParameter('marker', $marker); - } - - if (!empty($maxKeys)) - { - $request->setParameter('max-keys', $maxKeys); - } - - if (!empty($delimiter)) - { - $request->setParameter('delimiter', $delimiter); - } - - $response = $request->getResponse(); - - if (!$response->error->isError() && $response->code !== 200) - { - $response->error = new Error( - $response->code, - "Unexpected HTTP status {$response->code}" - ); - } - - if ($response->error->isError()) - { - throw new CannotGetBucket( - sprintf(__METHOD__ . "(): [%s] %s", $response->error->getCode(), $response->error->getMessage()), - $response->error->getCode() - ); - } - - $results = []; - - $nextMarker = null; - - if ($response->hasBody() && isset($response->body->Contents)) - { - foreach ($response->body->Contents as $c) - { - $results[(string) $c->Key] = [ - 'name' => (string) $c->Key, - 'time' => strtotime((string) $c->LastModified), - 'size' => (int) $c->Size, - 'hash' => substr((string) $c->ETag, 1, -1), - ]; - - $nextMarker = (string) $c->Key; - } - } - - if ($returnCommonPrefixes && $response->hasBody() && isset($response->body->CommonPrefixes)) - { - foreach ($response->body->CommonPrefixes as $c) - { - $results[(string) $c->Prefix] = ['prefix' => (string) $c->Prefix]; - } - } - - if ($response->hasBody() && isset($response->body->IsTruncated) && - ((string) $response->body->IsTruncated == 'false') - ) - { - return $results; - } - - if ($response->hasBody() && isset($response->body->NextMarker)) - { - $nextMarker = (string) $response->body->NextMarker; - } - - // Is it a truncated result? - $isTruncated = ($nextMarker !== null) && ((string) $response->body->IsTruncated == 'true'); - // Is this a truncated result and no maxKeys specified? - $isTruncatedAndNoMaxKeys = ($maxKeys == null) && $isTruncated; - // Is this a truncated result with less keys than the specified maxKeys; and common prefixes found but not returned to the caller? - $isTruncatedAndNeedsContinue = ($maxKeys != null) && $isTruncated && (count($results) < $maxKeys); - - // Loop through truncated results if maxKeys isn't specified - if ($isTruncatedAndNoMaxKeys || $isTruncatedAndNeedsContinue) + // Loop through truncated results if maxKeys isn't specified or we don't have enough object records yet. + if ($nextMarker !== null && ($maxKeys === null || count($objects) < $maxKeys)) { do { - $request = new Request('GET', $bucket, '', $this->configuration); + $internalResult = $this->internalGetBucket($bucket, $prefix, $nextMarker, $maxKeys, $delimiter, $returnCommonPrefixes); - if (!empty($prefix)) - { - $request->setParameter('prefix', $prefix); - } + $nextMarker = $internalResult['nextMarker']; + $objects = array_merge($objects, $internalResult['objects']); - $request->setParameter('marker', $nextMarker); + unset($internalResult); - if (!empty($delimiter)) - { - $request->setParameter('delimiter', $delimiter); - } - - try - { - $response = $request->getResponse(); - } - catch (\Exception $e) + // If the last call did not return a nextMarker I am done iterating. + if ($nextMarker === null) { break; } - if ($response->hasBody() && isset($response->body->Contents)) + // If we have maxKeys AND the number of objects is at least this many I am done iterating. + if ($maxKeys !== null && count($objects) >= $maxKeys) { - foreach ($response->body->Contents as $c) - { - $results[(string) $c->Key] = [ - 'name' => (string) $c->Key, - 'time' => strtotime((string) $c->LastModified), - 'size' => (int) $c->Size, - 'hash' => substr((string) $c->ETag, 1, -1), - ]; - - $nextMarker = (string) $c->Key; - } + break; } - - if ($returnCommonPrefixes && $response->hasBody() && isset($response->body->CommonPrefixes)) - { - foreach ($response->body->CommonPrefixes as $c) - { - $results[(string) $c->Prefix] = ['prefix' => (string) $c->Prefix]; - } - } - - if ($response->hasBody() && isset($response->body->NextMarker)) - { - $nextMarker = (string) $response->body->NextMarker; - } - - $continueCondition = false; - - if ($isTruncatedAndNoMaxKeys) - { - $continueCondition = !$response->error->isError() && $isTruncated; - } - - if ($isTruncatedAndNeedsContinue) - { - $continueCondition = !$response->error->isError() && $isTruncated && (count($results) < $maxKeys); - } - } while ($continueCondition); + } while (true); } - if (!is_null($maxKeys)) + if ($maxKeys !== null) { - $results = array_splice($results, 0, $maxKeys); + return array_splice($objects, 0, $maxKeys); } - return $results; + return $objects; } /** @@ -594,8 +527,7 @@ class Connector if ($response->error->isError()) { throw new CannotListBuckets( - sprintf(__METHOD__ . "(): [%s] %s", $response->error->getCode(), $response->error->getMessage()), - $response->error->getCode() + sprintf(__METHOD__ . "(): [%s] %s", $response->error->getCode(), $response->error->getMessage()) ); } @@ -691,7 +623,12 @@ class Connector if ($response->error->isError()) { throw new CannotPutFile( - sprintf(__METHOD__ . "(): [%s] %s\n\nDebug info:\n%s", $response->error->getCode(), $response->error->getMessage(), print_r($response->body, true)) + sprintf( + __METHOD__ . "(): [%s] %s\n\nDebug info:\n%s", + $response->error->getCode(), + $response->error->getMessage(), + print_r($response->body, true) + ) ); } @@ -958,4 +895,90 @@ class Connector { return $this->configuration; } + + private function internalGetBucket(string $bucket, ?string $prefix = null, ?string $marker = null, ?int $maxKeys = null, string $delimiter = '/', bool $returnCommonPrefixes = false): array + { + $request = new Request('GET', $bucket, '', $this->configuration); + + if (!empty($prefix)) + { + $request->setParameter('prefix', $prefix); + } + + if (!empty($marker)) + { + $request->setParameter('marker', $marker); + } + + if (!empty($maxKeys)) + { + $request->setParameter('max-keys', $maxKeys); + } + + if (!empty($delimiter)) + { + $request->setParameter('delimiter', $delimiter); + } + + $response = $request->getResponse(); + + if (!$response->error->isError() && $response->code !== 200) + { + $response->error = new Error( + $response->code, + "Unexpected HTTP status {$response->code}" + ); + } + + if ($response->error->isError()) + { + throw new CannotGetBucket( + sprintf(__METHOD__ . "(): [%s] %s", $response->error->getCode(), $response->error->getMessage()) + ); + } + + $results = [ + 'objects' => [], + 'nextMarker' => null, + ]; + + if ($response->hasBody() && isset($response->body->Contents)) + { + foreach ($response->body->Contents as $c) + { + $results['objects'][(string) $c->Key] = [ + 'name' => (string) $c->Key, + 'time' => strtotime((string) $c->LastModified), + 'size' => (int) $c->Size, + 'hash' => substr((string) $c->ETag, 1, -1), + ]; + + $results['nextMarker'] = (string) $c->Key; + } + } + + if ($returnCommonPrefixes && $response->hasBody() && isset($response->body->CommonPrefixes)) + { + foreach ($response->body->CommonPrefixes as $c) + { + $results['objects'][(string) $c->Prefix] = ['prefix' => (string) $c->Prefix]; + } + } + + if ($response->hasBody() && isset($response->body->IsTruncated) && + ((string) $response->body->IsTruncated == 'false') + ) + { + $results['nextMarker'] = null; + + return $results; + } + + if ($response->hasBody() && isset($response->body->NextMarker)) + { + $results['nextMarker'] = (string) $response->body->NextMarker; + } + + return $results; + } } diff --git a/s3_storage/vendor/akeeba/s3/src/Exception/CannotDeleteFile.php b/s3_storage/vendor/akeeba/s3/src/Exception/CannotDeleteFile.php index b98c566e5..05e3fa507 100644 --- a/s3_storage/vendor/akeeba/s3/src/Exception/CannotDeleteFile.php +++ b/s3_storage/vendor/akeeba/s3/src/Exception/CannotDeleteFile.php @@ -3,14 +3,14 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception; +namespace Akeeba\S3\Exception; // Protection against direct access -defined('AKEEBAENGINE') or die(); +defined('AKEEBAENGINE') || die(); use RuntimeException; diff --git a/s3_storage/vendor/akeeba/s3/src/Exception/CannotGetBucket.php b/s3_storage/vendor/akeeba/s3/src/Exception/CannotGetBucket.php index 6047a4b4b..e87c0994d 100644 --- a/s3_storage/vendor/akeeba/s3/src/Exception/CannotGetBucket.php +++ b/s3_storage/vendor/akeeba/s3/src/Exception/CannotGetBucket.php @@ -3,14 +3,14 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception; +namespace Akeeba\S3\Exception; // Protection against direct access -defined('AKEEBAENGINE') or die(); +defined('AKEEBAENGINE') || die(); use RuntimeException; diff --git a/s3_storage/vendor/akeeba/s3/src/Exception/CannotGetFile.php b/s3_storage/vendor/akeeba/s3/src/Exception/CannotGetFile.php index b97193533..5a9d8e823 100644 --- a/s3_storage/vendor/akeeba/s3/src/Exception/CannotGetFile.php +++ b/s3_storage/vendor/akeeba/s3/src/Exception/CannotGetFile.php @@ -3,14 +3,14 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception; +namespace Akeeba\S3\Exception; // Protection against direct access -defined('AKEEBAENGINE') or die(); +defined('AKEEBAENGINE') || die(); use RuntimeException; diff --git a/s3_storage/vendor/akeeba/s3/src/Exception/CannotListBuckets.php b/s3_storage/vendor/akeeba/s3/src/Exception/CannotListBuckets.php index de29bcbda..7a365fbaa 100644 --- a/s3_storage/vendor/akeeba/s3/src/Exception/CannotListBuckets.php +++ b/s3_storage/vendor/akeeba/s3/src/Exception/CannotListBuckets.php @@ -3,14 +3,14 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception; +namespace Akeeba\S3\Exception; // Protection against direct access -defined('AKEEBAENGINE') or die(); +defined('AKEEBAENGINE') || die(); use RuntimeException; diff --git a/s3_storage/vendor/akeeba/s3/src/Exception/CannotOpenFileForRead.php b/s3_storage/vendor/akeeba/s3/src/Exception/CannotOpenFileForRead.php index 6a206ffe8..78aa5cd2e 100644 --- a/s3_storage/vendor/akeeba/s3/src/Exception/CannotOpenFileForRead.php +++ b/s3_storage/vendor/akeeba/s3/src/Exception/CannotOpenFileForRead.php @@ -3,14 +3,14 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception; +namespace Akeeba\S3\Exception; // Protection against direct access -defined('AKEEBAENGINE') or die(); +defined('AKEEBAENGINE') || die(); use Exception; use RuntimeException; diff --git a/s3_storage/vendor/akeeba/s3/src/Exception/CannotOpenFileForWrite.php b/s3_storage/vendor/akeeba/s3/src/Exception/CannotOpenFileForWrite.php index ecec4e701..24f8a724b 100644 --- a/s3_storage/vendor/akeeba/s3/src/Exception/CannotOpenFileForWrite.php +++ b/s3_storage/vendor/akeeba/s3/src/Exception/CannotOpenFileForWrite.php @@ -3,14 +3,14 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception; +namespace Akeeba\S3\Exception; // Protection against direct access -defined('AKEEBAENGINE') or die(); +defined('AKEEBAENGINE') || die(); use Exception; use RuntimeException; diff --git a/s3_storage/vendor/akeeba/s3/src/Exception/CannotPutFile.php b/s3_storage/vendor/akeeba/s3/src/Exception/CannotPutFile.php index 9f53c4f5c..a7a2a4784 100644 --- a/s3_storage/vendor/akeeba/s3/src/Exception/CannotPutFile.php +++ b/s3_storage/vendor/akeeba/s3/src/Exception/CannotPutFile.php @@ -3,14 +3,14 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception; +namespace Akeeba\S3\Exception; // Protection against direct access -defined('AKEEBAENGINE') or die(); +defined('AKEEBAENGINE') || die(); use RuntimeException; diff --git a/s3_storage/vendor/akeeba/s3/src/Exception/ConfigurationError.php b/s3_storage/vendor/akeeba/s3/src/Exception/ConfigurationError.php index 60d64a6cb..2699b5e71 100644 --- a/s3_storage/vendor/akeeba/s3/src/Exception/ConfigurationError.php +++ b/s3_storage/vendor/akeeba/s3/src/Exception/ConfigurationError.php @@ -3,14 +3,14 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception; +namespace Akeeba\S3\Exception; // Protection against direct access -defined('AKEEBAENGINE') or die(); +defined('AKEEBAENGINE') || die(); use RuntimeException; diff --git a/s3_storage/vendor/akeeba/s3/src/Exception/InvalidAccessKey.php b/s3_storage/vendor/akeeba/s3/src/Exception/InvalidAccessKey.php index dd5616860..3db444b46 100644 --- a/s3_storage/vendor/akeeba/s3/src/Exception/InvalidAccessKey.php +++ b/s3_storage/vendor/akeeba/s3/src/Exception/InvalidAccessKey.php @@ -3,14 +3,14 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception; +namespace Akeeba\S3\Exception; // Protection against direct access -defined('AKEEBAENGINE') or die(); +defined('AKEEBAENGINE') || die(); use Exception; diff --git a/s3_storage/vendor/akeeba/s3/src/Exception/InvalidBody.php b/s3_storage/vendor/akeeba/s3/src/Exception/InvalidBody.php index 6e1e16904..57b628fd8 100644 --- a/s3_storage/vendor/akeeba/s3/src/Exception/InvalidBody.php +++ b/s3_storage/vendor/akeeba/s3/src/Exception/InvalidBody.php @@ -3,14 +3,14 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception; +namespace Akeeba\S3\Exception; // Protection against direct access -defined('AKEEBAENGINE') or die(); +defined('AKEEBAENGINE') || die(); use Exception; use RuntimeException; diff --git a/s3_storage/vendor/akeeba/s3/src/Exception/InvalidEndpoint.php b/s3_storage/vendor/akeeba/s3/src/Exception/InvalidEndpoint.php index b35e56d0f..3c58c0354 100644 --- a/s3_storage/vendor/akeeba/s3/src/Exception/InvalidEndpoint.php +++ b/s3_storage/vendor/akeeba/s3/src/Exception/InvalidEndpoint.php @@ -3,14 +3,14 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception; +namespace Akeeba\S3\Exception; // Protection against direct access -defined('AKEEBAENGINE') or die(); +defined('AKEEBAENGINE') || die(); use Exception; diff --git a/s3_storage/vendor/akeeba/s3/src/Exception/InvalidFilePointer.php b/s3_storage/vendor/akeeba/s3/src/Exception/InvalidFilePointer.php index 084b3cd0a..15c546cd0 100644 --- a/s3_storage/vendor/akeeba/s3/src/Exception/InvalidFilePointer.php +++ b/s3_storage/vendor/akeeba/s3/src/Exception/InvalidFilePointer.php @@ -3,14 +3,14 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception; +namespace Akeeba\S3\Exception; // Protection against direct access -defined('AKEEBAENGINE') or die(); +defined('AKEEBAENGINE') || die(); use Exception; use InvalidArgumentException; diff --git a/s3_storage/vendor/akeeba/s3/src/Exception/InvalidRegion.php b/s3_storage/vendor/akeeba/s3/src/Exception/InvalidRegion.php index fe6abc083..e21c1f67e 100644 --- a/s3_storage/vendor/akeeba/s3/src/Exception/InvalidRegion.php +++ b/s3_storage/vendor/akeeba/s3/src/Exception/InvalidRegion.php @@ -3,14 +3,14 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception; +namespace Akeeba\S3\Exception; // Protection against direct access -defined('AKEEBAENGINE') or die(); +defined('AKEEBAENGINE') || die(); use Exception; diff --git a/s3_storage/vendor/akeeba/s3/src/Exception/InvalidSecretKey.php b/s3_storage/vendor/akeeba/s3/src/Exception/InvalidSecretKey.php index 2348c2894..af58e5d9e 100644 --- a/s3_storage/vendor/akeeba/s3/src/Exception/InvalidSecretKey.php +++ b/s3_storage/vendor/akeeba/s3/src/Exception/InvalidSecretKey.php @@ -3,14 +3,14 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception; +namespace Akeeba\S3\Exception; // Protection against direct access -defined('AKEEBAENGINE') or die(); +defined('AKEEBAENGINE') || die(); use Exception; diff --git a/s3_storage/vendor/akeeba/s3/src/Exception/InvalidSignatureMethod.php b/s3_storage/vendor/akeeba/s3/src/Exception/InvalidSignatureMethod.php index 6145ed1c9..bd4fdedca 100644 --- a/s3_storage/vendor/akeeba/s3/src/Exception/InvalidSignatureMethod.php +++ b/s3_storage/vendor/akeeba/s3/src/Exception/InvalidSignatureMethod.php @@ -3,14 +3,14 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception; +namespace Akeeba\S3\Exception; // Protection against direct access -defined('AKEEBAENGINE') or die(); +defined('AKEEBAENGINE') || die(); use Exception; diff --git a/s3_storage/vendor/akeeba/s3/src/Exception/PropertyNotFound.php b/s3_storage/vendor/akeeba/s3/src/Exception/PropertyNotFound.php index c397fee86..3f521532b 100644 --- a/s3_storage/vendor/akeeba/s3/src/Exception/PropertyNotFound.php +++ b/s3_storage/vendor/akeeba/s3/src/Exception/PropertyNotFound.php @@ -3,14 +3,14 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\Engine\Postproc\Connector\S3v4\Exception; +namespace Akeeba\S3\Exception; // Protection against direct access -defined('AKEEBAENGINE') or die(); +defined('AKEEBAENGINE') || die(); use LogicException; diff --git a/s3_storage/vendor/akeeba/s3/src/Input.php b/s3_storage/vendor/akeeba/s3/src/Input.php index 4420bdba9..5dd5743d0 100644 --- a/s3_storage/vendor/akeeba/s3/src/Input.php +++ b/s3_storage/vendor/akeeba/s3/src/Input.php @@ -3,14 +3,14 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\Engine\Postproc\Connector\S3v4; +namespace Akeeba\S3; // Protection against direct access -defined('AKEEBAENGINE') or die(); +defined('AKEEBAENGINE') || die(); /** * Defines an input source for PUT/POST requests to Amazon S3 @@ -20,17 +20,17 @@ class Input /** * Input type: resource */ - const INPUT_RESOURCE = 1; + public const INPUT_RESOURCE = 1; /** * Input type: file */ - const INPUT_FILE = 2; + public const INPUT_FILE = 2; /** * Input type: raw data */ - const INPUT_DATA = 3; + public const INPUT_DATA = 3; /** * File pointer, in case we have a resource @@ -177,7 +177,13 @@ class Input { if (is_resource($this->fp)) { - @fclose($this->fp); + try + { + @fclose($this->fp); + } + catch (\Throwable $e) + { + } } } @@ -258,10 +264,16 @@ class Input if (is_resource($this->fp)) { - @fclose($this->fp); + try + { + @fclose($this->fp); + } + catch (\Throwable $e) + { + } } - $this->fp = @fopen($file, 'rb'); + $this->fp = @fopen($file, 'r'); if ($this->fp === false) { @@ -295,7 +307,13 @@ class Input if (is_resource($this->fp)) { - @fclose($this->fp); + try + { + @fclose($this->fp); + } + catch (\Throwable $e) + { + } } $this->file = null; @@ -329,7 +347,13 @@ class Input if (is_resource($this->fp)) { - @fclose($this->fp); + try + { + @fclose($this->fp); + } + catch (\Throwable $e) + { + } } $this->file = null; @@ -450,7 +474,7 @@ class Input */ public function setSha256(?string $sha256): void { - $this->sha256 = strtolower($sha256); + $this->sha256 = is_null($sha256) ? null : strtolower($sha256); } /** @@ -532,7 +556,7 @@ class Input switch ($this->getInputType()) { case self::INPUT_DATA: - return function_exists('mb_strlen') ? mb_strlen($this->data, '8bit') : strlen($this->data); + return function_exists('mb_strlen') ? mb_strlen($this->data ?? '', '8bit') : strlen($this->data ?? ''); break; case self::INPUT_FILE: @@ -635,7 +659,7 @@ class Input $ext = strtolower(pathInfo($file, PATHINFO_EXTENSION)); - return isset($exts[$ext]) ? $exts[$ext] : 'application/octet-stream'; + return $exts[$ext] ?? 'application/octet-stream'; } /** diff --git a/s3_storage/vendor/akeeba/s3/src/Request.php b/s3_storage/vendor/akeeba/s3/src/Request.php index 172113fcc..4237b862b 100644 --- a/s3_storage/vendor/akeeba/s3/src/Request.php +++ b/s3_storage/vendor/akeeba/s3/src/Request.php @@ -3,16 +3,16 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\Engine\Postproc\Connector\S3v4; +namespace Akeeba\S3; -use Akeeba\Engine\Postproc\Connector\S3v4\Response\Error; +use Akeeba\S3\Response\Error; // Protection against direct access -defined('AKEEBAENGINE') or die(); +defined('AKEEBAENGINE') || die(); class Request @@ -142,6 +142,12 @@ class Request // The date must always be added as a header $this->headers['Date'] = gmdate('D, d M Y H:i:s O'); + // S3-"compatible" services use a different date format. Because why not? + if (strpos($this->headers['Host'], '.amazonaws.com') === false) + { + $this->headers['Date'] = gmdate('D, d M Y H:i:s T'); + } + // If there is a security token we need to set up the X-Amz-Security-Token header $token = $this->configuration->getToken(); @@ -367,7 +373,7 @@ class Request * * @return Response */ - public function getResponse(): Response + public function getResponse(bool $rawResponse = false): Response { $this->processParametersIntoResource(); @@ -417,8 +423,10 @@ class Request * Caveat: if your bucket contains dots in the name we have to turn off host verification due to the way the * S3 SSL certificates are set up. */ - $isAmazonS3 = (substr($this->headers['Host'], -14) == '.amazonaws.com') || - substr($this->headers['Host'], -16) == 'amazonaws.com.cn'; + $isAmazonS3 = (substr($this->headers['Host'], -14) == '.amazonaws.com') + || substr( + $this->headers['Host'], -16 + ) == 'amazonaws.com.cn'; $tooManyDots = substr_count($this->headers['Host'], '.') > 4; $verifyHost = ($isAmazonS3 && $tooManyDots) ? 0 : 2; @@ -429,6 +437,27 @@ class Request curl_setopt($curl, CURLOPT_URL, $url); + /** + * Set the optional x-amz-date header for third party services. + * + * Amazon S3 proper expects to get the date from the Date header. Third party services typically implement the + * (wrongly) documented behaviour of using the x-amz-date header but, if it's missing, fall back to the Date + * header. Wasabi does not fall back; it only uses the x-amz-date header which is why we have to set it here if + * the request iss not made to Amazon S3 proper. + */ + $this->headers['x-amz-date'] = strpos($this->headers['Host'], '.amazonaws.com') !== false + ? '' + : (new \DateTime($this->headers['Date']))->format('Ymd\THis\Z'); + + /** + * Remove empty headers. + * + * While Amazon S3 proper and most third party implementations have no problem with that, there a few of them + * (such as Synology C2) which choke on empty headers. + */ + $this->headers = array_filter($this->headers); + + // Get the request signature $signer = Signature::getSignatureObject($this, $this->configuration->getSignatureMethod()); $signer->preProcessHeaders($this->headers, $this->amzHeaders); @@ -482,7 +511,7 @@ class Request $data = $this->input->getDataReference(); - if (strlen($data)) + if (strlen($data ?? '')) { curl_setopt($curl, CURLOPT_POSTFIELDS, $data); } @@ -538,12 +567,18 @@ class Request @curl_close($curl); // Set the body data - $this->response->finaliseBody(); + $this->response->finaliseBody($rawResponse); // Clean up file resources if (!is_null($this->fp) && is_resource($this->fp)) { - fclose($this->fp); + try + { + @fclose($this->fp); + } + catch (\Throwable $e) + { + } } return $this->response; @@ -560,7 +595,7 @@ class Request */ protected function __responseWriteCallback($curl, string $data): int { - if (in_array($this->response->code, [200, 206]) && !is_null($this->fp) && is_resource($this->fp)) + if (in_array($this->response->code, [0, 200, 206]) && !is_null($this->fp) && is_resource($this->fp)) { return fwrite($this->fp, $data); } @@ -573,7 +608,7 @@ class Request /** * cURL header callback * - * @param resource $curl cURL resource + * @param resource $curl cURL resource * @param string &$data Data * * @return int Length in bytes @@ -592,7 +627,15 @@ class Request return $strlen; } - [$header, $value] = explode(': ', trim($data), 2); + // Ignore malformed headers without a value. + if (strpos($data, ':') === false) + { + return $strlen; + } + + [$header, $value] = explode(':', trim($data), 2); + $header = trim($header ?? ''); + $value = trim($value ?? ''); switch (strtolower($header)) { @@ -609,10 +652,12 @@ class Request break; case 'etag': - $this->response->setHeader('hash', $value[0] == '"' ? substr($value, 1, -1) : $value); + $this->response->setHeader('hash', trim($value, '"')); break; default: + $this->response->setHeader(strtolower($header), is_numeric($value) ? (int) $value : $value); + if (preg_match('/^x-amz-meta-.*$/', $header)) { $this->setHeader($header, is_numeric($value) ? (int) $value : $value); @@ -652,13 +697,12 @@ class Request $query = substr($query, 0, -1); $this->uri .= $query; - if (array_key_exists('acl', $this->parameters) || - array_key_exists('location', $this->parameters) || - array_key_exists('torrent', $this->parameters) || - array_key_exists('logging', $this->parameters) || - array_key_exists('uploads', $this->parameters) || - array_key_exists('uploadId', $this->parameters) || - array_key_exists('partNumber', $this->parameters) + if (array_key_exists('acl', $this->parameters) || array_key_exists('location', $this->parameters) + || array_key_exists('torrent', $this->parameters) + || array_key_exists('logging', $this->parameters) + || array_key_exists('uploads', $this->parameters) + || array_key_exists('uploadId', $this->parameters) + || array_key_exists('partNumber', $this->parameters) ) { $this->resource .= $query; @@ -720,6 +764,8 @@ class Request } /** + * Only applies to Amazon S3 proper. + * * When using the Amazon S3 with the v4 signature API we have to use a different hostname per region. The * mapping can be found in https://docs.aws.amazon.com/general/latest/gr/s3.html#s3_region * @@ -728,25 +774,27 @@ class Request * * v4 signing does NOT support non-Amazon endpoints. */ - - // Most endpoints: s3-REGION.amazonaws.com - $regionalEndpoint = $region . '.amazonaws.com'; - - // Exception: China - if (substr($region, 0, 3) == 'cn-') + if (in_array($endpoint, ['s3.amazonaws.com', 'amazonaws.com.cn'])) { - // Chinese endpoint, e.g.: s3.cn-north-1.amazonaws.com.cn - $regionalEndpoint = $regionalEndpoint . '.cn'; - } + // Most endpoints: s3-REGION.amazonaws.com + $regionalEndpoint = $region . '.amazonaws.com'; - // If dual-stack URLs are enabled then prepend the endpoint - if ($configuration->getDualstackUrl()) - { - $endpoint = 's3.dualstack.' . $regionalEndpoint; - } - else - { - $endpoint = 's3.' . $regionalEndpoint; + // Exception: China + if (substr($region, 0, 3) == 'cn-') + { + // Chinese endpoint, e.g.: s3.cn-north-1.amazonaws.com.cn + $regionalEndpoint = $regionalEndpoint . '.cn'; + } + + // If dual-stack URLs are enabled then prepend the endpoint + if ($configuration->getDualstackUrl()) + { + $endpoint = 's3.dualstack.' . $regionalEndpoint; + } + else + { + $endpoint = 's3.' . $regionalEndpoint; + } } // Legacy path style access: return just the endpoint diff --git a/s3_storage/vendor/akeeba/s3/src/Response.php b/s3_storage/vendor/akeeba/s3/src/Response.php index a8078b293..01810941f 100644 --- a/s3_storage/vendor/akeeba/s3/src/Response.php +++ b/s3_storage/vendor/akeeba/s3/src/Response.php @@ -3,18 +3,18 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\Engine\Postproc\Connector\S3v4; +namespace Akeeba\S3; -use Akeeba\Engine\Postproc\Connector\S3v4\Exception\PropertyNotFound; -use Akeeba\Engine\Postproc\Connector\S3v4\Response\Error; +use Akeeba\S3\Exception\PropertyNotFound; +use Akeeba\S3\Response\Error; use SimpleXMLElement; // Protection against direct access -defined('AKEEBAENGINE') or die(); +defined('AKEEBAENGINE') || die(); /** * Amazon S3 API response object @@ -124,7 +124,7 @@ class Response * * @param string|SimpleXMLElement|null $body */ - public function setBody($body): void + public function setBody($body, bool $rawResponse = false): void { $this->body = null; @@ -135,7 +135,7 @@ class Response $this->body = $body; - $this->finaliseBody(); + $this->finaliseBody($rawResponse); } public function resetBody(): void @@ -153,7 +153,7 @@ class Response $this->body .= $data; } - public function finaliseBody(): void + public function finaliseBody(bool $rawResponse = false): void { if (!$this->hasBody()) { @@ -165,8 +165,14 @@ class Response $this->headers['type'] = 'text/plain'; } - if (is_string($this->body) && - (($this->headers['type'] == 'application/xml') || (substr($this->body, 0, 5) == 'body) + && + ( + ($this->headers['type'] == 'application/xml') + || (substr($this->body, 0, 5) == 'body = simplexml_load_string($this->body); @@ -332,8 +338,8 @@ class Response ) { $this->error = new Error( - $this->code, - (string) $this->body->Message + 500, + (string) $this->body->Code . ':' . (string) $this->body->Message ); if (isset($this->body->Resource)) diff --git a/s3_storage/vendor/akeeba/s3/src/Response/Error.php b/s3_storage/vendor/akeeba/s3/src/Response/Error.php index ca40985d8..69710bdfb 100644 --- a/s3_storage/vendor/akeeba/s3/src/Response/Error.php +++ b/s3_storage/vendor/akeeba/s3/src/Response/Error.php @@ -3,14 +3,14 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\Engine\Postproc\Connector\S3v4\Response; +namespace Akeeba\S3\Response; // Protection against direct access -defined('AKEEBAENGINE') or die(); +defined('AKEEBAENGINE') || die(); /** * S3 response error object diff --git a/s3_storage/vendor/akeeba/s3/src/Signature.php b/s3_storage/vendor/akeeba/s3/src/Signature.php index c841ebe1f..93d8f0f6a 100644 --- a/s3_storage/vendor/akeeba/s3/src/Signature.php +++ b/s3_storage/vendor/akeeba/s3/src/Signature.php @@ -3,14 +3,14 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\Engine\Postproc\Connector\S3v4; +namespace Akeeba\S3; // Protection against direct access -defined('AKEEBAENGINE') or die(); +defined('AKEEBAENGINE') || die(); /** * Base class for request signing objects. @@ -44,7 +44,7 @@ abstract class Signature */ public static function getSignatureObject(Request $request, string $method = 'v2'): self { - $className = '\\Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Signature\\' . ucfirst($method); + $className = __NAMESPACE__ . '\\Signature\\' . ucfirst($method); return new $className($request); } diff --git a/s3_storage/vendor/akeeba/s3/src/Signature/V2.php b/s3_storage/vendor/akeeba/s3/src/Signature/V2.php index 86d9be755..6864846fa 100644 --- a/s3_storage/vendor/akeeba/s3/src/Signature/V2.php +++ b/s3_storage/vendor/akeeba/s3/src/Signature/V2.php @@ -3,16 +3,16 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\Engine\Postproc\Connector\S3v4\Signature; +namespace Akeeba\S3\Signature; // Protection against direct access -defined('AKEEBAENGINE') or die(); +defined('AKEEBAENGINE') || die(); -use Akeeba\Engine\Postproc\Connector\S3v4\Signature; +use Akeeba\S3\Signature; /** * Implements the Amazon AWS v2 signatures @@ -123,7 +123,7 @@ class V2 extends Signature } // AMZ headers must be sorted and sent as separate lines - if (sizeof($amz) > 0) + if (count($amz) > 0) { sort($amz); $amzString = "\n" . implode("\n", $amz); @@ -150,8 +150,8 @@ class V2 extends Signature } $stringToSign = $verb . "\n" . - (isset($headers['Content-MD5']) ? $headers['Content-MD5'] : '') . "\n" . - (isset($headers['Content-Type']) ? $headers['Content-Type'] : '') . "\n" . + ($headers['Content-MD5'] ?? '') . "\n" . + ($headers['Content-Type'] ?? '') . "\n" . $headers['Date'] . $amzString . "\n" . $resourcePath; diff --git a/s3_storage/vendor/akeeba/s3/src/Signature/V4.php b/s3_storage/vendor/akeeba/s3/src/Signature/V4.php index e2bb908ee..b39f81f4a 100644 --- a/s3_storage/vendor/akeeba/s3/src/Signature/V4.php +++ b/s3_storage/vendor/akeeba/s3/src/Signature/V4.php @@ -3,16 +3,16 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\Engine\Postproc\Connector\S3v4\Signature; +namespace Akeeba\S3\Signature; // Protection against direct access -defined('AKEEBAENGINE') or die(); +defined('AKEEBAENGINE') || die(); -use Akeeba\Engine\Postproc\Connector\S3v4\Signature; +use Akeeba\S3\Signature; use DateTime; /** @@ -77,14 +77,20 @@ class V4 extends Signature * http://s3-eu-west-1.amazonaws.com/example instead of http://example.amazonaws.com/ for all authenticated URLs */ $region = $this->request->getConfiguration()->getRegion(); + $bucket = $this->request->getBucket(); $hostname = $this->getPresignedHostnameForRegion($region); + + if ($this->isValidBucketName($bucket)) + { + $hostname = $bucket . '.' . $hostname; + } + $this->request->setHeader('Host', $hostname); // Set the expiration time in seconds $this->request->setHeader('Expires', (int) $lifetime); // Get the query parameters, including the calculated signature - $bucket = $this->request->getBucket(); $uri = $this->request->getResource(); $headers = $this->request->getHeaders(); $protocol = $https ? 'https' : 'http'; @@ -93,6 +99,11 @@ class V4 extends Signature // The query parameters are returned serialized; unserialize them, then build and return the URL. $queryParameters = unserialize($serialisedParams); + if ($this->isValidBucketName($bucket) && strpos($uri, '/' . $bucket) === 0) + { + $uri = substr($uri, strlen($bucket) + 1); + } + $query = http_build_query($queryParameters); $url = $protocol . '://' . $headers['Host'] . $uri; @@ -129,8 +140,8 @@ class V4 extends Signature $signatureDate = new DateTime($headers['Date']); $credentialScope = $signatureDate->format('Ymd') . '/' . - $this->request->getConfiguration()->getRegion() . '/' . - 's3/aws4_request'; + $this->request->getConfiguration()->getRegion() . '/' . + 's3/aws4_request'; /** * If the Expires header is set up we're pre-signing a download URL. The string to sign is a bit @@ -208,12 +219,14 @@ class V4 extends Signature // The canonical URI is the resource path $canonicalURI = $resourcePath; $bucketResource = '/' . $bucket; - $regionalHostname = ($headers['Host'] != 's3.amazonaws.com') && ($headers['Host'] != $bucket . '.s3.amazonaws.com'); + $regionalHostname = ($headers['Host'] != 's3.amazonaws.com') + && ($headers['Host'] != $bucket . '.s3.amazonaws.com'); // Special case: if the canonical URI ends in /?location the bucket name DOES count as part of the canonical URL // even though the Host is s3.amazonaws.com (in which case it normally shouldn't count). Yeah, I know, it makes // no sense!!! - if (!$regionalHostname && ($headers['Host'] == 's3.amazonaws.com') && (substr($canonicalURI, -10) == '/?location')) + if (!$regionalHostname && ($headers['Host'] == 's3.amazonaws.com') + && (substr($canonicalURI, -10) == '/?location')) { $regionalHostname = true; } @@ -274,11 +287,11 @@ class V4 extends Signature // Calculate the canonical request $canonicalRequest = $verb . "\n" . - $canonicalURI . "\n" . - $canonicalQueryString . "\n" . - $canonicalHeaders . "\n" . - $signedHeaders . "\n" . - $requestPayloadHash; + $canonicalURI . "\n" . + $canonicalQueryString . "\n" . + $canonicalHeaders . "\n" . + $signedHeaders . "\n" . + $requestPayloadHash; $hashedCanonicalRequest = hash('sha256', $canonicalRequest); @@ -290,17 +303,40 @@ class V4 extends Signature $headers['Date'] = ''; } + /** + * The Date in the String-to-Sign is a messy situation. + * + * Amazon's documentation says it must be in ISO 8601 format: `Ymd\THis\Z`. Unfortunately, Amazon's + * documentation is actually wrong :troll_face: The actual Amazon S3 service expects the date to be formatted as + * per RFC1123. + * + * Most third party implementations have caught up to the fact that Amazon has documented the v4 signatures + * wrongly (naughty AWS!) and accept either format. + * + * Some other third party implementations, which never bothered to validate their implementations against Amazon + * S3 proper, only expect what Amazon has documented as "ISO 8601". Therefore, we detect third party services + * and switch to the as-documented date format. + * + * Some other third party services, like Wasabi, are broken in yet a different way. They will only use the date + * from the x-amz-date header, WITHOUT falling back to the Date header if the former is not present. This is + * the opposite of Amazon S3 proper which does expect the Date header. That's why the Request class sets both + * headers if the request is made to a service _other_ than Amazon S3 proper. + */ + $dateToSignFor = strpos($headers['Host'], '.amazonaws.com') !== false + ? $headers['Date'] + : $signatureDate->format('Ymd\THis\Z'); + $stringToSign = "AWS4-HMAC-SHA256\n" . - $headers['Date'] . "\n" . - $credentialScope . "\n" . - $hashedCanonicalRequest; + $dateToSignFor . "\n" . + $credentialScope . "\n" . + $hashedCanonicalRequest; if ($isPresignedURL) { $stringToSign = "AWS4-HMAC-SHA256\n" . - $parameters['X-Amz-Date'] . "\n" . - $credentialScope . "\n" . - $hashedCanonicalRequest; + $parameters['X-Amz-Date'] . "\n" . + $credentialScope . "\n" . + $hashedCanonicalRequest; } // ========== Step 3: Calculate the signature ========== @@ -313,9 +349,9 @@ class V4 extends Signature // See http://docs.aws.amazon.com/general/latest/gr/sigv4-add-signature-to-request.html $authorization = 'AWS4-HMAC-SHA256 Credential=' . - $this->request->getConfiguration()->getAccess() . '/' . $credentialScope . ', ' . - 'SignedHeaders=' . $signedHeaders . ', ' . - 'Signature=' . $signature; + $this->request->getConfiguration()->getAccess() . '/' . $credentialScope . ', ' . + 'SignedHeaders=' . $signedHeaders . ', ' . + 'Signature=' . $signature; // For presigned URLs we only return the Base64-encoded signature without the AWS format specifier and the // public access key. @@ -366,7 +402,14 @@ class V4 extends Signature */ private function getPresignedHostnameForRegion(string $region): string { - $endpoint = 's3.' . $region . '.amazonaws.com'; + $config = $this->request->getConfiguration(); + $endpoint = $config->getEndpoint(); + + if (empty($endpoint)) + { + $endpoint = 's3.' . $region . '.amazonaws.com'; + } + $dualstackEnabled = $this->request->getConfiguration()->getDualstackUrl(); // If dual-stack URLs are enabled then prepend the endpoint @@ -382,4 +425,83 @@ class V4 extends Signature return $endpoint; } + + /** + * Is this a valid bucket name? + * + * @param string $bucketName The bucket name to check + * @param bool $asSubdomain Should I put additional restrictions for use as a subdomain? + * + * @return bool + * @since 2.3.1 + * + * @see https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html + */ + private function isValidBucketName(string $bucketName, bool $asSubdomain = true): bool + { + /** + * If there are dots in the bucket name I can't use it as a subdomain. + * + * "If you include dots in a bucket's name, you can't use virtual-host-style addressing over HTTPS, unless you + * perform your own certificate validation. This is because the security certificates used for virtual hosting + * of buckets don't work for buckets with dots in their names." + */ + if ($asSubdomain && strpos($bucketName, '.') !== false) + { + return false; + } + + /** + * - Bucket names must be between 3 (min) and 63 (max) characters long. + * - Bucket names can consist only of lowercase letters, numbers, dots (.), and hyphens (-). + */ + if (!preg_match('/^[a-z0-9\-.]{3,63}$/', $bucketName)) + { + return false; + } + + // Bucket names must begin and end with a letter or number. + if (!preg_match('/^[a-z0-9].*[a-z0-9]$/', $bucketName)) + { + return false; + } + + // Bucket names must not contain two adjacent periods. + if (preg_match('/\.\./', $bucketName)) + { + return false; + } + + // Bucket names must not be formatted as an IP address (for example, 192.168.5.4). + if (preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/', $bucketName)) + { + return false; + } + + // Bucket names must not start with the prefix xn--. + if (strpos($bucketName, 'xn--') === 0) + { + return false; + } + + // Bucket names must not start with the prefix sthree- and the prefix sthree-configurator. + if (strpos($bucketName, 'sthree-') === 0) + { + return false; + } + + // Bucket names must not end with the suffix -s3alias. + if (substr($bucketName, -8) === '-s3alias') + { + return false; + } + + // Bucket names must not end with the suffix --ol-s3. + if (substr($bucketName, -7) === '--ol-s3') + { + return false; + } + + return true; + } } diff --git a/s3_storage/vendor/akeeba/s3/src/StorageClass.php b/s3_storage/vendor/akeeba/s3/src/StorageClass.php index 53ea310f5..0c213af24 100644 --- a/s3_storage/vendor/akeeba/s3/src/StorageClass.php +++ b/s3_storage/vendor/akeeba/s3/src/StorageClass.php @@ -3,11 +3,11 @@ * Akeeba Engine * * @package akeebaengine - * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd + * @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ -namespace Akeeba\Engine\Postproc\Connector\S3v4; +namespace Akeeba\S3; /** * Amazon S3 Storage Classes @@ -28,39 +28,39 @@ class StorageClass /** * Amazon S3 Standard (S3 Standard) */ - const STANDARD = 'STANDARD'; + public const STANDARD = 'STANDARD'; /** * Reduced redundancy storage * * Not recommended anymore. Use INTELLIGENT_TIERING instead. */ - const REDUCED_REDUNDANCY = 'REDUCED_REDUNDANCY'; + public const REDUCED_REDUNDANCY = 'REDUCED_REDUNDANCY'; /** * Amazon S3 Intelligent-Tiering (S3 Intelligent-Tiering) */ - const INTELLIGENT_TIERING = 'INTELLIGENT_TIERING'; + public const INTELLIGENT_TIERING = 'INTELLIGENT_TIERING'; /** * Amazon S3 Standard-Infrequent Access (S3 Standard-IA) */ - const STANDARD_IA = 'STANDARD_IA'; + public const STANDARD_IA = 'STANDARD_IA'; /** * Amazon S3 One Zone-Infrequent Access (S3 One Zone-IA) */ - const ONEZONE_IA = 'ONEZONE_IA'; + public const ONEZONE_IA = 'ONEZONE_IA'; /** * Amazon S3 Glacier (S3 Glacier) */ - const GLACIER = 'GLACIER'; + public const GLACIER = 'GLACIER'; /** * Amazon S3 Glacier Deep Archive (S3 Glacier Deep Archive) */ - const DEEP_ARCHIVE = 'DEEP_ARCHIVE'; + public const DEEP_ARCHIVE = 'DEEP_ARCHIVE'; /** * Manipulate the $headers array, setting the X-Amz-Storage-Class header for the requested storage class. diff --git a/s3_storage/vendor/akeeba/s3/src/aliasing.php b/s3_storage/vendor/akeeba/s3/src/aliasing.php new file mode 100644 index 000000000..4b408ac33 --- /dev/null +++ b/s3_storage/vendor/akeeba/s3/src/aliasing.php @@ -0,0 +1,35 @@ + $vendorDir . '/akeeba/s3/src/Acl.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Configuration' => $vendorDir . '/akeeba/s3/src/Configuration.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Connector' => $vendorDir . '/akeeba/s3/src/Connector.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Exception\\CannotDeleteFile' => $vendorDir . '/akeeba/s3/src/Exception/CannotDeleteFile.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Exception\\CannotGetBucket' => $vendorDir . '/akeeba/s3/src/Exception/CannotGetBucket.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Exception\\CannotGetFile' => $vendorDir . '/akeeba/s3/src/Exception/CannotGetFile.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Exception\\CannotListBuckets' => $vendorDir . '/akeeba/s3/src/Exception/CannotListBuckets.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Exception\\CannotOpenFileForRead' => $vendorDir . '/akeeba/s3/src/Exception/CannotOpenFileForRead.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Exception\\CannotOpenFileForWrite' => $vendorDir . '/akeeba/s3/src/Exception/CannotOpenFileForWrite.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Exception\\CannotPutFile' => $vendorDir . '/akeeba/s3/src/Exception/CannotPutFile.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Exception\\ConfigurationError' => $vendorDir . '/akeeba/s3/src/Exception/ConfigurationError.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Exception\\InvalidAccessKey' => $vendorDir . '/akeeba/s3/src/Exception/InvalidAccessKey.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Exception\\InvalidBody' => $vendorDir . '/akeeba/s3/src/Exception/InvalidBody.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Exception\\InvalidEndpoint' => $vendorDir . '/akeeba/s3/src/Exception/InvalidEndpoint.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Exception\\InvalidFilePointer' => $vendorDir . '/akeeba/s3/src/Exception/InvalidFilePointer.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Exception\\InvalidRegion' => $vendorDir . '/akeeba/s3/src/Exception/InvalidRegion.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Exception\\InvalidSecretKey' => $vendorDir . '/akeeba/s3/src/Exception/InvalidSecretKey.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Exception\\InvalidSignatureMethod' => $vendorDir . '/akeeba/s3/src/Exception/InvalidSignatureMethod.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Exception\\PropertyNotFound' => $vendorDir . '/akeeba/s3/src/Exception/PropertyNotFound.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Input' => $vendorDir . '/akeeba/s3/src/Input.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Request' => $vendorDir . '/akeeba/s3/src/Request.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Response' => $vendorDir . '/akeeba/s3/src/Response.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Response\\Error' => $vendorDir . '/akeeba/s3/src/Response/Error.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Signature' => $vendorDir . '/akeeba/s3/src/Signature.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Signature\\V2' => $vendorDir . '/akeeba/s3/src/Signature/V2.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Signature\\V4' => $vendorDir . '/akeeba/s3/src/Signature/V4.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\StorageClass' => $vendorDir . '/akeeba/s3/src/StorageClass.php', + 'Akeeba\\S3\\Acl' => $vendorDir . '/akeeba/s3/src/Acl.php', + 'Akeeba\\S3\\Configuration' => $vendorDir . '/akeeba/s3/src/Configuration.php', + 'Akeeba\\S3\\Connector' => $vendorDir . '/akeeba/s3/src/Connector.php', + 'Akeeba\\S3\\Exception\\CannotDeleteFile' => $vendorDir . '/akeeba/s3/src/Exception/CannotDeleteFile.php', + 'Akeeba\\S3\\Exception\\CannotGetBucket' => $vendorDir . '/akeeba/s3/src/Exception/CannotGetBucket.php', + 'Akeeba\\S3\\Exception\\CannotGetFile' => $vendorDir . '/akeeba/s3/src/Exception/CannotGetFile.php', + 'Akeeba\\S3\\Exception\\CannotListBuckets' => $vendorDir . '/akeeba/s3/src/Exception/CannotListBuckets.php', + 'Akeeba\\S3\\Exception\\CannotOpenFileForRead' => $vendorDir . '/akeeba/s3/src/Exception/CannotOpenFileForRead.php', + 'Akeeba\\S3\\Exception\\CannotOpenFileForWrite' => $vendorDir . '/akeeba/s3/src/Exception/CannotOpenFileForWrite.php', + 'Akeeba\\S3\\Exception\\CannotPutFile' => $vendorDir . '/akeeba/s3/src/Exception/CannotPutFile.php', + 'Akeeba\\S3\\Exception\\ConfigurationError' => $vendorDir . '/akeeba/s3/src/Exception/ConfigurationError.php', + 'Akeeba\\S3\\Exception\\InvalidAccessKey' => $vendorDir . '/akeeba/s3/src/Exception/InvalidAccessKey.php', + 'Akeeba\\S3\\Exception\\InvalidBody' => $vendorDir . '/akeeba/s3/src/Exception/InvalidBody.php', + 'Akeeba\\S3\\Exception\\InvalidEndpoint' => $vendorDir . '/akeeba/s3/src/Exception/InvalidEndpoint.php', + 'Akeeba\\S3\\Exception\\InvalidFilePointer' => $vendorDir . '/akeeba/s3/src/Exception/InvalidFilePointer.php', + 'Akeeba\\S3\\Exception\\InvalidRegion' => $vendorDir . '/akeeba/s3/src/Exception/InvalidRegion.php', + 'Akeeba\\S3\\Exception\\InvalidSecretKey' => $vendorDir . '/akeeba/s3/src/Exception/InvalidSecretKey.php', + 'Akeeba\\S3\\Exception\\InvalidSignatureMethod' => $vendorDir . '/akeeba/s3/src/Exception/InvalidSignatureMethod.php', + 'Akeeba\\S3\\Exception\\PropertyNotFound' => $vendorDir . '/akeeba/s3/src/Exception/PropertyNotFound.php', + 'Akeeba\\S3\\Input' => $vendorDir . '/akeeba/s3/src/Input.php', + 'Akeeba\\S3\\Request' => $vendorDir . '/akeeba/s3/src/Request.php', + 'Akeeba\\S3\\Response' => $vendorDir . '/akeeba/s3/src/Response.php', + 'Akeeba\\S3\\Response\\Error' => $vendorDir . '/akeeba/s3/src/Response/Error.php', + 'Akeeba\\S3\\Signature' => $vendorDir . '/akeeba/s3/src/Signature.php', + 'Akeeba\\S3\\Signature\\V2' => $vendorDir . '/akeeba/s3/src/Signature/V2.php', + 'Akeeba\\S3\\Signature\\V4' => $vendorDir . '/akeeba/s3/src/Signature/V4.php', + 'Akeeba\\S3\\StorageClass' => $vendorDir . '/akeeba/s3/src/StorageClass.php', ); diff --git a/s3_storage/vendor/composer/autoload_files.php b/s3_storage/vendor/composer/autoload_files.php new file mode 100644 index 000000000..cc01550fa --- /dev/null +++ b/s3_storage/vendor/composer/autoload_files.php @@ -0,0 +1,10 @@ + $vendorDir . '/akeeba/s3/src/aliasing.php', +); diff --git a/s3_storage/vendor/composer/autoload_psr4.php b/s3_storage/vendor/composer/autoload_psr4.php index b1215e7f5..400320bf0 100644 --- a/s3_storage/vendor/composer/autoload_psr4.php +++ b/s3_storage/vendor/composer/autoload_psr4.php @@ -6,5 +6,5 @@ $vendorDir = dirname(dirname(__FILE__)); $baseDir = dirname($vendorDir); return array( - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\' => array($vendorDir . '/akeeba/s3/src'), + 'Akeeba\\S3\\' => array($vendorDir . '/akeeba/s3/src'), ); diff --git a/s3_storage/vendor/composer/autoload_real.php b/s3_storage/vendor/composer/autoload_real.php index a5d4ee9a7..9df2057bb 100644 --- a/s3_storage/vendor/composer/autoload_real.php +++ b/s3_storage/vendor/composer/autoload_real.php @@ -50,6 +50,24 @@ class ComposerAutoloaderInitS3StorageAddon $loader->register(true); + if ($useStaticLoader) { + $includeFiles = Composer\Autoload\ComposerStaticInitS3StorageAddon::$files; + } else { + $includeFiles = require __DIR__ . '/autoload_files.php'; + } + foreach ($includeFiles as $fileIdentifier => $file) { + composerRequireS3StorageAddon($fileIdentifier, $file); + } + return $loader; } } + +function composerRequireS3StorageAddon($fileIdentifier, $file) +{ + if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { + require $file; + + $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; + } +} diff --git a/s3_storage/vendor/composer/autoload_static.php b/s3_storage/vendor/composer/autoload_static.php index 09179f94f..929f8194b 100644 --- a/s3_storage/vendor/composer/autoload_static.php +++ b/s3_storage/vendor/composer/autoload_static.php @@ -6,48 +6,52 @@ namespace Composer\Autoload; class ComposerStaticInitS3StorageAddon { + public static $files = array ( + '714ccd4b330431237faf946f71c4c9a4' => __DIR__ . '/..' . '/akeeba/s3/src/aliasing.php', + ); + public static $prefixLengthsPsr4 = array ( 'A' => array ( - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\' => 38, + 'Akeeba\\S3\\' => 10, ), ); public static $prefixDirsPsr4 = array ( - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\' => + 'Akeeba\\S3\\' => array ( 0 => __DIR__ . '/..' . '/akeeba/s3/src', ), ); public static $classMap = array ( - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Acl' => __DIR__ . '/..' . '/akeeba/s3/src/Acl.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Configuration' => __DIR__ . '/..' . '/akeeba/s3/src/Configuration.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Connector' => __DIR__ . '/..' . '/akeeba/s3/src/Connector.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Exception\\CannotDeleteFile' => __DIR__ . '/..' . '/akeeba/s3/src/Exception/CannotDeleteFile.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Exception\\CannotGetBucket' => __DIR__ . '/..' . '/akeeba/s3/src/Exception/CannotGetBucket.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Exception\\CannotGetFile' => __DIR__ . '/..' . '/akeeba/s3/src/Exception/CannotGetFile.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Exception\\CannotListBuckets' => __DIR__ . '/..' . '/akeeba/s3/src/Exception/CannotListBuckets.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Exception\\CannotOpenFileForRead' => __DIR__ . '/..' . '/akeeba/s3/src/Exception/CannotOpenFileForRead.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Exception\\CannotOpenFileForWrite' => __DIR__ . '/..' . '/akeeba/s3/src/Exception/CannotOpenFileForWrite.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Exception\\CannotPutFile' => __DIR__ . '/..' . '/akeeba/s3/src/Exception/CannotPutFile.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Exception\\ConfigurationError' => __DIR__ . '/..' . '/akeeba/s3/src/Exception/ConfigurationError.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Exception\\InvalidAccessKey' => __DIR__ . '/..' . '/akeeba/s3/src/Exception/InvalidAccessKey.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Exception\\InvalidBody' => __DIR__ . '/..' . '/akeeba/s3/src/Exception/InvalidBody.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Exception\\InvalidEndpoint' => __DIR__ . '/..' . '/akeeba/s3/src/Exception/InvalidEndpoint.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Exception\\InvalidFilePointer' => __DIR__ . '/..' . '/akeeba/s3/src/Exception/InvalidFilePointer.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Exception\\InvalidRegion' => __DIR__ . '/..' . '/akeeba/s3/src/Exception/InvalidRegion.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Exception\\InvalidSecretKey' => __DIR__ . '/..' . '/akeeba/s3/src/Exception/InvalidSecretKey.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Exception\\InvalidSignatureMethod' => __DIR__ . '/..' . '/akeeba/s3/src/Exception/InvalidSignatureMethod.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Exception\\PropertyNotFound' => __DIR__ . '/..' . '/akeeba/s3/src/Exception/PropertyNotFound.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Input' => __DIR__ . '/..' . '/akeeba/s3/src/Input.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Request' => __DIR__ . '/..' . '/akeeba/s3/src/Request.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Response' => __DIR__ . '/..' . '/akeeba/s3/src/Response.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Response\\Error' => __DIR__ . '/..' . '/akeeba/s3/src/Response/Error.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Signature' => __DIR__ . '/..' . '/akeeba/s3/src/Signature.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Signature\\V2' => __DIR__ . '/..' . '/akeeba/s3/src/Signature/V2.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\Signature\\V4' => __DIR__ . '/..' . '/akeeba/s3/src/Signature/V4.php', - 'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\StorageClass' => __DIR__ . '/..' . '/akeeba/s3/src/StorageClass.php', + 'Akeeba\\S3\\Acl' => __DIR__ . '/..' . '/akeeba/s3/src/Acl.php', + 'Akeeba\\S3\\Configuration' => __DIR__ . '/..' . '/akeeba/s3/src/Configuration.php', + 'Akeeba\\S3\\Connector' => __DIR__ . '/..' . '/akeeba/s3/src/Connector.php', + 'Akeeba\\S3\\Exception\\CannotDeleteFile' => __DIR__ . '/..' . '/akeeba/s3/src/Exception/CannotDeleteFile.php', + 'Akeeba\\S3\\Exception\\CannotGetBucket' => __DIR__ . '/..' . '/akeeba/s3/src/Exception/CannotGetBucket.php', + 'Akeeba\\S3\\Exception\\CannotGetFile' => __DIR__ . '/..' . '/akeeba/s3/src/Exception/CannotGetFile.php', + 'Akeeba\\S3\\Exception\\CannotListBuckets' => __DIR__ . '/..' . '/akeeba/s3/src/Exception/CannotListBuckets.php', + 'Akeeba\\S3\\Exception\\CannotOpenFileForRead' => __DIR__ . '/..' . '/akeeba/s3/src/Exception/CannotOpenFileForRead.php', + 'Akeeba\\S3\\Exception\\CannotOpenFileForWrite' => __DIR__ . '/..' . '/akeeba/s3/src/Exception/CannotOpenFileForWrite.php', + 'Akeeba\\S3\\Exception\\CannotPutFile' => __DIR__ . '/..' . '/akeeba/s3/src/Exception/CannotPutFile.php', + 'Akeeba\\S3\\Exception\\ConfigurationError' => __DIR__ . '/..' . '/akeeba/s3/src/Exception/ConfigurationError.php', + 'Akeeba\\S3\\Exception\\InvalidAccessKey' => __DIR__ . '/..' . '/akeeba/s3/src/Exception/InvalidAccessKey.php', + 'Akeeba\\S3\\Exception\\InvalidBody' => __DIR__ . '/..' . '/akeeba/s3/src/Exception/InvalidBody.php', + 'Akeeba\\S3\\Exception\\InvalidEndpoint' => __DIR__ . '/..' . '/akeeba/s3/src/Exception/InvalidEndpoint.php', + 'Akeeba\\S3\\Exception\\InvalidFilePointer' => __DIR__ . '/..' . '/akeeba/s3/src/Exception/InvalidFilePointer.php', + 'Akeeba\\S3\\Exception\\InvalidRegion' => __DIR__ . '/..' . '/akeeba/s3/src/Exception/InvalidRegion.php', + 'Akeeba\\S3\\Exception\\InvalidSecretKey' => __DIR__ . '/..' . '/akeeba/s3/src/Exception/InvalidSecretKey.php', + 'Akeeba\\S3\\Exception\\InvalidSignatureMethod' => __DIR__ . '/..' . '/akeeba/s3/src/Exception/InvalidSignatureMethod.php', + 'Akeeba\\S3\\Exception\\PropertyNotFound' => __DIR__ . '/..' . '/akeeba/s3/src/Exception/PropertyNotFound.php', + 'Akeeba\\S3\\Input' => __DIR__ . '/..' . '/akeeba/s3/src/Input.php', + 'Akeeba\\S3\\Request' => __DIR__ . '/..' . '/akeeba/s3/src/Request.php', + 'Akeeba\\S3\\Response' => __DIR__ . '/..' . '/akeeba/s3/src/Response.php', + 'Akeeba\\S3\\Response\\Error' => __DIR__ . '/..' . '/akeeba/s3/src/Response/Error.php', + 'Akeeba\\S3\\Signature' => __DIR__ . '/..' . '/akeeba/s3/src/Signature.php', + 'Akeeba\\S3\\Signature\\V2' => __DIR__ . '/..' . '/akeeba/s3/src/Signature/V2.php', + 'Akeeba\\S3\\Signature\\V4' => __DIR__ . '/..' . '/akeeba/s3/src/Signature/V4.php', + 'Akeeba\\S3\\StorageClass' => __DIR__ . '/..' . '/akeeba/s3/src/StorageClass.php', ); public static function getInitializer(ClassLoader $loader) diff --git a/s3_storage/vendor/composer/installed.json b/s3_storage/vendor/composer/installed.json index f122e1ba0..70c17e11c 100644 --- a/s3_storage/vendor/composer/installed.json +++ b/s3_storage/vendor/composer/installed.json @@ -1,35 +1,38 @@ [ { "name": "akeeba/s3", - "version": "2.0.0", - "version_normalized": "2.0.0.0", + "version": "2.3.1", + "version_normalized": "2.3.1.0", "source": { "type": "git", "url": "https://github.com/akeeba/s3.git", - "reference": "01520dae1f736555e08efda0ddc1044701bd340a" + "reference": "7f5b3e929c93eb02ba24472560c0cbbef735aed9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/akeeba/s3/zipball/01520dae1f736555e08efda0ddc1044701bd340a", - "reference": "01520dae1f736555e08efda0ddc1044701bd340a", + "url": "https://api.github.com/repos/akeeba/s3/zipball/7f5b3e929c93eb02ba24472560c0cbbef735aed9", + "reference": "7f5b3e929c93eb02ba24472560c0cbbef735aed9", "shasum": "" }, "require": { "ext-curl": "*", "ext-simplexml": "*", - "php": ">=7.1.0 <8.1" + "php": ">=7.1.0 <8.4" }, - "time": "2020-11-30T14:03:55+00:00", + "time": "2023-09-26T11:40:10+00:00", "type": "library", "installation-source": "dist", "autoload": { + "files": [ + "src/aliasing.php" + ], "psr-4": { - "Akeeba\\Engine\\Postproc\\Connector\\S3v4\\": "src" + "Akeeba\\S3\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "GPL-3.0+" + "GPL-3.0-or-later" ], "authors": [ { From 96a354bc6540c1a729729ba361a26d4ec0a8b1d2 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 20 Dec 2023 20:46:24 +0000 Subject: [PATCH 093/388] Bluesky/Tumblr: Set "received" to "created" if fetched after previous poll --- bluesky/bluesky.php | 69 +++++++++++++++++-------------- bluesky/bluesky_feed.php | 8 ++-- bluesky/bluesky_notifications.php | 8 ++-- bluesky/bluesky_timeline.php | 8 ++-- tumblr/tumblr.php | 26 +++++++----- 5 files changed, 65 insertions(+), 54 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index 2f70ed745..94d5cb319 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -498,13 +498,13 @@ function bluesky_cron() // Refresh the token now, so that it doesn't need to be refreshed in parallel by the following workers bluesky_get_token($pconfig['uid']); - Worker::add(['priority' => Worker::PRIORITY_MEDIUM, 'force_priority' => true], 'addon/bluesky/bluesky_timeline.php', $pconfig['uid']); - Worker::add(['priority' => Worker::PRIORITY_MEDIUM, 'force_priority' => true], 'addon/bluesky/bluesky_notifications.php', $pconfig['uid']); + Worker::add(['priority' => Worker::PRIORITY_MEDIUM, 'force_priority' => true], 'addon/bluesky/bluesky_timeline.php', $pconfig['uid'], $last); + Worker::add(['priority' => Worker::PRIORITY_MEDIUM, 'force_priority' => true], 'addon/bluesky/bluesky_notifications.php', $pconfig['uid'], $last); if (DI::pConfig()->get($pconfig['uid'], 'bluesky', 'import_feeds')) { $feeds = bluesky_get_feeds($pconfig['uid']); foreach ($feeds as $feed) { - Worker::add(['priority' => Worker::PRIORITY_MEDIUM, 'force_priority' => true], 'addon/bluesky/bluesky_feed.php', $pconfig['uid'], $feed); + Worker::add(['priority' => Worker::PRIORITY_MEDIUM, 'force_priority' => true], 'addon/bluesky/bluesky_feed.php', $pconfig['uid'], $feed, $last); } } } @@ -930,7 +930,7 @@ function bluesky_delete_post(string $uri, int $uid) Logger::debug('Deleted', ['parts' => $parts]); } -function bluesky_fetch_timeline(int $uid) +function bluesky_fetch_timeline(int $uid, int $last_poll) { $data = bluesky_xrpc_get($uid, 'app.bsky.feed.getTimeline'); if (empty($data)) { @@ -942,7 +942,7 @@ function bluesky_fetch_timeline(int $uid) } foreach (array_reverse($data->feed) as $entry) { - bluesky_process_post($entry->post, $uid, Item::PR_NONE, 0); + bluesky_process_post($entry->post, $uid, Item::PR_NONE, 0, $last_poll); if (!empty($entry->reason)) { bluesky_process_reason($entry->reason, bluesky_get_uri($entry->post), $uid); } @@ -993,7 +993,7 @@ function bluesky_process_reason(stdClass $reason, string $uri, int $uid) } } -function bluesky_fetch_notifications(int $uid) +function bluesky_fetch_notifications(int $uid, int $last_poll) { $data = bluesky_xrpc_get($uid, 'app.bsky.notification.listNotifications'); if (empty($data->notifications)) { @@ -1012,7 +1012,7 @@ function bluesky_fetch_notifications(int $uid) $item['gravity'] = Item::GRAVITY_ACTIVITY; $item['body'] = $item['verb'] = Activity::LIKE; $item['thr-parent'] = bluesky_get_uri($notification->record->subject); - $item['thr-parent'] = bluesky_fetch_missing_post($item['thr-parent'], $uid, $uid, $item['contact-id'], 0); + $item['thr-parent'] = bluesky_fetch_missing_post($item['thr-parent'], $uid, $uid, $item['contact-id'], 0, $last_poll); if (!empty($item['thr-parent'])) { $data = Item::insert($item); Logger::debug('Got like', ['uid' => $uid, 'result' => $data, 'uri' => $uri]); @@ -1026,7 +1026,7 @@ function bluesky_fetch_notifications(int $uid) $item['gravity'] = Item::GRAVITY_ACTIVITY; $item['body'] = $item['verb'] = Activity::ANNOUNCE; $item['thr-parent'] = bluesky_get_uri($notification->record->subject); - $item['thr-parent'] = bluesky_fetch_missing_post($item['thr-parent'], $uid, $uid, $item['contact-id'], 0); + $item['thr-parent'] = bluesky_fetch_missing_post($item['thr-parent'], $uid, $uid, $item['contact-id'], 0, $last_poll); if (!empty($item['thr-parent'])) { $data = Item::insert($item); Logger::debug('Got repost', ['uid' => $uid, 'result' => $data, 'uri' => $uri]); @@ -1041,17 +1041,17 @@ function bluesky_fetch_notifications(int $uid) break; case 'mention': - $data = bluesky_process_post($notification, $uid, Item::PR_PUSHED, 0); + $data = bluesky_process_post($notification, $uid, Item::PR_PUSHED, 0, $last_poll); Logger::debug('Got mention', ['uid' => $uid, 'result' => $data, 'uri' => $uri]); break; case 'reply': - $data = bluesky_process_post($notification, $uid, Item::PR_PUSHED, 0); + $data = bluesky_process_post($notification, $uid, Item::PR_PUSHED, 0, $last_poll); Logger::debug('Got reply', ['uid' => $uid, 'result' => $data, 'uri' => $uri]); break; case 'quote': - $data = bluesky_process_post($notification, $uid, Item::PR_PUSHED, 0); + $data = bluesky_process_post($notification, $uid, Item::PR_PUSHED, 0, $last_poll); Logger::debug('Got quote', ['uid' => $uid, 'result' => $data, 'uri' => $uri]); break; @@ -1062,7 +1062,7 @@ function bluesky_fetch_notifications(int $uid) } } -function bluesky_fetch_feed(int $uid, string $feed) +function bluesky_fetch_feed(int $uid, string $feed, int $last_poll) { $data = bluesky_xrpc_get($uid, 'app.bsky.feed.getFeed', ['feed' => $feed]); if (empty($data)) { @@ -1090,7 +1090,7 @@ function bluesky_fetch_feed(int $uid, string $feed) Logger::debug('Unwanted language detected', ['text' => $entry->post->record->text]); continue; } - $id = bluesky_process_post($entry->post, $uid, Item::PR_TAG, 0); + $id = bluesky_process_post($entry->post, $uid, Item::PR_TAG, 0, $last_poll); if (!empty($id)) { $post = Post::selectFirst(['uri-id'], ['id' => $id]); if (!empty($post['uri-id'])) { @@ -1106,7 +1106,7 @@ function bluesky_fetch_feed(int $uid, string $feed) } } -function bluesky_process_post(stdClass $post, int $uid, int $post_reason, $level): int +function bluesky_process_post(stdClass $post, int $uid, int $post_reason, int $level, int $last_poll): int { $uri = bluesky_get_uri($post); @@ -1121,20 +1121,20 @@ function bluesky_process_post(stdClass $post, int $uid, int $post_reason, $level Logger::debug('Importing post', ['uid' => $uid, 'indexedAt' => $post->indexedAt, 'uri' => $post->uri, 'cid' => $post->cid, 'root' => $post->record->reply->root ?? '']); $item = bluesky_get_header($post, $uri, $uid, $uid); - $item = bluesky_get_content($item, $post->record, $uri, $uid, $uid, $level); + $item = bluesky_get_content($item, $post->record, $uri, $uid, $uid, $level, $last_poll); if (empty($item)) { return 0; } if (!empty($post->embed)) { - $item = bluesky_add_media($post->embed, $item, $uid, $level); + $item = bluesky_add_media($post->embed, $item, $uid, $level, $last_poll); } if (empty($item['post-reason'])) { $item['post-reason'] = $post_reason; } - return item::insert($item); + return Item::insert($item); } function bluesky_get_header(stdClass $post, string $uri, int $uid, int $fetch_uid): array @@ -1172,7 +1172,7 @@ function bluesky_get_header(stdClass $post, string $uri, int $uid, int $fetch_ui return $item; } -function bluesky_get_content(array $item, stdClass $record, string $uri, int $uid, int $fetch_uid, int $level): array +function bluesky_get_content(array $item, stdClass $record, string $uri, int $uid, int $fetch_uid, int $level, int $last_poll): array { if (empty($item)) { return []; @@ -1181,7 +1181,7 @@ function bluesky_get_content(array $item, stdClass $record, string $uri, int $ui if (!empty($record->reply)) { $item['parent-uri'] = bluesky_get_uri($record->reply->root); if ($item['parent-uri'] != $uri) { - $item['parent-uri'] = bluesky_fetch_missing_post($item['parent-uri'], $uid, $fetch_uid, $item['contact-id'], $level); + $item['parent-uri'] = bluesky_fetch_missing_post($item['parent-uri'], $uid, $fetch_uid, $item['contact-id'], $level, $last_poll); if (empty($item['parent-uri'])) { return []; } @@ -1189,7 +1189,7 @@ function bluesky_get_content(array $item, stdClass $record, string $uri, int $ui $item['thr-parent'] = bluesky_get_uri($record->reply->parent); if (!in_array($item['thr-parent'], [$uri, $item['parent-uri']])) { - $item['thr-parent'] = bluesky_fetch_missing_post($item['thr-parent'], $uid, $fetch_uid, $item['contact-id'], $level, $item['parent-uri']); + $item['thr-parent'] = bluesky_fetch_missing_post($item['thr-parent'], $uid, $fetch_uid, $item['contact-id'], $level, $last_poll, $item['parent-uri']); if (empty($item['thr-parent'])) { return []; } @@ -1199,6 +1199,11 @@ function bluesky_get_content(array $item, stdClass $record, string $uri, int $ui $item['body'] = bluesky_get_text($record, $item['uri-id']); $item['created'] = DateTimeFormat::utc($record->createdAt, DateTimeFormat::MYSQL); $item['transmitted-languages'] = $record->langs ?? []; + + if (($last_poll != 0) && strtotime($item['created']) > $last_poll) { + $item['received'] = $item['created']; + } + return $item; } @@ -1259,7 +1264,7 @@ function bluesky_get_text(stdClass $record, int $uri_id): string return $text; } -function bluesky_add_media(stdClass $embed, array $item, int $fetch_uid, int $level): array +function bluesky_add_media(stdClass $embed, array $item, int $fetch_uid, int $level, int $last_poll): array { $type = '$type'; switch ($embed->$type) { @@ -1296,11 +1301,11 @@ function bluesky_add_media(stdClass $embed, array $item, int $fetch_uid, int $le break; } $shared = bluesky_get_header($embed->record, $uri, 0, $fetch_uid); - $shared = bluesky_get_content($shared, $embed->record->value, $uri, $item['uid'], $fetch_uid, $level); + $shared = bluesky_get_content($shared, $embed->record->value, $uri, $item['uid'], $fetch_uid, $level, $last_poll); if (!empty($shared)) { if (!empty($embed->record->embeds)) { foreach ($embed->record->embeds as $single) { - $shared = bluesky_add_media($single, $shared, $fetch_uid, $level); + $shared = bluesky_add_media($single, $shared, $fetch_uid, $level, $last_poll); } } Item::insert($shared); @@ -1316,11 +1321,11 @@ function bluesky_add_media(stdClass $embed, array $item, int $fetch_uid, int $le $shared = Post::selectFirst(['uri-id'], ['uri' => $uri, 'uid' => $item['uid']]); if (empty($shared)) { $shared = bluesky_get_header($embed->record->record, $uri, 0, $fetch_uid); - $shared = bluesky_get_content($shared, $embed->record->record->value, $uri, $item['uid'], $fetch_uid, $level); + $shared = bluesky_get_content($shared, $embed->record->record->value, $uri, $item['uid'], $fetch_uid, $level, $last_poll); if (!empty($shared)) { if (!empty($embed->record->record->embeds)) { foreach ($embed->record->record->embeds as $single) { - $shared = bluesky_add_media($single, $shared, $fetch_uid, $level); + $shared = bluesky_add_media($single, $shared, $fetch_uid, $level, $last_poll); } } Item::insert($shared); @@ -1331,7 +1336,7 @@ function bluesky_add_media(stdClass $embed, array $item, int $fetch_uid, int $le } if (!empty($embed->media)) { - $item = bluesky_add_media($embed->media, $item, $fetch_uid, $level); + $item = bluesky_add_media($embed->media, $item, $fetch_uid, $level, $last_poll); } break; @@ -1394,7 +1399,7 @@ function bluesky_get_uri_parts(string $uri): ?stdClass return $class; } -function bluesky_fetch_missing_post(string $uri, int $uid, int $fetch_uid, int $causer, int $level, string $fallback = ''): string +function bluesky_fetch_missing_post(string $uri, int $uid, int $fetch_uid, int $causer, int $level, int $last_poll = 0, string $fallback = ''): string { $fetched_uri = bluesky_fetch_post($uri, $uid); if (!empty($fetched_uri)) { @@ -1426,7 +1431,7 @@ function bluesky_fetch_missing_post(string $uri, int $uid, int $fetch_uid, int $ $cdata = []; } - return bluesky_process_thread($data->thread, $uid, $fetch_uid, $cdata, $level); + return bluesky_process_thread($data->thread, $uid, $fetch_uid, $cdata, $level, $last_poll); } function bluesky_fetch_post(string $uri, int $uid): string @@ -1444,7 +1449,7 @@ function bluesky_fetch_post(string $uri, int $uid): string return ''; } -function bluesky_process_thread(stdClass $thread, int $uid, int $fetch_uid, array $cdata, int $level): string +function bluesky_process_thread(stdClass $thread, int $uid, int $fetch_uid, array $cdata, int $level, int $last_poll): string { if (empty($thread->post)) { Logger::info('Invalid post', ['post' => $thread]); @@ -1456,7 +1461,7 @@ function bluesky_process_thread(stdClass $thread, int $uid, int $fetch_uid, arra if (empty($fetched_uri)) { Logger::debug('Process missing post', ['uri' => $uri]); $item = bluesky_get_header($thread->post, $uri, $uid, $uid); - $item = bluesky_get_content($item, $thread->post->record, $uri, $uid, $fetch_uid, $level); + $item = bluesky_get_content($item, $thread->post->record, $uri, $uid, $fetch_uid, $level, $last_poll); if (!empty($item)) { $item['post-reason'] = Item::PR_FETCHED; @@ -1465,7 +1470,7 @@ function bluesky_process_thread(stdClass $thread, int $uid, int $fetch_uid, arra } if (!empty($thread->post->embed)) { - $item = bluesky_add_media($thread->post->embed, $item, $uid, $level); + $item = bluesky_add_media($thread->post->embed, $item, $uid, $level, $last_poll); } $id = Item::insert($item); if (!$id) { @@ -1483,7 +1488,7 @@ function bluesky_process_thread(stdClass $thread, int $uid, int $fetch_uid, arra } foreach ($thread->replies ?? [] as $reply) { - $reply_uri = bluesky_process_thread($reply, $uid, $fetch_uid, $cdata, $level); + $reply_uri = bluesky_process_thread($reply, $uid, $fetch_uid, $cdata, $level, $last_poll); Logger::debug('Reply has been processed', ['uri' => $uri, 'reply' => $reply_uri]); } diff --git a/bluesky/bluesky_feed.php b/bluesky/bluesky_feed.php index 905fadfa7..c9a54223f 100644 --- a/bluesky/bluesky_feed.php +++ b/bluesky/bluesky_feed.php @@ -6,11 +6,11 @@ function bluesky_feed_run($argv, $argc) { require_once 'addon/bluesky/bluesky.php'; - if ($argc != 3) { + if ($argc != 4) { return; } - Logger::debug('Importing feed - start', ['user' => $argv[1], 'feed' => $argv[2]]); - bluesky_fetch_feed($argv[1], $argv[2]); - Logger::debug('Importing feed - done', ['user' => $argv[1], 'feed' => $argv[2]]); + Logger::debug('Importing feed - start', ['user' => $argv[1], 'feed' => $argv[2], 'last_poll' => $argv[3]]); + bluesky_fetch_feed($argv[1], $argv[2], $argv[3]); + Logger::debug('Importing feed - done', ['user' => $argv[1], 'feed' => $argv[2], 'last_poll' => $argv[3]]); } diff --git a/bluesky/bluesky_notifications.php b/bluesky/bluesky_notifications.php index 1377abbfe..ad35dfe0f 100644 --- a/bluesky/bluesky_notifications.php +++ b/bluesky/bluesky_notifications.php @@ -6,11 +6,11 @@ function bluesky_notifications_run($argv, $argc) { require_once 'addon/bluesky/bluesky.php'; - if ($argc != 2) { + if ($argc != 3) { return; } - Logger::notice('importing notifications - start', ['user' => $argv[1]]); - bluesky_fetch_notifications($argv[1]); - Logger::notice('importing notifications - done', ['user' => $argv[1]]); + Logger::notice('importing notifications - start', ['user' => $argv[1], 'last_poll' => $argv[2]]); + bluesky_fetch_notifications($argv[1], $argv[2]); + Logger::notice('importing notifications - done', ['user' => $argv[1], 'last_poll' => $argv[2]]); } diff --git a/bluesky/bluesky_timeline.php b/bluesky/bluesky_timeline.php index c5dfba265..22ef2224e 100644 --- a/bluesky/bluesky_timeline.php +++ b/bluesky/bluesky_timeline.php @@ -6,11 +6,11 @@ function bluesky_timeline_run($argv, $argc) { require_once 'addon/bluesky/bluesky.php'; - if ($argc != 2) { + if ($argc != 3) { return; } - Logger::notice('importing timeline - start', ['user' => $argv[1]]); - bluesky_fetch_timeline($argv[1]); - Logger::notice('importing timeline - done', ['user' => $argv[1]]); + Logger::notice('importing timeline - start', ['user' => $argv[1], 'last_poll' => $argv[2]]); + bluesky_fetch_timeline($argv[1], $argv[2]); + Logger::notice('importing timeline - done', ['user' => $argv[1], 'last_poll' => $argv[2]]); } diff --git a/tumblr/tumblr.php b/tumblr/tumblr.php index 812b5b30c..9b29deb31 100644 --- a/tumblr/tumblr.php +++ b/tumblr/tumblr.php @@ -439,8 +439,8 @@ function tumblr_cron() } Logger::notice('importing timeline - start', ['user' => $pconfig['uid']]); - tumblr_fetch_dashboard($pconfig['uid']); - tumblr_fetch_tags($pconfig['uid']); + tumblr_fetch_dashboard($pconfig['uid'], $last); + tumblr_fetch_tags($pconfig['uid'], $last); Logger::notice('importing timeline - done', ['user' => $pconfig['uid']]); } @@ -719,10 +719,11 @@ function tumblr_get_post_from_uri(string $uri): array /** * Fetch posts for user defined hashtags for the given user * - * @param integer $uid + * @param int $uid + * @param int $last_poll * @return void */ -function tumblr_fetch_tags(int $uid) +function tumblr_fetch_tags(int $uid, int $last_poll) { if (!DI::config()->get('tumblr', 'max_tags') ?? TUMBLR_DEFAULT_MAXIMUM_TAGS) { return; @@ -731,7 +732,7 @@ function tumblr_fetch_tags(int $uid) foreach (DI::pConfig()->get($uid, 'tumblr', 'tags') ?? [] as $tag) { $data = tumblr_get($uid, 'tagged', ['tag' => $tag]); foreach (array_reverse($data->response) as $post) { - $id = tumblr_process_post($post, $uid, Item::PR_TAG); + $id = tumblr_process_post($post, $uid, Item::PR_TAG, $last_poll); if (!empty($id)) { Logger::debug('Tag post imported', ['tag' => $tag, 'id' => $id]); $post = Post::selectFirst(['uri-id'], ['id' => $id]); @@ -745,10 +746,11 @@ function tumblr_fetch_tags(int $uid) /** * Fetch the dashboard (timeline) for the given user * - * @param integer $uid + * @param int $uid + * @param int $last_poll * @return void */ -function tumblr_fetch_dashboard(int $uid) +function tumblr_fetch_dashboard(int $uid, int $last_poll) { $parameters = ['reblog_info' => false, 'notes_info' => false, 'npf' => false]; @@ -774,13 +776,13 @@ function tumblr_fetch_dashboard(int $uid) Logger::debug('Importing post', ['uid' => $uid, 'created' => date(DateTimeFormat::MYSQL, $post->timestamp), 'id' => $post->id_string]); - tumblr_process_post($post, $uid, Item::PR_NONE); + tumblr_process_post($post, $uid, Item::PR_NONE, $last_poll); DI::pConfig()->set($uid, 'tumblr', 'last_id', $last); } } -function tumblr_process_post(stdClass $post, int $uid, int $post_reason): int +function tumblr_process_post(stdClass $post, int $uid, int $post_reason, int $last_poll = 0): int { $uri = 'tumblr::' . $post->id_string . ':' . $post->reblog_key; @@ -798,7 +800,11 @@ function tumblr_process_post(stdClass $post, int $uid, int $post_reason): int $item['post-reason'] = Item::PR_FOLLOWER; } - $id = item::insert($item); + if (($last_poll != 0) && strtotime($item['created']) > $last_poll) { + $item['received'] = $item['created']; + } + + $id = Item::insert($item); if ($id) { $stored = Post::selectFirst(['uri-id'], ['id' => $id]); From 96c70489f59c8c9ba6914873a8a2a70c41ca8fa9 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 21 Dec 2023 05:23:38 +0000 Subject: [PATCH 094/388] Tumblr/Bluesky: Avoid problems on first fetch --- bluesky/bluesky.php | 2 +- tumblr/tumblr.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index 94d5cb319..dac95437e 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -463,7 +463,7 @@ function bluesky_jot_nets(array &$jotnets_fields) function bluesky_cron() { - $last = DI::keyValue()->get('bluesky_last_poll'); + $last = (int)DI::keyValue()->get('bluesky_last_poll'); $poll_interval = intval(DI::config()->get('bluesky', 'poll_interval')); if (!$poll_interval) { diff --git a/tumblr/tumblr.php b/tumblr/tumblr.php index 9b29deb31..4d5368b80 100644 --- a/tumblr/tumblr.php +++ b/tumblr/tumblr.php @@ -406,7 +406,7 @@ function tumblr_settings_post(array &$b) function tumblr_cron() { - $last = DI::keyValue()->get('tumblr_last_poll'); + $last = (int)DI::keyValue()->get('tumblr_last_poll'); $poll_interval = intval(DI::config()->get('tumblr', 'poll_interval')); if (!$poll_interval) { From a26e90b2024ca3dbdccfd44ae5a33e11aafa7ae2 Mon Sep 17 00:00:00 2001 From: "Dr. Tobias Quathamer" Date: Fri, 5 Jan 2024 00:12:20 +0100 Subject: [PATCH 095/388] Initial commit of url_replace addon. This closes https://github.com/friendica/friendica/issues/13220 --- url_replace/LICENSE.md | 21 ++++++ url_replace/README.md | 17 +++++ url_replace/lang/C/messages.po | 50 +++++++++++++ url_replace/templates/admin.tpl | 5 ++ url_replace/url_replace.php | 127 ++++++++++++++++++++++++++++++++ 5 files changed, 220 insertions(+) create mode 100644 url_replace/LICENSE.md create mode 100644 url_replace/README.md create mode 100644 url_replace/lang/C/messages.po create mode 100644 url_replace/templates/admin.tpl create mode 100644 url_replace/url_replace.php diff --git a/url_replace/LICENSE.md b/url_replace/LICENSE.md new file mode 100644 index 000000000..09dc8f64a --- /dev/null +++ b/url_replace/LICENSE.md @@ -0,0 +1,21 @@ +# MIT License + +Copyright © 2024 Dr. Tobias Quathamer + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/url_replace/README.md b/url_replace/README.md new file mode 100644 index 000000000..278de91b9 --- /dev/null +++ b/url_replace/README.md @@ -0,0 +1,17 @@ +# URL replace + +This addon will replace all occurrences of specified URLs with the address of +alternative servers in all displayed postings on a Friendica node. + +You can use this to switch from Twitter (or X) to a nitter instance, from +YouTube to an invidious instance, or from some news sites to 12ft.io. + +Note: If you are using the twitter connector on your server, the links to the +contacts profile pages will not be replaced by this addon. Only links in the +body of the postings are affected. + +## Why + +- Access a website without JavaScript enabled to prevent JavaScript analytics + and potential IP-based tracking +- Avoid seeing ads on YouTube videos diff --git a/url_replace/lang/C/messages.po b/url_replace/lang/C/messages.po new file mode 100644 index 000000000..c09ad6d96 --- /dev/null +++ b/url_replace/lang/C/messages.po @@ -0,0 +1,50 @@ +# ADDON url_replace +# Copyright (C) +# This file is distributed under the same license as the Friendica url_replace addon package. +# +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-01-05 00:06+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: url_replace.php:54 +msgid "Nitter server" +msgstr "" + +#: url_replace.php:56 +msgid "Specify the URL with protocol. The default is https://nitter.net." +msgstr "" + +#: url_replace.php:62 +msgid "Invidious server" +msgstr "" + +#: url_replace.php:64 +msgid "Specify the URL with protocol. The default is https://yewtu.be." +msgstr "" + +#: url_replace.php:70 +msgid "Sites which are accessed through 12ft.io" +msgstr "" + +#: url_replace.php:72 +msgid "Specify the URLs with protocol, one per line." +msgstr "" + +#: url_replace.php:76 +msgid "Save settings" +msgstr "" + +#: url_replace.php:125 +msgid "(URL replace addon enabled for X, YouTube and some news sites.)" +msgstr "" diff --git a/url_replace/templates/admin.tpl b/url_replace/templates/admin.tpl new file mode 100644 index 000000000..b99e63552 --- /dev/null +++ b/url_replace/templates/admin.tpl @@ -0,0 +1,5 @@ +{{include file="field_input.tpl" field=$nitter_server}} +{{include file="field_input.tpl" field=$invidious_server}} +{{include file="field_textarea.tpl" field=$twelvefeet_sites}} + +
diff --git a/url_replace/url_replace.php b/url_replace/url_replace.php new file mode 100644 index 000000000..51bc10fe8 --- /dev/null +++ b/url_replace/url_replace.php @@ -0,0 +1,127 @@ + + * Maintainer: Dr. Tobias Quathamer + */ +use Friendica\Core\Hook; +use Friendica\Core\Renderer; +use Friendica\DI; + +function url_replace_install() +{ + Hook::register('prepare_body_final', 'addon/url_replace/url_replace.php', 'url_replace_render'); +} + +/** + * Handle sent data from admin settings + */ +function url_replace_addon_admin_post() +{ + DI::config()->set('url_replace', 'nitter_server', rtrim(trim($_POST['nitter_server']), '/')); + DI::config()->set('url_replace', 'invidious_server', rtrim(trim($_POST['invidious_server']), '/')); + // Convert twelvefeet_sites into an array before setting the new value + $twelvefeet_sites = explode(PHP_EOL, $_POST['twelvefeet_sites']); + // Normalize URLs by using lower case, removing a trailing slash and whitespace + $twelvefeet_sites = array_map(fn ($value): string => rtrim(trim(strtolower($value)), '/'), $twelvefeet_sites); + // Do not store empty lines or duplicates + $twelvefeet_sites = array_filter($twelvefeet_sites, fn ($value): bool => !empty($value)); + $twelvefeet_sites = array_unique($twelvefeet_sites); + // Ensure a protocol and default to HTTPS + $twelvefeet_sites = array_map( + fn ($value): string => substr($value, 0, 4) !== 'http' ? 'https://'.$value : $value, + $twelvefeet_sites + ); + asort($twelvefeet_sites); + DI::config()->set('url_replace', 'twelvefeet_sites', $twelvefeet_sites); +} + +/** + * Hook into admin settings to enable choosing a different server + * for twitter, youtube, and news sites. + */ +function url_replace_addon_admin(string &$o) +{ + $nitter_server = DI::config()->get('url_replace', 'nitter_server'); + $invidious_server = DI::config()->get('url_replace', 'invidious_server'); + $twelvefeet_sites = implode(PHP_EOL, DI::config()->get('url_replace', 'twelvefeet_sites')); + $t = Renderer::getMarkupTemplate('admin.tpl', 'addon/url_replace/'); + $o = Renderer::replaceMacros($t, [ + '$nitter_server' => [ + 'nitter_server', + DI::l10n()->t('Nitter server'), + $nitter_server, + DI::l10n()->t('Specify the URL with protocol. The default is https://nitter.net.'), + null, + 'placeholder="https://nitter.net"', + ], + '$invidious_server' => [ + 'invidious_server', + DI::l10n()->t('Invidious server'), + $invidious_server, + DI::l10n()->t('Specify the URL with protocol. The default is https://yewtu.be.'), + null, + 'placeholder="https://yewtu.be"', + ], + '$twelvefeet_sites' => [ + 'twelvefeet_sites', + DI::l10n()->t('Sites which are accessed through 12ft.io'), + $twelvefeet_sites, + DI::l10n()->t('Specify the URLs with protocol, one per line.'), + null, + 'rows=6' + ], + '$submit' => DI::l10n()->t('Save settings'), + ]); +} + +/** + * Replace proprietary URLs with their specified counterpart + */ +function url_replace_render(array &$b) +{ + $replaced = false; + + $nitter_server = DI::config()->get('url_replace', 'nitter_server'); + if (empty($nitter_server)) { + $nitter_server = 'https://nitter.net'; + } + + $invidious_server = DI::config()->get('url_replace', 'invidious_server'); + if (empty($invidious_server)) { + $invidious_server = 'https://yewtu.be'; + } + + // Handle some of twitter and youtube + $replacements = [ + 'https://mobile.twitter.com' => $nitter_server, + 'https://twitter.com' => $nitter_server, + 'https://mobile.x.com' => $nitter_server, + 'https://x.com' => $nitter_server, + 'https://www.youtube.com' => $invidious_server, + 'https://youtube.com' => $invidious_server, + 'https://m.youtube.com' => $invidious_server, + 'https://youtu.be' => $invidious_server, + ]; + foreach ($replacements as $server => $replacement) { + if (strpos($b['html'], $server) !== false) { + $b['html'] = str_replace($server, $replacement, $b['html']); + $replaced = true; + } + } + + $twelvefeet_sites = DI::config()->get('url_replace', 'twelvefeet_sites'); + foreach ($twelvefeet_sites as $twelvefeet_site) { + if (strpos($b['html'], $twelvefeet_site) !== false) { + $b['html'] = str_replace($twelvefeet_site, 'https://12ft.io/'.$twelvefeet_site, $b['html']); + $replaced = true; + } + } + + + if ($replaced) { + $b['html'] .= '

' . DI::l10n()->t('(URL replace addon enabled for X, YouTube and some news sites.)') . '

'; + } +} From bddb7f4d49d1f36120b0054d2763aa7c89d03f17 Mon Sep 17 00:00:00 2001 From: "Dr. Tobias Quathamer" Date: Mon, 8 Jan 2024 10:36:21 +0100 Subject: [PATCH 096/388] Fix PHP warning and use quotes --- url_replace/url_replace.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/url_replace/url_replace.php b/url_replace/url_replace.php index 51bc10fe8..4c61b6c21 100644 --- a/url_replace/url_replace.php +++ b/url_replace/url_replace.php @@ -71,7 +71,7 @@ function url_replace_addon_admin(string &$o) $twelvefeet_sites, DI::l10n()->t('Specify the URLs with protocol, one per line.'), null, - 'rows=6' + 'rows="6"' ], '$submit' => DI::l10n()->t('Save settings'), ]); @@ -113,6 +113,9 @@ function url_replace_render(array &$b) } $twelvefeet_sites = DI::config()->get('url_replace', 'twelvefeet_sites'); + if (empty($twelvefeet_sites)) { + $twelvefeet_sites = []; + } foreach ($twelvefeet_sites as $twelvefeet_site) { if (strpos($b['html'], $twelvefeet_site) !== false) { $b['html'] = str_replace($twelvefeet_site, 'https://12ft.io/'.$twelvefeet_site, $b['html']); From 13fd713b66cdce186f30cb70bdcf237814f961b5 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Fri, 12 Jan 2024 01:16:01 -0500 Subject: [PATCH 097/388] [various] Rename ICanHandleHttpResponses->getBody to getBodyString - Depends on https://github.com/friendica/friendica/pull/13826 --- bluesky/bluesky.php | 14 +++++++------- discourse/discourse.php | 4 ++-- dwpost/dwpost.php | 2 +- ijpost/ijpost.php | 2 +- libertree/libertree.php | 2 +- ljpost/ljpost.php | 2 +- mailstream/mailstream.php | 2 +- mastodoncustomemojis/mastodoncustomemojis.php | 2 +- openstreetmap/openstreetmap.php | 2 +- tumblr/tumblr.php | 10 +++++----- twitter/twitter.php | 4 ++-- webdav_storage/src/WebDav.php | 4 ++-- wppost/wppost.php | 2 +- 13 files changed, 26 insertions(+), 26 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index dac95437e..a2c85ad37 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -1111,11 +1111,11 @@ function bluesky_process_post(stdClass $post, int $uid, int $post_reason, int $l $uri = bluesky_get_uri($post); if ($id = Post::selectFirst(['id'], ['uri' => $uri, 'uid' => $uid])) { - return $id['id']; + return $id['id']; } if ($id = Post::selectFirst(['id'], ['extid' => $uri, 'uid' => $uid])) { - return $id['id']; + return $id['id']; } Logger::debug('Importing post', ['uid' => $uid, 'indexedAt' => $post->indexedAt, 'uri' => $post->uri, 'cid' => $post->cid, 'root' => $post->record->reply->root ?? '']); @@ -1251,7 +1251,7 @@ function bluesky_get_text(stdClass $record, int $uri_id): string $url = DI::baseUrl() . '/search?tag=' . urlencode($feature->tag); $linktext = '#' . $feature->tag; break; - + default: Logger::notice('Unhandled feature type', ['type' => $feature->$type, 'feature' => $feature, 'record' => $record]); break; @@ -1736,13 +1736,13 @@ function bluesky_post(int $uid, string $url, string $params, array $headers): ?s } if (!$curlResult->isSuccess()) { - Logger::notice('API Error', ['error' => json_decode($curlResult->getBody()) ?: $curlResult->getBody()]); + Logger::notice('API Error', ['error' => json_decode($curlResult->getBodyString()) ?: $curlResult->getBodyString()]); DI::pConfig()->set($uid, 'bluesky', 'status', BLUEKSY_STATUS_API_FAIL); return null; } DI::pConfig()->set($uid, 'bluesky', 'status', BLUEKSY_STATUS_SUCCESS); - return json_decode($curlResult->getBody()); + return json_decode($curlResult->getBodyString()); } function bluesky_xrpc_get(int $uid, string $url, array $parameters = []): ?stdClass @@ -1767,9 +1767,9 @@ function bluesky_get(string $url, string $accept_content = HttpClientAccept::DEF } if (!$curlResult->isSuccess()) { - Logger::notice('API Error', ['error' => json_decode($curlResult->getBody()) ?: $curlResult->getBody()]); + Logger::notice('API Error', ['error' => json_decode($curlResult->getBodyString()) ?: $curlResult->getBodyString()]); return null; } - return json_decode($curlResult->getBody()); + return json_decode($curlResult->getBodyString()); } diff --git a/discourse/discourse.php b/discourse/discourse.php index 3d27c5b0b..298b3f3ee 100644 --- a/discourse/discourse.php +++ b/discourse/discourse.php @@ -126,7 +126,7 @@ function discourse_fetch_post($host, $topic, $pid) return false; } - $raw = $curlResult->getBody(); + $raw = $curlResult->getBodyString(); $data = json_decode($raw, true); $posts = $data['post_stream']['posts']; foreach($posts as $post) { @@ -162,7 +162,7 @@ function discourse_fetch_post_from_api(&$message, $post, $host) return false; } - $raw = $curlResult->getBody(); + $raw = $curlResult->getBodyString(); $data = json_decode($raw, true); if (empty($data)) { return false; diff --git a/dwpost/dwpost.php b/dwpost/dwpost.php index 6c1742e41..4ad5021f7 100644 --- a/dwpost/dwpost.php +++ b/dwpost/dwpost.php @@ -192,7 +192,7 @@ EOT; Logger::debug('dwpost: data: ' . $xml); if ($dw_blog !== 'test') { - $x = DI::httpClient()->post($dw_blog, $xml, ['Content-Type' => 'text/xml'])->getBody(); + $x = DI::httpClient()->post($dw_blog, $xml, ['Content-Type' => 'text/xml'])->getBodyString(); } Logger::info('posted to dreamwidth: ' . ($x) ? $x : ''); diff --git a/ijpost/ijpost.php b/ijpost/ijpost.php index 55d3fb058..885bc289c 100644 --- a/ijpost/ijpost.php +++ b/ijpost/ijpost.php @@ -186,7 +186,7 @@ EOT; Logger::debug('ijpost: data: ' . $xml); if ($ij_blog !== 'test') { - $x = DI::httpClient()->post($ij_blog, $xml, ['Content-Type' => 'text/xml'])->getBody(); + $x = DI::httpClient()->post($ij_blog, $xml, ['Content-Type' => 'text/xml'])->getBodyString(); } Logger::info('posted to insanejournal: ' . $x ? $x : ''); } diff --git a/libertree/libertree.php b/libertree/libertree.php index c0f896c0c..f69c0aabb 100644 --- a/libertree/libertree.php +++ b/libertree/libertree.php @@ -201,7 +201,7 @@ function libertree_send(array &$b) // 'token' => $ltree_api_token ]; - $result = DI::httpClient()->post($ltree_blog, $params)->getBody(); + $result = DI::httpClient()->post($ltree_blog, $params)->getBodyString(); Logger::notice('libertree: ' . $result); } } diff --git a/ljpost/ljpost.php b/ljpost/ljpost.php index f6f2b79aa..fac447677 100644 --- a/ljpost/ljpost.php +++ b/ljpost/ljpost.php @@ -207,7 +207,7 @@ EOT; Logger::debug('ljpost: data: ' . $xml); if ($lj_blog !== 'test') { - $x = DI::httpClient()->post($lj_blog, $xml, ['Content-Type' => 'text/xml'])->getBody(); + $x = DI::httpClient()->post($lj_blog, $xml, ['Content-Type' => 'text/xml'])->getBodyString(); } Logger::info('posted to livejournal: ' . ($x) ? $x : ''); diff --git a/mailstream/mailstream.php b/mailstream/mailstream.php index d76ccf86e..968ee4c02 100644 --- a/mailstream/mailstream.php +++ b/mailstream/mailstream.php @@ -221,7 +221,7 @@ function mailstream_do_images(array &$item, array &$attachments) continue; } $attachments[$url] = [ - 'data' => $curlResult->getBody(), + 'data' => $curlResult->getBodyString(), 'guid' => hash('crc32', $url), 'filename' => basename($components['path']), 'type' => $curlResult->getContentType() diff --git a/mastodoncustomemojis/mastodoncustomemojis.php b/mastodoncustomemojis/mastodoncustomemojis.php index c84f1a4f3..f67054a1c 100644 --- a/mastodoncustomemojis/mastodoncustomemojis.php +++ b/mastodoncustomemojis/mastodoncustomemojis.php @@ -82,7 +82,7 @@ function mastodoncustomemojis_fetch_custom_emojis_for_url($api_base_url) $fetchResult = DI::httpClient()->fetchFull($api_url); if ($fetchResult->isSuccess()) { - $emojis_array = json_decode($fetchResult->getBody(), true); + $emojis_array = json_decode($fetchResult->getBodyString(), true); if (is_array($emojis_array) && count($emojis_array)) { foreach ($emojis_array as $emoji) { diff --git a/openstreetmap/openstreetmap.php b/openstreetmap/openstreetmap.php index 3b7c4a586..ae22aff04 100644 --- a/openstreetmap/openstreetmap.php +++ b/openstreetmap/openstreetmap.php @@ -121,7 +121,7 @@ function openstreetmap_get_coordinates(array &$b) if (is_null($j)) { $curlResult = DI::httpClient()->get($nomserver . $args); if ($curlResult->isSuccess()) { - $j = json_decode($curlResult->getBody(), true); + $j = json_decode($curlResult->getBodyString(), true); DI::cache()->set($cachekey, $j, Duration::MONTH); } } diff --git a/tumblr/tumblr.php b/tumblr/tumblr.php index 4d5368b80..d6508ff87 100644 --- a/tumblr/tumblr.php +++ b/tumblr/tumblr.php @@ -1244,7 +1244,7 @@ function tumblr_get_contact_by_url(string $url, int $uid): ?array } catch (\Exception $e) { return null; } - $html = $curlResult->getBody(); + $html = $curlResult->getBodyString(); if (empty($html)) { return null; } @@ -1372,7 +1372,7 @@ function tumblr_delete(int $uid, string $url, array $parameters): stdClass */ function tumblr_format_result(ICanHandleHttpResponses $curlResult): stdClass { - $result = json_decode($curlResult->getBody()); + $result = json_decode($curlResult->getBodyString()); if (empty($result) || empty($result->meta)) { $result = new stdClass; $result->meta = new stdClass; @@ -1426,11 +1426,11 @@ function tumblr_get_token(int $uid, string $code = ''): string $curlResult = DI::httpClient()->post('https://api.tumblr.com/v2/oauth2/token', $parameters); if (!$curlResult->isSuccess()) { - Logger::info('Error fetching token', ['uid' => $uid, 'code' => $code, 'result' => $curlResult->getBody(), 'parameters' => $parameters]); + Logger::info('Error fetching token', ['uid' => $uid, 'code' => $code, 'result' => $curlResult->getBodyString(), 'parameters' => $parameters]); return ''; } - $result = json_decode($curlResult->getBody()); + $result = json_decode($curlResult->getBodyString()); if (empty($result)) { Logger::info('Invalid result when updating token', ['uid' => $uid]); return ''; @@ -1479,7 +1479,7 @@ function tumblr_exchange_token(int $uid): stdClass ]); $response = $client->post('oauth2/exchange', ['auth' => 'oauth']); - return json_decode($response->getBody()->getContents()); + return json_decode($response->getBodyString()->getContents()); } catch (RequestException $exception) { Logger::notice('Exchange failed', ['code' => $exception->getCode(), 'message' => $exception->getMessage()]); return new stdClass; diff --git a/twitter/twitter.php b/twitter/twitter.php index b01345b74..8c906daf7 100644 --- a/twitter/twitter.php +++ b/twitter/twitter.php @@ -362,7 +362,7 @@ function twitter_post(int $uid, string $url, string $type, array $data): stdClas ]); $response = $client->post($url, ['auth' => 'oauth', $type => $data]); - $body = $response->getBody()->getContents(); + $body = $response->getBodyString()->getContents(); $status = [ 'code' => $response->getStatusCode(), @@ -399,7 +399,7 @@ function twitter_test_connection(int $uid) $status = [ 'code' => $response->getStatusCode(), 'reason' => $response->getReasonPhrase(), - 'content' => $response->getBody()->getContents() + 'content' => $response->getBodyString()->getContents() ]; DI::pConfig()->set(1, 'twitter', 'last_status', $status); Logger::info('Test successful', ['uid' => $uid]); diff --git a/webdav_storage/src/WebDav.php b/webdav_storage/src/WebDav.php index de9fc4769..ddf2dae0a 100644 --- a/webdav_storage/src/WebDav.php +++ b/webdav_storage/src/WebDav.php @@ -113,7 +113,7 @@ class WebDav implements ICanWriteToStorage $response = $this->client->request('propfind', $uri, $opts); $responseDoc = new \DOMDocument(); - $responseDoc->loadXML($response->getBody()); + $responseDoc->loadXML($response->getBodyString()); $responseDoc->formatOutput = true; $xpath = new \DOMXPath($responseDoc); @@ -205,7 +205,7 @@ class WebDav implements ICanWriteToStorage throw new ReferenceStorageException(sprintf('Invalid reference %s', $reference)); } - return $response->getBody(); + return $response->getBodyString(); } /** diff --git a/wppost/wppost.php b/wppost/wppost.php index 0405f78ad..e27079aa3 100644 --- a/wppost/wppost.php +++ b/wppost/wppost.php @@ -269,7 +269,7 @@ EOT; Logger::debug('wppost: data: ' . $xml); if ($wp_blog !== 'test') { - $x = DI::httpClient()->post($wp_blog, $xml)->getBody(); + $x = DI::httpClient()->post($wp_blog, $xml)->getBodyString(); } Logger::info('posted to wordpress: ' . (($x) ? $x : '')); } From 4dd903b473e914b1f8814220dff50fe1f2baf480 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 14 Jan 2024 19:21:08 +0000 Subject: [PATCH 098/388] New addon "tesseract" for OCR --- tesseract/composer.json | 5 + tesseract/composer.lock | 66 +++ tesseract/tesseract.php | 33 ++ tesseract/vendor/autoload.php | 7 + tesseract/vendor/composer/ClassLoader.php | 445 +++++++++++++++ tesseract/vendor/composer/LICENSE | 21 + .../vendor/composer/autoload_classmap.php | 9 + .../vendor/composer/autoload_namespaces.php | 9 + tesseract/vendor/composer/autoload_psr4.php | 10 + tesseract/vendor/composer/autoload_real.php | 55 ++ tesseract/vendor/composer/autoload_static.php | 31 ++ tesseract/vendor/composer/installed.json | 48 ++ .../thiagoalessio/tesseract_ocr/.appveyor.yml | 14 + .../thiagoalessio/tesseract_ocr/MIT-LICENSE | 19 + .../thiagoalessio/tesseract_ocr/README.md | 508 ++++++++++++++++++ .../thiagoalessio/tesseract_ocr/codecov.yml | 4 + .../thiagoalessio/tesseract_ocr/composer.json | 35 ++ .../tesseract_ocr/src/Command.php | 80 +++ .../src/FeatureNotAvailableException.php | 7 + .../tesseract_ocr/src/FriendlyErrors.php | 120 +++++ .../src/ImageNotFoundException.php | 7 + .../src/NoWritePermissionsForOutputFile.php | 7 + .../tesseract_ocr/src/Option.php | 79 +++ .../tesseract_ocr/src/Process.php | 83 +++ .../src/TesseractNotFoundException.php | 7 + .../tesseract_ocr/src/TesseractOCR.php | 181 +++++++ .../src/TesseractOcrException.php | 7 + .../src/UnsuccessfulCommandException.php | 7 + 28 files changed, 1904 insertions(+) create mode 100644 tesseract/composer.json create mode 100644 tesseract/composer.lock create mode 100644 tesseract/tesseract.php create mode 100644 tesseract/vendor/autoload.php create mode 100644 tesseract/vendor/composer/ClassLoader.php create mode 100644 tesseract/vendor/composer/LICENSE create mode 100644 tesseract/vendor/composer/autoload_classmap.php create mode 100644 tesseract/vendor/composer/autoload_namespaces.php create mode 100644 tesseract/vendor/composer/autoload_psr4.php create mode 100644 tesseract/vendor/composer/autoload_real.php create mode 100644 tesseract/vendor/composer/autoload_static.php create mode 100644 tesseract/vendor/composer/installed.json create mode 100644 tesseract/vendor/thiagoalessio/tesseract_ocr/.appveyor.yml create mode 100644 tesseract/vendor/thiagoalessio/tesseract_ocr/MIT-LICENSE create mode 100644 tesseract/vendor/thiagoalessio/tesseract_ocr/README.md create mode 100644 tesseract/vendor/thiagoalessio/tesseract_ocr/codecov.yml create mode 100644 tesseract/vendor/thiagoalessio/tesseract_ocr/composer.json create mode 100644 tesseract/vendor/thiagoalessio/tesseract_ocr/src/Command.php create mode 100644 tesseract/vendor/thiagoalessio/tesseract_ocr/src/FeatureNotAvailableException.php create mode 100644 tesseract/vendor/thiagoalessio/tesseract_ocr/src/FriendlyErrors.php create mode 100644 tesseract/vendor/thiagoalessio/tesseract_ocr/src/ImageNotFoundException.php create mode 100644 tesseract/vendor/thiagoalessio/tesseract_ocr/src/NoWritePermissionsForOutputFile.php create mode 100644 tesseract/vendor/thiagoalessio/tesseract_ocr/src/Option.php create mode 100644 tesseract/vendor/thiagoalessio/tesseract_ocr/src/Process.php create mode 100644 tesseract/vendor/thiagoalessio/tesseract_ocr/src/TesseractNotFoundException.php create mode 100644 tesseract/vendor/thiagoalessio/tesseract_ocr/src/TesseractOCR.php create mode 100644 tesseract/vendor/thiagoalessio/tesseract_ocr/src/TesseractOcrException.php create mode 100644 tesseract/vendor/thiagoalessio/tesseract_ocr/src/UnsuccessfulCommandException.php diff --git a/tesseract/composer.json b/tesseract/composer.json new file mode 100644 index 000000000..2a0937c03 --- /dev/null +++ b/tesseract/composer.json @@ -0,0 +1,5 @@ +{ + "require": { + "thiagoalessio/tesseract_ocr": "^2.13" + } +} diff --git a/tesseract/composer.lock b/tesseract/composer.lock new file mode 100644 index 000000000..036868e70 --- /dev/null +++ b/tesseract/composer.lock @@ -0,0 +1,66 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "778b5479cb5d2b31b57f40473a87f8eb", + "packages": [ + { + "name": "thiagoalessio/tesseract_ocr", + "version": "2.13.0", + "source": { + "type": "git", + "url": "https://github.com/thiagoalessio/tesseract-ocr-for-php.git", + "reference": "232a8cb9d571992f9bd1e263f2f6909cf6c173a1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thiagoalessio/tesseract-ocr-for-php/zipball/232a8cb9d571992f9bd1e263f2f6909cf6c173a1", + "reference": "232a8cb9d571992f9bd1e263f2f6909cf6c173a1", + "shasum": "" + }, + "require": { + "php": "^5.3 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpunit/php-code-coverage": "^2.2.4 || ^9.0.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "thiagoalessio\\TesseractOCR\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "thiagoalessio", + "email": "thiagoalessio@me.com" + } + ], + "description": "A wrapper to work with Tesseract OCR inside PHP.", + "keywords": [ + "OCR", + "Tesseract", + "text recognition" + ], + "time": "2023-10-05T21:14:48+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [], + "platform-overrides": { + "php": "7.2" + }, + "plugin-api-version": "1.1.0" +} diff --git a/tesseract/tesseract.php b/tesseract/tesseract.php new file mode 100644 index 000000000..3c61273f2 --- /dev/null +++ b/tesseract/tesseract.php @@ -0,0 +1,33 @@ + + */ + +use Friendica\Core\Hook; +use Friendica\Core\Logger; +use Friendica\Core\System; +use thiagoalessio\TesseractOCR\TesseractOCR; + +require_once __DIR__ . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php'; + +function tesseract_install() +{ + Hook::register('ocr-detection', __FILE__, 'tesseract_ocr_detection'); + + Logger::notice('installed tesseract'); +} + +function tesseract_ocr_detection(&$media) +{ + $ocr = new TesseractOCR(); + try { + $ocr->tempDir(System::getTempPath()); + $ocr->imageData($media['img_str'], strlen($media['img_str'])); + $media['description'] = $ocr->run(); + } catch (\Throwable $th) { + Logger::info('Error calling TesseractOCR', ['message' => $th->getMessage()]); + } +} diff --git a/tesseract/vendor/autoload.php b/tesseract/vendor/autoload.php new file mode 100644 index 000000000..1238ecead --- /dev/null +++ b/tesseract/vendor/autoload.php @@ -0,0 +1,7 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Autoload; + +/** + * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. + * + * $loader = new \Composer\Autoload\ClassLoader(); + * + * // register classes with namespaces + * $loader->add('Symfony\Component', __DIR__.'/component'); + * $loader->add('Symfony', __DIR__.'/framework'); + * + * // activate the autoloader + * $loader->register(); + * + * // to enable searching the include path (eg. for PEAR packages) + * $loader->setUseIncludePath(true); + * + * In this example, if you try to use a class in the Symfony\Component + * namespace or one of its children (Symfony\Component\Console for instance), + * the autoloader will first look for the class under the component/ + * directory, and it will then fallback to the framework/ directory if not + * found before giving up. + * + * This class is loosely based on the Symfony UniversalClassLoader. + * + * @author Fabien Potencier + * @author Jordi Boggiano + * @see http://www.php-fig.org/psr/psr-0/ + * @see http://www.php-fig.org/psr/psr-4/ + */ +class ClassLoader +{ + // PSR-4 + private $prefixLengthsPsr4 = array(); + private $prefixDirsPsr4 = array(); + private $fallbackDirsPsr4 = array(); + + // PSR-0 + private $prefixesPsr0 = array(); + private $fallbackDirsPsr0 = array(); + + private $useIncludePath = false; + private $classMap = array(); + private $classMapAuthoritative = false; + private $missingClasses = array(); + private $apcuPrefix; + + public function getPrefixes() + { + if (!empty($this->prefixesPsr0)) { + return call_user_func_array('array_merge', array_values($this->prefixesPsr0)); + } + + return array(); + } + + public function getPrefixesPsr4() + { + return $this->prefixDirsPsr4; + } + + public function getFallbackDirs() + { + return $this->fallbackDirsPsr0; + } + + public function getFallbackDirsPsr4() + { + return $this->fallbackDirsPsr4; + } + + public function getClassMap() + { + return $this->classMap; + } + + /** + * @param array $classMap Class to filename map + */ + public function addClassMap(array $classMap) + { + if ($this->classMap) { + $this->classMap = array_merge($this->classMap, $classMap); + } else { + $this->classMap = $classMap; + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, either + * appending or prepending to the ones previously set for this prefix. + * + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories + */ + public function add($prefix, $paths, $prepend = false) + { + if (!$prefix) { + if ($prepend) { + $this->fallbackDirsPsr0 = array_merge( + (array) $paths, + $this->fallbackDirsPsr0 + ); + } else { + $this->fallbackDirsPsr0 = array_merge( + $this->fallbackDirsPsr0, + (array) $paths + ); + } + + return; + } + + $first = $prefix[0]; + if (!isset($this->prefixesPsr0[$first][$prefix])) { + $this->prefixesPsr0[$first][$prefix] = (array) $paths; + + return; + } + if ($prepend) { + $this->prefixesPsr0[$first][$prefix] = array_merge( + (array) $paths, + $this->prefixesPsr0[$first][$prefix] + ); + } else { + $this->prefixesPsr0[$first][$prefix] = array_merge( + $this->prefixesPsr0[$first][$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, either + * appending or prepending to the ones previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-4 base directories + * @param bool $prepend Whether to prepend the directories + * + * @throws \InvalidArgumentException + */ + public function addPsr4($prefix, $paths, $prepend = false) + { + if (!$prefix) { + // Register directories for the root namespace. + if ($prepend) { + $this->fallbackDirsPsr4 = array_merge( + (array) $paths, + $this->fallbackDirsPsr4 + ); + } else { + $this->fallbackDirsPsr4 = array_merge( + $this->fallbackDirsPsr4, + (array) $paths + ); + } + } elseif (!isset($this->prefixDirsPsr4[$prefix])) { + // Register directories for a new namespace. + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } elseif ($prepend) { + // Prepend directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + (array) $paths, + $this->prefixDirsPsr4[$prefix] + ); + } else { + // Append directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + $this->prefixDirsPsr4[$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, + * replacing any others previously set for this prefix. + * + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 base directories + */ + public function set($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr0 = (array) $paths; + } else { + $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, + * replacing any others previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-4 base directories + * + * @throws \InvalidArgumentException + */ + public function setPsr4($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr4 = (array) $paths; + } else { + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } + } + + /** + * Turns on searching the include path for class files. + * + * @param bool $useIncludePath + */ + public function setUseIncludePath($useIncludePath) + { + $this->useIncludePath = $useIncludePath; + } + + /** + * Can be used to check if the autoloader uses the include path to check + * for classes. + * + * @return bool + */ + public function getUseIncludePath() + { + return $this->useIncludePath; + } + + /** + * Turns off searching the prefix and fallback directories for classes + * that have not been registered with the class map. + * + * @param bool $classMapAuthoritative + */ + public function setClassMapAuthoritative($classMapAuthoritative) + { + $this->classMapAuthoritative = $classMapAuthoritative; + } + + /** + * Should class lookup fail if not found in the current class map? + * + * @return bool + */ + public function isClassMapAuthoritative() + { + return $this->classMapAuthoritative; + } + + /** + * APCu prefix to use to cache found/not-found classes, if the extension is enabled. + * + * @param string|null $apcuPrefix + */ + public function setApcuPrefix($apcuPrefix) + { + $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null; + } + + /** + * The APCu prefix in use, or null if APCu caching is not enabled. + * + * @return string|null + */ + public function getApcuPrefix() + { + return $this->apcuPrefix; + } + + /** + * Registers this instance as an autoloader. + * + * @param bool $prepend Whether to prepend the autoloader or not + */ + public function register($prepend = false) + { + spl_autoload_register(array($this, 'loadClass'), true, $prepend); + } + + /** + * Unregisters this instance as an autoloader. + */ + public function unregister() + { + spl_autoload_unregister(array($this, 'loadClass')); + } + + /** + * Loads the given class or interface. + * + * @param string $class The name of the class + * @return bool|null True if loaded, null otherwise + */ + public function loadClass($class) + { + if ($file = $this->findFile($class)) { + includeFile($file); + + return true; + } + } + + /** + * Finds the path to the file where the class is defined. + * + * @param string $class The name of the class + * + * @return string|false The path if found, false otherwise + */ + public function findFile($class) + { + // class map lookup + if (isset($this->classMap[$class])) { + return $this->classMap[$class]; + } + if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) { + return false; + } + if (null !== $this->apcuPrefix) { + $file = apcu_fetch($this->apcuPrefix.$class, $hit); + if ($hit) { + return $file; + } + } + + $file = $this->findFileWithExtension($class, '.php'); + + // Search for Hack files if we are running on HHVM + if (false === $file && defined('HHVM_VERSION')) { + $file = $this->findFileWithExtension($class, '.hh'); + } + + if (null !== $this->apcuPrefix) { + apcu_add($this->apcuPrefix.$class, $file); + } + + if (false === $file) { + // Remember that this class does not exist. + $this->missingClasses[$class] = true; + } + + return $file; + } + + private function findFileWithExtension($class, $ext) + { + // PSR-4 lookup + $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; + + $first = $class[0]; + if (isset($this->prefixLengthsPsr4[$first])) { + $subPath = $class; + while (false !== $lastPos = strrpos($subPath, '\\')) { + $subPath = substr($subPath, 0, $lastPos); + $search = $subPath . '\\'; + if (isset($this->prefixDirsPsr4[$search])) { + $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); + foreach ($this->prefixDirsPsr4[$search] as $dir) { + if (file_exists($file = $dir . $pathEnd)) { + return $file; + } + } + } + } + } + + // PSR-4 fallback dirs + foreach ($this->fallbackDirsPsr4 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { + return $file; + } + } + + // PSR-0 lookup + if (false !== $pos = strrpos($class, '\\')) { + // namespaced class name + $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) + . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); + } else { + // PEAR-like class name + $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; + } + + if (isset($this->prefixesPsr0[$first])) { + foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { + if (0 === strpos($class, $prefix)) { + foreach ($dirs as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + } + } + } + + // PSR-0 fallback dirs + foreach ($this->fallbackDirsPsr0 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + + // PSR-0 include paths. + if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { + return $file; + } + + return false; + } +} + +/** + * Scope isolated include. + * + * Prevents access to $this/self from included files. + */ +function includeFile($file) +{ + include $file; +} diff --git a/tesseract/vendor/composer/LICENSE b/tesseract/vendor/composer/LICENSE new file mode 100644 index 000000000..f27399a04 --- /dev/null +++ b/tesseract/vendor/composer/LICENSE @@ -0,0 +1,21 @@ + +Copyright (c) Nils Adermann, Jordi Boggiano + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + diff --git a/tesseract/vendor/composer/autoload_classmap.php b/tesseract/vendor/composer/autoload_classmap.php new file mode 100644 index 000000000..7a91153b0 --- /dev/null +++ b/tesseract/vendor/composer/autoload_classmap.php @@ -0,0 +1,9 @@ + array($vendorDir . '/thiagoalessio/tesseract_ocr/src'), +); diff --git a/tesseract/vendor/composer/autoload_real.php b/tesseract/vendor/composer/autoload_real.php new file mode 100644 index 000000000..10af9c56b --- /dev/null +++ b/tesseract/vendor/composer/autoload_real.php @@ -0,0 +1,55 @@ += 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); + if ($useStaticLoader) { + require_once __DIR__ . '/autoload_static.php'; + + call_user_func(\Composer\Autoload\ComposerStaticInit695d781792f754383aa61632167d066e::getInitializer($loader)); + } else { + $map = require __DIR__ . '/autoload_namespaces.php'; + foreach ($map as $namespace => $path) { + $loader->set($namespace, $path); + } + + $map = require __DIR__ . '/autoload_psr4.php'; + foreach ($map as $namespace => $path) { + $loader->setPsr4($namespace, $path); + } + + $classMap = require __DIR__ . '/autoload_classmap.php'; + if ($classMap) { + $loader->addClassMap($classMap); + } + } + + $loader->register(true); + + return $loader; + } +} diff --git a/tesseract/vendor/composer/autoload_static.php b/tesseract/vendor/composer/autoload_static.php new file mode 100644 index 000000000..59b660535 --- /dev/null +++ b/tesseract/vendor/composer/autoload_static.php @@ -0,0 +1,31 @@ + + array ( + 'thiagoalessio\\TesseractOCR\\' => 27, + ), + ); + + public static $prefixDirsPsr4 = array ( + 'thiagoalessio\\TesseractOCR\\' => + array ( + 0 => __DIR__ . '/..' . '/thiagoalessio/tesseract_ocr/src', + ), + ); + + public static function getInitializer(ClassLoader $loader) + { + return \Closure::bind(function () use ($loader) { + $loader->prefixLengthsPsr4 = ComposerStaticInit695d781792f754383aa61632167d066e::$prefixLengthsPsr4; + $loader->prefixDirsPsr4 = ComposerStaticInit695d781792f754383aa61632167d066e::$prefixDirsPsr4; + + }, null, ClassLoader::class); + } +} diff --git a/tesseract/vendor/composer/installed.json b/tesseract/vendor/composer/installed.json new file mode 100644 index 000000000..70bcc01ce --- /dev/null +++ b/tesseract/vendor/composer/installed.json @@ -0,0 +1,48 @@ +[ + { + "name": "thiagoalessio/tesseract_ocr", + "version": "2.13.0", + "version_normalized": "2.13.0.0", + "source": { + "type": "git", + "url": "https://github.com/thiagoalessio/tesseract-ocr-for-php.git", + "reference": "232a8cb9d571992f9bd1e263f2f6909cf6c173a1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thiagoalessio/tesseract-ocr-for-php/zipball/232a8cb9d571992f9bd1e263f2f6909cf6c173a1", + "reference": "232a8cb9d571992f9bd1e263f2f6909cf6c173a1", + "shasum": "" + }, + "require": { + "php": "^5.3 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpunit/php-code-coverage": "^2.2.4 || ^9.0.0" + }, + "time": "2023-10-05T21:14:48+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "thiagoalessio\\TesseractOCR\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "thiagoalessio", + "email": "thiagoalessio@me.com" + } + ], + "description": "A wrapper to work with Tesseract OCR inside PHP.", + "keywords": [ + "OCR", + "Tesseract", + "text recognition" + ] + } +] diff --git a/tesseract/vendor/thiagoalessio/tesseract_ocr/.appveyor.yml b/tesseract/vendor/thiagoalessio/tesseract_ocr/.appveyor.yml new file mode 100644 index 000000000..1debc1a12 --- /dev/null +++ b/tesseract/vendor/thiagoalessio/tesseract_ocr/.appveyor.yml @@ -0,0 +1,14 @@ +--- +build: false + +install: + - ps: Set-Service wuauserv -StartupType Manual + - choco install php + - choco install capture2text --version 3.9 + - choco install composer + - refreshenv + - cd %APPVEYOR_BUILD_FOLDER% + - composer install + +test_script: + - php tests\run.php unit e2e diff --git a/tesseract/vendor/thiagoalessio/tesseract_ocr/MIT-LICENSE b/tesseract/vendor/thiagoalessio/tesseract_ocr/MIT-LICENSE new file mode 100644 index 000000000..448104d6b --- /dev/null +++ b/tesseract/vendor/thiagoalessio/tesseract_ocr/MIT-LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2012-2021 Thiago Alessio Pereira + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/tesseract/vendor/thiagoalessio/tesseract_ocr/README.md b/tesseract/vendor/thiagoalessio/tesseract_ocr/README.md new file mode 100644 index 000000000..b828344c7 --- /dev/null +++ b/tesseract/vendor/thiagoalessio/tesseract_ocr/README.md @@ -0,0 +1,508 @@ +Tesseract OCR for PHP + +# Tesseract OCR for PHP + +A wrapper to work with Tesseract OCR inside PHP. + +[![CI][ci_badge]][ci] +[![AppVeyor][appveyor_badge]][appveyor] +[![Codacy][codacy_badge]][codacy] +[![Test Coverage][test_coverage_badge]][test_coverage] +
+[![Latest Stable Version][stable_version_badge]][packagist] +[![Total Downloads][total_downloads_badge]][packagist] +[![Monthly Downloads][monthly_downloads_badge]][packagist] + +## Installation + +Via [Composer][]: + + $ composer require thiagoalessio/tesseract_ocr + +:bangbang: **This library depends on [Tesseract OCR][], version _3.02_ or later.** + +
+ +### ![][windows_icon] Note for Windows users + +There are [many ways][tesseract_installation_on_windows] to install +[Tesseract OCR][] on your system, but if you just want something quick to +get up and running, I recommend installing the [Capture2Text][] package with +[Chocolatey][]. + + choco install capture2text --version 3.9 + +:warning: Recent versions of [Capture2Text][] stopped shipping the `tesseract` binary. + +
+ +### ![][macos_icon] Note for macOS users + +With [MacPorts][] you can install support for individual languages, like so: + + $ sudo port install tesseract- + +But that is not possible with [Homebrew][]. It comes only with **English** support +by default, so if you intend to use it for other language, the quickest solution +is to install them all: + + $ brew install tesseract tesseract-lang + +
+ +## Usage + +### Basic usage + + + +```php +use thiagoalessio\TesseractOCR\TesseractOCR; +echo (new TesseractOCR('text.png')) + ->run(); +``` + +``` +The quick brown fox +jumps over +the lazy dog. +``` + +
+ +### Other languages + + + +```php +use thiagoalessio\TesseractOCR\TesseractOCR; +echo (new TesseractOCR('german.png')) + ->lang('deu') + ->run(); +``` + +``` +Bülowstraße +``` + +
+ +### Multiple languages + + + +```php +use thiagoalessio\TesseractOCR\TesseractOCR; +echo (new TesseractOCR('mixed-languages.png')) + ->lang('eng', 'jpn', 'spa') + ->run(); +``` + +``` +I eat すし y Pollo +``` + +
+ +### Inducing recognition + + + +```php +use thiagoalessio\TesseractOCR\TesseractOCR; +echo (new TesseractOCR('8055.png')) + ->allowlist(range('A', 'Z')) + ->run(); +``` + +``` +BOSS +``` + +
+ +### Breaking CAPTCHAs + +Yes, I know some of you might want to use this library for the *noble* purpose +of breaking CAPTCHAs, so please take a look at this comment: + + + +## API + +### run + +Executes a `tesseract` command, optionally receiving an integer as `timeout`, +in case you experience stalled tesseract processes. + +```php +$ocr = new TesseractOCR(); +$ocr->run(); +``` +```php +$ocr = new TesseractOCR(); +$timeout = 500; +$ocr->run($timeout); +``` + +### image + +Define the path of an image to be recognized by `tesseract`. + +```php +$ocr = new TesseractOCR(); +$ocr->image('/path/to/image.png'); +$ocr->run(); +``` + +### imageData + +Set the image to be recognized by `tesseract` from a string, with its size. +This can be useful when dealing with files that are already loaded in memory. +You can easily retrieve the image data and size of an image object : +```php +//Using Imagick +$data = $img->getImageBlob(); +$size = $img->getImageLength(); +//Using GD +ob_start(); +// Note that you can use any format supported by tesseract +imagepng($img, null, 0); +$size = ob_get_length(); +$data = ob_get_clean(); + +$ocr = new TesseractOCR(); +$ocr->imageData($data, $size); +$ocr->run(); +``` + +### executable + +Define a custom location of the `tesseract` executable, +if by any reason it is not present in the `$PATH`. + +```php +echo (new TesseractOCR('img.png')) + ->executable('/path/to/tesseract') + ->run(); +``` + +### version + +Returns the current version of `tesseract`. + +```php +echo (new TesseractOCR())->version(); +``` + +### availableLanguages + +Returns a list of available languages/scripts. + +```php +foreach((new TesseractOCR())->availableLanguages() as $lang) echo $lang; +``` + +__More info:__ + +### tessdataDir + +Specify a custom location for the tessdata directory. + +```php +echo (new TesseractOCR('img.png')) + ->tessdataDir('/path') + ->run(); +``` + +### userWords + +Specify the location of user words file. + +This is a plain text file containing a list of words that you want to be +considered as a normal dictionary words by `tesseract`. + +Useful when dealing with contents that contain technical terminology, jargon, +etc. + +``` +$ cat /path/to/user-words.txt +foo +bar +``` + +```php +echo (new TesseractOCR('img.png')) + ->userWords('/path/to/user-words.txt') + ->run(); +``` + +### userPatterns + +Specify the location of user patterns file. + +If the contents you are dealing with have known patterns, this option can help +a lot tesseract's recognition accuracy. + +``` +$ cat /path/to/user-patterns.txt' +1-\d\d\d-GOOG-441 +www.\n\\\*.com +``` + +```php +echo (new TesseractOCR('img.png')) + ->userPatterns('/path/to/user-patterns.txt') + ->run(); +``` + +### lang + +Define one or more languages to be used during the recognition. +A complete list of available languages can be found at: + + +__Tip from [@daijiale][]:__ Use the combination `->lang('chi_sim', 'chi_tra')` +for proper recognition of Chinese. + +```php + echo (new TesseractOCR('img.png')) + ->lang('lang1', 'lang2', 'lang3') + ->run(); +``` + +### psm + +Specify the Page Segmentation Method, which instructs `tesseract` how to +interpret the given image. + +__More info:__ + +```php +echo (new TesseractOCR('img.png')) + ->psm(6) + ->run(); +``` + +### oem + +Specify the OCR Engine Mode. (see `tesseract --help-oem`) + +```php +echo (new TesseractOCR('img.png')) + ->oem(2) + ->run(); +``` + +### dpi + +Specify the image DPI. It is useful if your image does not contain this information in its metadata. + +```php +echo (new TesseractOCR('img.png')) + ->dpi(300) + ->run(); +``` + +### allowlist + +This is a shortcut for `->config('tessedit_char_whitelist', 'abcdef....')`. + +```php +echo (new TesseractOCR('img.png')) + ->allowlist(range('a', 'z'), range(0, 9), '-_@') + ->run(); +``` + +### configFile + +Specify a config file to be used. It can either be the path to your own +config file or the name of one of the predefined config files: + + +```php +echo (new TesseractOCR('img.png')) + ->configFile('hocr') + ->run(); +``` + +### setOutputFile + +Specify an Outputfile to be used. Be aware: If you set an outputfile then +the option `withoutTempFiles` is ignored. +Tempfiles are written (and deleted) even if `withoutTempFiles = true`. + +In combination with `configFile` you are able to get the `hocr`, `tsv` or +`pdf` files. + +```php +echo (new TesseractOCR('img.png')) + ->configFile('pdf') + ->setOutputFile('/PATH_TO_MY_OUTPUTFILE/searchable.pdf') + ->run(); +``` + +### digits + +Shortcut for `->configFile('digits')`. + +```php +echo (new TesseractOCR('img.png')) + ->digits() + ->run(); +``` + +### hocr + +Shortcut for `->configFile('hocr')`. + +```php +echo (new TesseractOCR('img.png')) + ->hocr() + ->run(); +``` + +### pdf + +Shortcut for `->configFile('pdf')`. + +```php +echo (new TesseractOCR('img.png')) + ->pdf() + ->run(); +``` + +### quiet + +Shortcut for `->configFile('quiet')`. + +```php +echo (new TesseractOCR('img.png')) + ->quiet() + ->run(); +``` + +### tsv + +Shortcut for `->configFile('tsv')`. + +```php +echo (new TesseractOCR('img.png')) + ->tsv() + ->run(); +``` + +### txt + +Shortcut for `->configFile('txt')`. + +```php +echo (new TesseractOCR('img.png')) + ->txt() + ->run(); +``` + +### tempDir + +Define a custom directory to store temporary files generated by tesseract. +Make sure the directory actually exists and the user running `php` is allowed +to write in there. + +```php +echo (new TesseractOCR('img.png')) + ->tempDir('./my/custom/temp/dir') + ->run(); +``` + +### withoutTempFiles + +Specify that `tesseract` should output the recognized text without writing to temporary files. +The data is gathered from the standard output of `tesseract` instead. + +```php +echo (new TesseractOCR('img.png')) + ->withoutTempFiles() + ->run(); +``` + +### Other options + +Any configuration option offered by Tesseract can be used like that: + +```php +echo (new TesseractOCR('img.png')) + ->config('config_var', 'value') + ->config('other_config_var', 'other value') + ->run(); +``` + +Or like that: + +```php +echo (new TesseractOCR('img.png')) + ->configVar('value') + ->otherConfigVar('other value') + ->run(); +``` + +__More info:__ + +### Thread-limit + +Sometimes, it may be useful to limit the number of threads that tesseract is +allowed to use (e.g. in [this case](https://github.com/tesseract-ocr/tesseract/issues/898)). +Set the maxmium number of threads as param for the `run` function: + +```php +echo (new TesseractOCR('img.png')) + ->threadLimit(1) + ->run(); +``` + +## How to contribute + +You can contribute to this project by: + +* Opening an [Issue][] if you found a bug or wish to propose a new feature; +* Placing a [Pull Request][] with code that fix a bug, missing/wrong documentation + or implement a new feature; + +Just make sure you take a look at our [Code of Conduct][] and [Contributing][] +instructions. + +## License + +tesseract-ocr-for-php is released under the [MIT License][]. + + +

Made with love in Berlin

+ +[ci_badge]: https://github.com/thiagoalessio/tesseract-ocr-for-php/workflows/CI/badge.svg?event=push&branch=main +[ci]: https://github.com/thiagoalessio/tesseract-ocr-for-php/actions?query=workflow%3ACI +[appveyor_badge]: https://ci.appveyor.com/api/projects/status/xwy5ls0798iwcim3/branch/main?svg=true +[appveyor]: https://ci.appveyor.com/project/thiagoalessio/tesseract-ocr-for-php/branch/main +[codacy_badge]: https://app.codacy.com/project/badge/Grade/a81aa10012874f23a57df5b492d835f2 +[codacy]: https://www.codacy.com/gh/thiagoalessio/tesseract-ocr-for-php/dashboard +[test_coverage_badge]: https://codecov.io/gh/thiagoalessio/tesseract-ocr-for-php/branch/main/graph/badge.svg?token=Y0VnrqiSIf +[test_coverage]: https://codecov.io/gh/thiagoalessio/tesseract-ocr-for-php +[stable_version_badge]: https://img.shields.io/packagist/v/thiagoalessio/tesseract_ocr.svg +[packagist]: https://packagist.org/packages/thiagoalessio/tesseract_ocr +[total_downloads_badge]: https://img.shields.io/packagist/dt/thiagoalessio/tesseract_ocr.svg +[monthly_downloads_badge]: https://img.shields.io/packagist/dm/thiagoalessio/tesseract_ocr.svg +[Tesseract OCR]: https://github.com/tesseract-ocr/tesseract +[Composer]: http://getcomposer.org/ +[windows_icon]: https://thiagoalessio.github.io/tesseract-ocr-for-php/images/windows-18.svg +[macos_icon]: https://thiagoalessio.github.io/tesseract-ocr-for-php/images/apple-18.svg +[tesseract_installation_on_windows]: https://github.com/tesseract-ocr/tesseract/wiki#windows +[Capture2Text]: https://chocolatey.org/packages/capture2text +[Chocolatey]: https://chocolatey.org +[MacPorts]: https://www.macports.org +[Homebrew]: https://brew.sh +[@daijiale]: https://github.com/daijiale +[HOCR]: https://github.com/tesseract-ocr/tesseract/wiki/Command-Line-Usage#hocr-output +[TSV]: https://github.com/tesseract-ocr/tesseract/wiki/Command-Line-Usage#tsv-output-currently-available-in-305-dev-in-master-branch-on-github +[Issue]: https://github.com/thiagoalessio/tesseract-ocr-for-php/issues +[Pull Request]: https://github.com/thiagoalessio/tesseract-ocr-for-php/pulls +[Code of Conduct]: https://github.com/thiagoalessio/tesseract-ocr-for-php/blob/main/.github/CODE_OF_CONDUCT.md +[Contributing]: https://github.com/thiagoalessio/tesseract-ocr-for-php/blob/main/.github/CONTRIBUTING.md +[MIT License]: https://github.com/thiagoalessio/tesseract-ocr-for-php/blob/main/MIT-LICENSE diff --git a/tesseract/vendor/thiagoalessio/tesseract_ocr/codecov.yml b/tesseract/vendor/thiagoalessio/tesseract_ocr/codecov.yml new file mode 100644 index 000000000..8fd4c9219 --- /dev/null +++ b/tesseract/vendor/thiagoalessio/tesseract_ocr/codecov.yml @@ -0,0 +1,4 @@ +fixes: +- "/home/runner/work/tesseract-ocr-for-php/tesseract-ocr-for-php/::" +- "/Users/runner/work/tesseract-ocr-for-php/tesseract-ocr-for-php/::" +- "C:\\projects\\tesseract-ocr-for-php\\::" diff --git a/tesseract/vendor/thiagoalessio/tesseract_ocr/composer.json b/tesseract/vendor/thiagoalessio/tesseract_ocr/composer.json new file mode 100644 index 000000000..9a07e6d57 --- /dev/null +++ b/tesseract/vendor/thiagoalessio/tesseract_ocr/composer.json @@ -0,0 +1,35 @@ +{ + "name": "thiagoalessio/tesseract_ocr", + "description": "A wrapper to work with Tesseract OCR inside PHP.", + "version": "2.13.0", + "type": "library", + "keywords": ["Tesseract", "OCR", "text recognition"], + "license": "MIT", + "authors": [ + { + "name": "thiagoalessio", + "email": "thiagoalessio@me.com" + } + ], + "support": { + "issues": "https://github.com/thiagoalessio/tesseract-ocr-for-php/issues", + "irc": "irc://irc.freenode.net/tesseract-ocr-for-php", + "source": "https://github.com/thiagoalessio/tesseract-ocr-for-php" + }, + "require": { + "php": "^5.3 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpunit/php-code-coverage": "^2.2.4 || ^9.0.0" + }, + "autoload": { + "psr-4": { + "thiagoalessio\\TesseractOCR\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "thiagoalessio\\TesseractOCR\\Tests\\": "tests/" + } + } +} diff --git a/tesseract/vendor/thiagoalessio/tesseract_ocr/src/Command.php b/tesseract/vendor/thiagoalessio/tesseract_ocr/src/Command.php new file mode 100644 index 000000000..ad123e82b --- /dev/null +++ b/tesseract/vendor/thiagoalessio/tesseract_ocr/src/Command.php @@ -0,0 +1,80 @@ +image = $image; + $this->outputFile = $outputFile; + } + + public function build() { return "$this"; } + + public function __toString() + { + $cmd = array(); + if ($this->threadLimit) $cmd[] = "OMP_THREAD_LIMIT={$this->threadLimit}"; + $cmd[] = self::escape($this->executable); + $cmd[] = $this->useFileAsInput ? self::escape($this->image) : "-"; + $cmd[] = $this->useFileAsOutput ? self::escape($this->getOutputFile(false)) : "-"; + + $version = $this->getTesseractVersion(); + + foreach ($this->options as $option) { + $cmd[] = is_callable($option) ? $option($version) : "$option"; + } + if ($this->configFile) $cmd[] = $this->configFile; + + return join(' ', $cmd); + } + + public function getOutputFile($withExt=true) + { + if (!$this->outputFile) + $this->outputFile = $this->getTempDir() + .DIRECTORY_SEPARATOR + .basename(tempnam($this->getTempDir(), 'ocr')); + if (!$withExt) return $this->outputFile; + + $hasCustomExt = array('hocr', 'tsv', 'pdf'); + $ext = in_array($this->configFile, $hasCustomExt) ? $this->configFile : 'txt'; + return "{$this->outputFile}.{$ext}"; + } + + public function getTempDir() + { + return $this->tempDir ?: sys_get_temp_dir(); + } + + public function getTesseractVersion() + { + exec(self::escape($this->executable).' --version 2>&1', $output); + $outputParts = explode(' ', $output[0]); + return $outputParts[1]; + } + + public function getAvailableLanguages() + { + exec(self::escape($this->executable) . ' --list-langs 2>&1', $output); + array_shift($output); + sort($output); + return $output; + } + + public static function escape($str) + { + $charlist = strtoupper(substr(PHP_OS, 0, 3)) == 'WIN' ? '$"`' : '$"\\`'; + return '"'.addcslashes($str, $charlist).'"'; + } +} diff --git a/tesseract/vendor/thiagoalessio/tesseract_ocr/src/FeatureNotAvailableException.php b/tesseract/vendor/thiagoalessio/tesseract_ocr/src/FeatureNotAvailableException.php new file mode 100644 index 000000000..12264f5c9 --- /dev/null +++ b/tesseract/vendor/thiagoalessio/tesseract_ocr/src/FeatureNotAvailableException.php @@ -0,0 +1,7 @@ + NUL 2>&1' + : 'type '.Command::escape($executable).' > /dev/null 2>&1'; + system($cmd, $exitCode); + + if ($exitCode == 0) return; + + $currentPath = getenv('PATH'); + $msg = array(); + $msg[] = "Error! The command \"$executable\" was not found."; + $msg[] = ''; + $msg[] = 'Make sure you have Tesseract OCR installed on your system:'; + $msg[] = 'https://github.com/tesseract-ocr/tesseract'; + $msg[] = ''; + $msg[] = "The current \$PATH is $currentPath"; + $msg = join(PHP_EOL, $msg); + + throw new TesseractNotFoundException($msg); + } + + public static function checkCommandExecution($command, $stdout, $stderr) + { + if ($command->useFileAsOutput) { + $file = $command->getOutputFile(); + if (file_exists($file) && filesize($file) > 0) return; + } + + if (!$command->useFileAsOutput && $stdout) { + return; + } + + $msg = array(); + $msg[] = 'Error! The command did not produce any output.'; + $msg[] = ''; + $msg[] = 'Generated command:'; + $msg[] = "$command"; + $msg[] = ''; + $msg[] = 'Returned message:'; + $arrayStderr = explode(PHP_EOL, $stderr); + array_pop($arrayStderr); + $msg = array_merge($msg, $arrayStderr); + $msg = join(PHP_EOL, $msg); + + throw new UnsuccessfulCommandException($msg); + } + + public static function checkProcessCreation($processHandle, $command) + { + if ($processHandle !== FALSE) return; + + $msg = array(); + $msg[] = 'Error! The command could not be launched.'; + $msg[] = ''; + $msg[] = 'Generated command:'; + $msg[] = "$command"; + $msg = join(PHP_EOL, $msg); + + throw new UnsuccessfulCommandException($msg); + } + + public static function checkTesseractVersion($expected, $action, $command) + { + $actual = $command->getTesseractVersion(); + + if ($actual[0] === 'v') + $actual = substr($actual, 1); + + if (version_compare($actual, $expected, ">=")) return; + + $msg = array(); + $msg[] = "Error! $action is not available this tesseract version"; + $msg[] = "Required version is $expected, actual version is $actual"; + $msg[] = ''; + $msg[] = 'Generated command:'; + $msg[] = "$command"; + $msg = join(PHP_EOL, $msg); + + throw new FeatureNotAvailableException($msg); + } + + public static function checkWritePermissions($path) + { + if (!is_dir(dirname($path))) mkdir(dirname($path)); + $writableDirectory = is_writable(dirname($path)); + $writableFile = true; + if (file_exists($path)) $writableFile = is_writable($path); + if ($writableFile && $writableDirectory) return; + + $msg = array(); + $msg[] = "Error! No permission to write to $path"; + $msg[] = "Make sure you have the right outputFile and permissions " + ."to write to the folder"; + $msg[] = ''; + $msg = join(PHP_EOL, $msg); + + throw new NoWritePermissionsForOutputFile($msg); + } +} diff --git a/tesseract/vendor/thiagoalessio/tesseract_ocr/src/ImageNotFoundException.php b/tesseract/vendor/thiagoalessio/tesseract_ocr/src/ImageNotFoundException.php new file mode 100644 index 000000000..2ba7df647 --- /dev/null +++ b/tesseract/vendor/thiagoalessio/tesseract_ocr/src/ImageNotFoundException.php @@ -0,0 +1,7 @@ +=') ? '-' : '')."-psm $psm"; + }; + } + + public static function oem($oem) + { + return function($version) use ($oem) { + Option::checkMinVersion('3.05', $version, 'oem'); + return "--oem $oem"; + }; + } + + public static function dpi($dpi) + { + return function() use ($dpi) { + return "--dpi $dpi"; + }; + } + + public static function userWords($path) + { + return function($version) use ($path) { + Option::checkMinVersion('3.04', $version, 'user-words'); + return '--user-words "'.addcslashes($path, '\\"').'"'; + }; + } + + public static function userPatterns($path) + { + return function($version) use ($path) { + Option::checkMinVersion('3.04', $version, 'user-patterns'); + return '--user-patterns "'.addcslashes($path, '\\"').'"'; + }; + } + + public static function tessdataDir($path) + { + return function() use ($path) { + return '--tessdata-dir "'.addcslashes($path, '\\"').'"'; + }; + } + + public static function lang() + { + $languages = func_get_args(); + return function() use ($languages) { + return '-l '.join('+', $languages); + }; + } + + public static function config($var, $value) + { + return function() use($var, $value) { + $snakeCase = function($str) { + return strtolower(preg_replace('/([A-Z])+/', '_$1', $str)); + }; + $pair = $snakeCase($var).'='.$value; + return '-c "'.addcslashes($pair, '\\"').'"'; + }; + } + + public static function checkMinVersion($minVersion, $currVersion, $option) + { + $minVersion = preg_replace('/^v/', '', $minVersion); + $currVersion = preg_replace('/^v/', '', $currVersion); + if (!version_compare($currVersion, $minVersion, '<')) return; + $msg = "$option option is only available on Tesseract $minVersion or later."; + $msg.= PHP_EOL."Your version of Tesseract is $currVersion"; + throw new \Exception($msg); + } +} diff --git a/tesseract/vendor/thiagoalessio/tesseract_ocr/src/Process.php b/tesseract/vendor/thiagoalessio/tesseract_ocr/src/Process.php new file mode 100644 index 000000000..38460eb07 --- /dev/null +++ b/tesseract/vendor/thiagoalessio/tesseract_ocr/src/Process.php @@ -0,0 +1,83 @@ +startTime = microtime(true); + $streamDescriptors = [ + array("pipe", "r"), + array("pipe", "w"), + array("pipe", "w") + ]; + $this->handle = proc_open($command, $streamDescriptors, $pipes, NULL, NULL, ["bypass_shell" => true]); + list($this->stdin, $this->stdout, $this->stderr) = $pipes; + + FriendlyErrors::checkProcessCreation($this->handle, $command); + + //This is can avoid deadlock on some cases (when stderr buffer is filled up before writing to stdout and vice-versa) + stream_set_blocking($this->stdout, 0); + stream_set_blocking($this->stderr, 0); + } + + public function write($data, $len) + { + $total = 0; + do + { + $res = fwrite($this->stdin, substr($data, $total)); + } while($res && $total += $res < $len); + return $total === $len; + } + + + public function wait($timeout = 0) + { + $running = true; + $data = ["out" => "", "err" => ""]; + while (($running === true) && !$this->hasTimedOut($timeout)) + { + $data["out"] .= fread($this->stdout, 8192); + $data["err"] .= fread($this->stderr, 8192); + $procInfo = proc_get_status($this->handle); + $running = $procInfo["running"]; + if ($running) { + usleep(1000); // Sleep 1ms to yield CPU time + } + } + return $data; + } + + public function close() + { + $this->closeStream($this->stdin); + $this->closeStream($this->stdout); + $this->closeStream($this->stderr); + return proc_close($this->handle); + } + + public function closeStdin() + { + $this->closeStream($this->stdin); + } + + private function hasTimedOut($timeout) + { + return (($timeout > 0) && ($this->startTime + $timeout < microtime(true))); + } + + private function closeStream(&$stream) + { + if ($stream !== NULL) + { + fclose($stream); + $stream = NULL; + } + } +} diff --git a/tesseract/vendor/thiagoalessio/tesseract_ocr/src/TesseractNotFoundException.php b/tesseract/vendor/thiagoalessio/tesseract_ocr/src/TesseractNotFoundException.php new file mode 100644 index 000000000..7b7f0c1e8 --- /dev/null +++ b/tesseract/vendor/thiagoalessio/tesseract_ocr/src/TesseractNotFoundException.php @@ -0,0 +1,7 @@ +command = $command ?: new Command; + $this->image("$image"); + } + + public function run($timeout = 0) + { + try { + if ($this->outputFile !== null) { + FriendlyErrors::checkWritePermissions($this->outputFile); + $this->command->useFileAsOutput = true; + } + + FriendlyErrors::checkTesseractPresence($this->command->executable); + if ($this->command->useFileAsInput) { + FriendlyErrors::checkImagePath($this->command->image); + } + + $process = new Process("{$this->command}"); + + if (!$this->command->useFileAsInput) { + $process->write($this->command->image, $this->command->imageSize); + $process->closeStdin(); + } + $output = $process->wait($timeout); + + FriendlyErrors::checkCommandExecution($this->command, $output["out"], $output["err"]); + } + catch (TesseractOcrException $e) { + if ($this->command->useFileAsOutput) $this->cleanTempFiles(); + throw $e; + } + + if ($this->command->useFileAsOutput) { + $text = file_get_contents($this->command->getOutputFile()); + + if ($this->outputFile !== null) { + rename($this->command->getOutputFile(), $this->outputFile); + } + + $this->cleanTempFiles(); + } + else + $text = $output["out"]; + + return trim($text, " \t\n\r\0\x0A\x0B\x0C"); + } + + public function imageData($image, $size) + { + FriendlyErrors::checkTesseractVersion("3.03-rc1", "Reading image data from stdin", $this->command); + $this->command->useFileAsInput = false; + $this->command->image = $image; + $this->command->imageSize = $size; + return $this; + } + + public function withoutTempFiles() + { + FriendlyErrors::checkTesseractVersion("3.03-rc1", "Writing to stdout (without using temp files)", $this->command); + $this->command->useFileAsOutput = false; + return $this; + } + + public function image($image) + { + $this->command->image = $image; + return $this; + } + + public function executable($executable) + { + FriendlyErrors::checkTesseractPresence($executable); + $this->command->executable = $executable; + return $this; + } + + public function configFile($configFile) + { + $this->command->configFile = $configFile; + return $this; + } + + public function tempDir($tempDir) + { + $this->command->tempDir = $tempDir; + return $this; + } + + public function threadLimit($limit) + { + $this->command->threadLimit = $limit; + return $this; + } + + // @deprecated + public function format($fmt) { return $this->configFile($fmt); } + + public function setOutputFile($path) { + $this->outputFile = $path; + return $this; + } + + public function allowlist() + { + $concat = function ($arg) { return is_array($arg) ? join('', $arg) : $arg; }; + $allowlist = join('', array_map($concat, func_get_args())); + $this->command->options[] = Option::config('tessedit_char_whitelist', $allowlist); + return $this; + } + + public function whitelist() + { + $warningMsg = 'Notice: whitelist is deprecated, use allowlist instead.'; + trigger_error($warningMsg, E_USER_NOTICE); + + $concat = function ($arg) { return is_array($arg) ? join('', $arg) : $arg; }; + $allowlist = join('', array_map($concat, func_get_args())); + return $this->allowlist($allowlist); + } + + public function version() + { + return $this->command->getTesseractVersion(); + } + + public function availableLanguages() + { + return $this->command->getAvailableLanguages(); + } + + public function __call($method, $args) + { + if ($this->isConfigFile($method)) return $this->configFile($method); + if ($this->isOption($method)) { + $option = $this->getOptionClassName().'::'.$method; + $this->command->options[] = call_user_func_array($option, $args); + return $this; + } + $arg = empty($args) ? null : $args[0]; + $this->command->options[] = Option::config($method, $arg); + return $this; + } + + private function isConfigFile($name) + { + return in_array($name, array('digits', 'hocr', 'pdf', 'quiet', 'tsv', 'txt')); + } + + private function isOption($name) + { + return in_array($name, get_class_methods($this->getOptionClassName())); + } + + private function getOptionClassName() + { + return __NAMESPACE__.'\\Option'; + } + + private function cleanTempFiles() + { + if (file_exists($this->command->getOutputFile(false))) { + unlink($this->command->getOutputFile(false)); + } + if (file_exists($this->command->getOutputFile(true))) { + unlink($this->command->getOutputFile(true)); + } + } +} diff --git a/tesseract/vendor/thiagoalessio/tesseract_ocr/src/TesseractOcrException.php b/tesseract/vendor/thiagoalessio/tesseract_ocr/src/TesseractOcrException.php new file mode 100644 index 000000000..8c0786165 --- /dev/null +++ b/tesseract/vendor/thiagoalessio/tesseract_ocr/src/TesseractOcrException.php @@ -0,0 +1,7 @@ + Date: Mon, 15 Jan 2024 20:09:03 +0000 Subject: [PATCH 099/388] README.md created --- tesseract/README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 tesseract/README.md diff --git a/tesseract/README.md b/tesseract/README.md new file mode 100644 index 000000000..d0b5eee2a --- /dev/null +++ b/tesseract/README.md @@ -0,0 +1 @@ +To make the addon work, you have to install the tesseract-ocr command line tool. \ No newline at end of file From c28af61873b71b5de2d1cdd4ebb64cd3ec535960 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 21 Jan 2024 21:24:08 +0000 Subject: [PATCH 100/388] Twitter: Fix error after posting --- twitter/twitter.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/twitter/twitter.php b/twitter/twitter.php index 8c906daf7..b01345b74 100644 --- a/twitter/twitter.php +++ b/twitter/twitter.php @@ -362,7 +362,7 @@ function twitter_post(int $uid, string $url, string $type, array $data): stdClas ]); $response = $client->post($url, ['auth' => 'oauth', $type => $data]); - $body = $response->getBodyString()->getContents(); + $body = $response->getBody()->getContents(); $status = [ 'code' => $response->getStatusCode(), @@ -399,7 +399,7 @@ function twitter_test_connection(int $uid) $status = [ 'code' => $response->getStatusCode(), 'reason' => $response->getReasonPhrase(), - 'content' => $response->getBodyString()->getContents() + 'content' => $response->getBody()->getContents() ]; DI::pConfig()->set(1, 'twitter', 'last_status', $status); Logger::info('Test successful', ['uid' => $uid]); From a30e9b788c427c73b3e3a0b621d70cb85de38eb1 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Fri, 12 Jan 2024 00:08:24 -0500 Subject: [PATCH 101/388] [advancedcontentfilter] Migrate Slim to version 4 to avoid PHP 8.2 deprecation error - Fix https://github.com/friendica/friendica/issues/13822 --- .../advancedcontentfilter.php | 24 +- advancedcontentfilter/composer.json | 3 +- advancedcontentfilter/composer.lock | 553 +++++--- advancedcontentfilter/src/middlewares.php | 33 +- advancedcontentfilter/src/routes.php | 21 +- .../vendor/composer/ClassLoader.php | 6 +- .../vendor/composer/autoload_classmap.php | 133 +- .../vendor/composer/autoload_namespaces.php | 1 - .../vendor/composer/autoload_psr4.php | 4 +- .../vendor/composer/autoload_real.php | 3 + .../vendor/composer/autoload_static.php | 161 +-- .../vendor/composer/installed.json | 572 +++++--- .../container-interop/.gitignore | 3 - .../container-interop/LICENSE | 20 - .../container-interop/README.md | 148 -- .../container-interop/composer.json | 15 - .../docs/ContainerInterface-meta.md | 114 -- .../docs/ContainerInterface.md | 158 --- .../docs/Delegate-lookup-meta.md | 259 ---- .../container-interop/docs/Delegate-lookup.md | 60 - .../docs/images/interoperating_containers.png | Bin 25738 -> 0 bytes .../docs/images/priority.png | Bin 16252 -> 0 bytes .../docs/images/side_by_side_containers.png | Bin 16265 -> 0 bytes .../Interop/Container/ContainerInterface.php | 15 - .../Exception/ContainerException.php | 15 - .../Container/Exception/NotFoundException.php | 15 - .../vendor/pimple/pimple/.gitignore | 3 - .../vendor/pimple/pimple/.travis.yml | 40 - .../vendor/pimple/pimple/CHANGELOG | 59 - .../vendor/pimple/pimple/README.rst | 326 ----- .../vendor/pimple/pimple/composer.json | 29 - .../pimple/pimple/ext/pimple/.gitignore | 30 - .../vendor/pimple/pimple/ext/pimple/README.md | 12 - .../vendor/pimple/pimple/ext/pimple/config.m4 | 63 - .../pimple/pimple/ext/pimple/config.w32 | 13 - .../pimple/pimple/ext/pimple/php_pimple.h | 137 -- .../vendor/pimple/pimple/ext/pimple/pimple.c | 1114 --------------- .../pimple/pimple/ext/pimple/pimple_compat.h | 81 -- .../pimple/pimple/ext/pimple/tests/001.phpt | 45 - .../pimple/pimple/ext/pimple/tests/002.phpt | 15 - .../pimple/pimple/ext/pimple/tests/003.phpt | 16 - .../pimple/pimple/ext/pimple/tests/004.phpt | 30 - .../pimple/pimple/ext/pimple/tests/005.phpt | 27 - .../pimple/pimple/ext/pimple/tests/006.phpt | 51 - .../pimple/pimple/ext/pimple/tests/007.phpt | 22 - .../pimple/pimple/ext/pimple/tests/008.phpt | 29 - .../pimple/pimple/ext/pimple/tests/009.phpt | 13 - .../pimple/pimple/ext/pimple/tests/010.phpt | 45 - .../pimple/pimple/ext/pimple/tests/011.phpt | 19 - .../pimple/pimple/ext/pimple/tests/012.phpt | 28 - .../pimple/pimple/ext/pimple/tests/013.phpt | 33 - .../pimple/pimple/ext/pimple/tests/014.phpt | 30 - .../pimple/pimple/ext/pimple/tests/015.phpt | 17 - .../pimple/pimple/ext/pimple/tests/016.phpt | 24 - .../pimple/pimple/ext/pimple/tests/017.phpt | 17 - .../pimple/pimple/ext/pimple/tests/017_1.phpt | 17 - .../pimple/pimple/ext/pimple/tests/018.phpt | 23 - .../pimple/pimple/ext/pimple/tests/019.phpt | 18 - .../pimple/pimple/ext/pimple/tests/bench.phpb | 51 - .../pimple/ext/pimple/tests/bench_shared.phpb | 25 - .../vendor/pimple/pimple/phpunit.xml.dist | 14 - .../pimple/pimple/src/Pimple/Container.php | 298 ---- .../Exception/ExpectedInvokableException.php | 38 - .../Exception/FrozenServiceException.php | 45 - .../InvalidServiceIdentifierException.php | 45 - .../Exception/UnknownIdentifierException.php | 45 - .../pimple/src/Pimple/Psr11/Container.php | 55 - .../src/Pimple/Psr11/ServiceLocator.php | 75 - .../pimple/src/Pimple/ServiceIterator.php | 69 - .../src/Pimple/ServiceProviderInterface.php | 46 - .../src/Pimple/Tests/Fixtures/Invokable.php | 38 - .../Pimple/Tests/Fixtures/NonInvokable.php | 34 - .../Tests/Fixtures/PimpleServiceProvider.php | 54 - .../src/Pimple/Tests/Fixtures/Service.php | 35 - .../PimpleServiceProviderInterfaceTest.php | 76 - .../pimple/src/Pimple/Tests/PimpleTest.php | 589 -------- .../src/Pimple/Tests/Psr11/ContainerTest.php | 77 -- .../Pimple/Tests/Psr11/ServiceLocatorTest.php | 134 -- .../src/Pimple/Tests/ServiceIteratorTest.php | 52 - .../vendor/psr/container/README.md | 14 +- .../vendor/psr/container/composer.json | 6 +- .../src/ContainerExceptionInterface.php | 7 +- .../psr/container/src/ContainerInterface.php | 9 +- .../src/NotFoundExceptionInterface.php | 3 - .../pimple => psr/http-factory}/LICENSE | 12 +- .../vendor/psr/http-factory/README.md | 12 + .../vendor/psr/http-factory/composer.json | 35 + .../src/RequestFactoryInterface.php | 18 + .../src/ResponseFactoryInterface.php | 18 + .../src/ServerRequestFactoryInterface.php | 24 + .../src/StreamFactoryInterface.php | 45 + .../src/UploadedFileFactoryInterface.php | 34 + .../http-factory/src/UriFactoryInterface.php | 17 + .../vendor/psr/http-message/README.md | 5 +- .../vendor/psr/http-message/composer.json | 4 +- .../psr/http-message/docs/PSR7-Interfaces.md | 130 ++ .../psr/http-message/docs/PSR7-Usage.md | 159 +++ .../psr/http-message/src/MessageInterface.php | 16 +- .../psr/http-message/src/RequestInterface.php | 10 +- .../http-message/src/ResponseInterface.php | 4 +- .../src/ServerRequestInterface.php | 8 +- .../psr/http-message/src/StreamInterface.php | 12 +- .../src/UploadedFileInterface.php | 4 +- .../psr/http-message/src/UriInterface.php | 17 +- .../vendor/psr/http-server-handler/LICENSE | 21 + .../vendor/psr/http-server-handler/README.md | 12 + .../psr/http-server-handler/composer.json | 36 + .../src/RequestHandlerInterface.php | 22 + .../vendor/psr/http-server-middleware/LICENSE | 21 + .../psr/http-server-middleware/README.md | 12 + .../psr/http-server-middleware/composer.json | 36 + .../src/MiddlewareInterface.php | 25 + .../vendor/psr/log/.gitignore | 1 - .../vendor/psr/log/Psr/Log/AbstractLogger.php | 32 +- .../psr/log/Psr/Log/LoggerAwareTrait.php | 2 +- .../psr/log/Psr/Log/LoggerInterface.php | 40 +- .../vendor/psr/log/Psr/Log/LoggerTrait.php | 2 + .../vendor/psr/log/Psr/Log/NullLogger.php | 2 + .../vendor/psr/log/Psr/Log/Test/DummyTest.php | 18 + .../log/Psr/Log/Test/LoggerInterfaceTest.php | 14 +- .../psr/log/Psr/Log/Test/TestLogger.php | 147 ++ .../vendor/psr/log/README.md | 13 + .../vendor/psr/log/composer.json | 4 +- .../vendor/slim/slim/CHANGELOG.md | 237 ++++ .../vendor/slim/slim/LICENSE.md | 2 +- .../vendor/slim/slim/MAINTAINERS.md | 17 + .../vendor/slim/slim/SECURITY.md | 14 + .../vendor/slim/slim/Slim/App.php | 730 ++-------- .../slim/slim/Slim/CallableResolver.php | 227 ++- .../slim/Slim/CallableResolverAwareTrait.php | 47 - .../vendor/slim/slim/Slim/Collection.php | 202 --- .../vendor/slim/slim/Slim/Container.php | 179 --- .../slim/Slim/DefaultServicesProvider.php | 211 --- .../slim/slim/Slim/DeferredCallable.php | 45 - .../slim/Slim/Error/AbstractErrorRenderer.php | 46 + .../Error/Renderers/HtmlErrorRenderer.php | 84 ++ .../Error/Renderers/JsonErrorRenderer.php | 56 + .../Renderers/PlainTextErrorRenderer.php | 59 + .../Slim/Error/Renderers/XmlErrorRenderer.php | 54 + .../Slim/Exception/ContainerException.php | 20 - .../ContainerValueNotFoundException.php | 20 - .../Exception/HttpBadRequestException.php | 28 + .../slim/Slim/Exception/HttpException.php | 64 + .../Slim/Exception/HttpForbiddenException.php | 27 + .../slim/Slim/Exception/HttpGoneException.php | 27 + .../HttpInternalServerErrorException.php | 27 + .../HttpMethodNotAllowedException.php | 52 + .../Slim/Exception/HttpNotFoundException.php | 27 + .../Exception/HttpNotImplementedException.php | 27 + .../Exception/HttpSpecializedException.php | 31 + .../Exception/HttpUnauthorizedException.php | 27 + .../Slim/Exception/InvalidMethodException.php | 27 - .../Exception/MethodNotAllowedException.php | 45 - .../slim/Slim/Exception/NotFoundException.php | 14 - .../slim/Slim/Exception/SlimException.php | 69 - .../slim/slim/Slim/Factory/AppFactory.php | 206 +++ .../Slim/Factory/Psr17/GuzzlePsr17Factory.php | 19 + .../Factory/Psr17/HttpSoftPsr17Factory.php | 19 + .../Psr17/LaminasDiactorosPsr17Factory.php | 19 + .../Slim/Factory/Psr17/NyholmPsr17Factory.php | 36 + .../slim/Slim/Factory/Psr17/Psr17Factory.php | 101 ++ .../Factory/Psr17/Psr17FactoryProvider.php | 53 + .../Factory/Psr17/ServerRequestCreator.php | 44 + .../Factory/Psr17/SlimHttpPsr17Factory.php | 39 + .../Psr17/SlimHttpServerRequestCreator.php | 56 + .../Slim/Factory/Psr17/SlimPsr17Factory.php | 19 + .../Factory/ServerRequestCreatorFactory.php | 87 ++ .../slim/slim/Slim/Handlers/AbstractError.php | 99 -- .../slim/Slim/Handlers/AbstractHandler.php | 59 - .../vendor/slim/slim/Slim/Handlers/Error.php | 224 --- .../slim/slim/Slim/Handlers/ErrorHandler.php | 308 +++++ .../slim/slim/Slim/Handlers/NotAllowed.php | 147 -- .../slim/slim/Slim/Handlers/NotFound.php | 141 -- .../slim/slim/Slim/Handlers/PhpError.php | 205 --- .../Handlers/Strategies/RequestHandler.php | 48 + .../Handlers/Strategies/RequestResponse.php | 19 +- .../Strategies/RequestResponseArgs.php | 24 +- .../Strategies/RequestResponseNamedArgs.php | 44 + .../vendor/slim/slim/Slim/Http/Body.php | 22 - .../vendor/slim/slim/Slim/Http/Cookies.php | 195 --- .../slim/slim/Slim/Http/Environment.php | 63 - .../vendor/slim/slim/Slim/Http/Headers.php | 222 --- .../vendor/slim/slim/Slim/Http/Message.php | 305 ---- .../vendor/slim/slim/Slim/Http/Request.php | 1227 ----------------- .../slim/slim/Slim/Http/RequestBody.php | 27 - .../vendor/slim/slim/Slim/Http/Response.php | 508 ------- .../vendor/slim/slim/Slim/Http/Stream.php | 450 ------ .../slim/slim/Slim/Http/UploadedFile.php | 327 ----- .../vendor/slim/slim/Slim/Http/Uri.php | 845 ------------ .../AdvancedCallableResolverInterface.php | 28 + .../Interfaces/CallableResolverInterface.php | 22 +- .../Slim/Interfaces/CollectionInterface.php | 32 - .../Slim/Interfaces/DispatcherInterface.php | 28 + .../Slim/Interfaces/ErrorHandlerInterface.php | 26 + .../Interfaces/ErrorRendererInterface.php | 18 + .../Slim/Interfaces/Http/CookiesInterface.php | 23 - .../Interfaces/Http/EnvironmentInterface.php | 20 - .../Slim/Interfaces/Http/HeadersInterface.php | 24 - .../InvocationStrategyInterface.php | 20 +- .../MiddlewareDispatcherInterface.php | 42 + .../Slim/Interfaces/Psr17FactoryInterface.php | 48 + .../Psr17FactoryProviderInterface.php | 26 + ...uestHandlerInvocationStrategyInterface.php | 15 + .../Interfaces/RouteCollectorInterface.php | 102 ++ .../RouteCollectorProxyInterface.php | 118 ++ .../Slim/Interfaces/RouteGroupInterface.php | 51 +- .../slim/Slim/Interfaces/RouteInterface.php | 151 +- .../Slim/Interfaces/RouteParserInterface.php | 52 + .../Interfaces/RouteResolverInterface.php | 17 + .../slim/Slim/Interfaces/RouterInterface.php | 111 -- .../ServerRequestCreatorInterface.php | 18 + .../vendor/slim/slim/Slim/Logger.php | 32 + .../Slim/Middleware/BodyParsingMiddleware.php | 196 +++ .../Middleware/ContentLengthMiddleware.php | 32 + .../slim/Slim/Middleware/ErrorMiddleware.php | 212 +++ .../Middleware/MethodOverrideMiddleware.php | 43 + .../Middleware/OutputBufferingMiddleware.php | 74 + .../Slim/Middleware/RoutingMiddleware.php | 98 ++ .../slim/slim/Slim/MiddlewareAwareTrait.php | 121 -- .../slim/slim/Slim/MiddlewareDispatcher.php | 275 ++++ .../vendor/slim/slim/Slim/ResponseEmitter.php | 136 ++ .../vendor/slim/slim/Slim/Routable.php | 106 -- .../vendor/slim/slim/Slim/Route.php | 349 ----- .../vendor/slim/slim/Slim/RouteGroup.php | 47 - .../vendor/slim/slim/Slim/Router.php | 455 ------ .../slim/slim/Slim/Routing/Dispatcher.php | 78 ++ .../slim/Slim/Routing/FastRouteDispatcher.php | 109 ++ .../vendor/slim/slim/Slim/Routing/Route.php | 360 +++++ .../slim/slim/Slim/Routing/RouteCollector.php | 293 ++++ .../slim/Slim/Routing/RouteCollectorProxy.php | 187 +++ .../slim/slim/Slim/Routing/RouteContext.php | 88 ++ .../slim/slim/Slim/Routing/RouteGroup.php | 104 ++ .../slim/slim/Slim/Routing/RouteParser.php | 127 ++ .../slim/slim/Slim/Routing/RouteResolver.php | 56 + .../slim/slim/Slim/Routing/RouteRunner.php | 70 + .../slim/slim/Slim/Routing/RoutingResults.php | 112 ++ .../vendor/slim/slim/composer.json | 74 +- .../symfony/cache/Adapter/AbstractAdapter.php | 94 +- .../cache/Adapter/AdapterInterface.php | 2 +- .../symfony/cache/Adapter/ArrayAdapter.php | 23 +- .../symfony/cache/Adapter/ChainAdapter.php | 48 +- .../symfony/cache/Adapter/DoctrineAdapter.php | 5 +- .../symfony/cache/Adapter/NullAdapter.php | 2 +- .../symfony/cache/Adapter/PdoAdapter.php | 4 +- .../symfony/cache/Adapter/PhpArrayAdapter.php | 62 +- .../symfony/cache/Adapter/PhpFilesAdapter.php | 4 +- .../symfony/cache/Adapter/ProxyAdapter.php | 42 +- .../cache/Adapter/SimpleCacheAdapter.php | 8 +- .../symfony/cache/Adapter/TagAwareAdapter.php | 183 ++- .../cache/Adapter/TraceableAdapter.php | 18 +- .../vendor/symfony/cache/CacheItem.php | 53 +- .../DataCollector/CacheDataCollector.php | 44 +- .../vendor/symfony/cache/DoctrineProvider.php | 3 +- .../vendor/symfony/cache/LICENSE | 2 +- .../symfony/cache/Simple/AbstractCache.php | 55 +- .../symfony/cache/Simple/ArrayCache.php | 30 +- .../symfony/cache/Simple/ChainCache.php | 14 +- .../symfony/cache/Simple/DoctrineCache.php | 5 +- .../symfony/cache/Simple/MemcachedCache.php | 5 +- .../vendor/symfony/cache/Simple/PdoCache.php | 4 +- .../symfony/cache/Simple/PhpArrayCache.php | 60 +- .../symfony/cache/Simple/PhpFilesCache.php | 4 +- .../vendor/symfony/cache/Simple/Psr6Cache.php | 69 +- .../symfony/cache/Simple/TraceableCache.php | 14 +- .../Adapter/AbstractRedisAdapterTest.php | 15 +- .../cache/Tests/Adapter/AdapterTestCase.php | 8 +- .../cache/Tests/Adapter/ApcuAdapterTest.php | 14 +- .../cache/Tests/Adapter/ArrayAdapterTest.php | 4 +- .../cache/Tests/Adapter/ChainAdapterTest.php | 157 ++- .../Tests/Adapter/DoctrineAdapterTest.php | 4 +- .../Tests/Adapter/FilesystemAdapterTest.php | 2 +- .../Tests/Adapter/MaxIdLengthAdapterTest.php | 50 +- .../Tests/Adapter/MemcachedAdapterTest.php | 112 +- .../cache/Tests/Adapter/NullAdapterTest.php | 4 +- .../cache/Tests/Adapter/PdoAdapterTest.php | 4 +- .../Tests/Adapter/PdoDbalAdapterTest.php | 8 +- .../Tests/Adapter/PhpArrayAdapterTest.php | 30 +- .../PhpArrayAdapterWithFallbackTest.php | 8 +- .../Tests/Adapter/PhpFilesAdapterTest.php | 4 +- .../cache/Tests/Adapter/PredisAdapterTest.php | 12 +- .../Adapter/PredisClusterAdapterTest.php | 6 +- .../Adapter/PredisRedisClusterAdapterTest.php | 28 + .../cache/Tests/Adapter/ProxyAdapterTest.php | 10 +- .../cache/Tests/Adapter/RedisAdapterTest.php | 36 +- .../Tests/Adapter/RedisArrayAdapterTest.php | 4 +- .../Tests/Adapter/RedisClusterAdapterTest.php | 27 + .../Tests/Adapter/SimpleCacheAdapterTest.php | 17 +- .../Tests/Adapter/TagAwareAdapterTest.php | 183 ++- ...TagAwareAndProxyAdapterIntegrationTest.php | 38 + .../Tests/Adapter/TraceableAdapterTest.php | 24 +- .../Adapter/TraceableTagAwareAdapterTest.php | 2 +- .../symfony/cache/Tests/CacheItemTest.php | 48 +- .../cache/Tests/Fixtures/ArrayCache.php | 8 +- .../cache/Tests/Fixtures/ExternalAdapter.php | 6 +- .../Tests/Simple/AbstractRedisCacheTest.php | 15 +- .../cache/Tests/Simple/ApcuCacheTest.php | 8 +- .../cache/Tests/Simple/CacheTestCase.php | 19 +- .../cache/Tests/Simple/ChainCacheTest.php | 37 +- .../cache/Tests/Simple/DoctrineCacheTest.php | 4 +- .../cache/Tests/Simple/MemcachedCacheTest.php | 99 +- .../Simple/MemcachedCacheTextModeTest.php | 25 + .../cache/Tests/Simple/NullCacheTest.php | 6 +- .../cache/Tests/Simple/PdoCacheTest.php | 4 +- .../cache/Tests/Simple/PdoDbalCacheTest.php | 8 +- .../cache/Tests/Simple/PhpArrayCacheTest.php | 36 +- .../Simple/PhpArrayCacheWithFallbackTest.php | 8 +- .../cache/Tests/Simple/PhpFilesCacheTest.php | 4 +- .../cache/Tests/Simple/Psr6CacheTest.php | 4 +- .../Tests/Simple/RedisArrayCacheTest.php | 4 +- .../cache/Tests/Simple/RedisCacheTest.php | 32 +- .../Tests/Simple/RedisClusterCacheTest.php | 27 + .../cache/Tests/Simple/TraceableCacheTest.php | 26 +- .../cache/Tests/Traits/PdoPruneableTrait.php | 6 +- .../symfony/cache/Traits/AbstractTrait.php | 52 +- .../vendor/symfony/cache/Traits/ApcuTrait.php | 16 +- .../symfony/cache/Traits/ArrayTrait.php | 12 +- .../symfony/cache/Traits/DoctrineTrait.php | 2 +- .../cache/Traits/FilesystemCommonTrait.php | 20 +- .../symfony/cache/Traits/FilesystemTrait.php | 6 +- .../symfony/cache/Traits/MemcachedTrait.php | 105 +- .../vendor/symfony/cache/Traits/PdoTrait.php | 105 +- .../symfony/cache/Traits/PhpArrayTrait.php | 40 +- .../symfony/cache/Traits/PhpFilesTrait.php | 24 +- .../symfony/cache/Traits/ProxyTrait.php | 2 + .../symfony/cache/Traits/RedisProxy.php | 2 +- .../symfony/cache/Traits/RedisTrait.php | 180 +-- .../vendor/symfony/cache/composer.json | 13 +- .../vendor/symfony/cache/phpunit.xml.dist | 12 +- .../symfony/expression-language/Compiler.php | 16 +- .../ExpressionFunction.php | 10 +- .../ExpressionLanguage.php | 20 +- .../symfony/expression-language/LICENSE | 2 +- .../symfony/expression-language/Lexer.php | 30 +- .../Node/ArgumentsNode.php | 2 +- .../expression-language/Node/ArrayNode.php | 14 +- .../expression-language/Node/BinaryNode.php | 28 +- .../Node/ConditionalNode.php | 4 +- .../expression-language/Node/ConstantNode.php | 8 +- .../expression-language/Node/FunctionNode.php | 14 +- .../expression-language/Node/GetAttrNode.php | 28 +- .../expression-language/Node/NameNode.php | 6 +- .../symfony/expression-language/Node/Node.php | 16 +- .../expression-language/Node/UnaryNode.php | 10 +- .../symfony/expression-language/Parser.php | 88 +- .../ParserCache/ArrayParserCache.php | 4 +- .../ParserCache/ParserCacheAdapter.php | 18 +- .../ParserCache/ParserCacheInterface.php | 2 +- .../Resources/bin/generate_operator_regex.php | 14 +- .../expression-language/SyntaxError.php | 4 +- .../Tests/ExpressionFunctionTest.php | 12 +- .../Tests/ExpressionLanguageTest.php | 130 +- .../Tests/Fixtures/TestProvider.php | 4 +- .../expression-language/Tests/LexerTest.php | 92 +- .../Tests/Node/AbstractNodeTest.php | 4 +- .../Tests/Node/ArgumentsNodeTest.php | 12 +- .../Tests/Node/ArrayNodeTest.php | 18 +- .../Tests/Node/BinaryNodeTest.php | 194 +-- .../Tests/Node/ConditionalNodeTest.php | 24 +- .../Tests/Node/ConstantNodeTest.php | 62 +- .../Tests/Node/FunctionNodeTest.php | 24 +- .../Tests/Node/GetAttrNodeTest.php | 46 +- .../Tests/Node/NameNodeTest.php | 18 +- .../Tests/Node/NodeTest.php | 6 +- .../Tests/Node/UnaryNodeTest.php | 38 +- .../ParserCache/ParserCacheAdapterTest.php | 26 +- .../expression-language/Tests/ParserTest.php | 193 +-- .../symfony/expression-language/Token.php | 2 +- .../expression-language/TokenStream.php | 4 +- .../symfony/expression-language/composer.json | 10 +- .../expression-language/phpunit.xml.dist | 2 +- .../vendor/symfony/polyfill-apcu/Apcu.php | 18 +- .../vendor/symfony/polyfill-apcu/LICENSE | 2 +- .../vendor/symfony/polyfill-apcu/README.md | 4 +- .../symfony/polyfill-apcu/bootstrap.php | 67 +- .../symfony/polyfill-apcu/bootstrap80.php | 75 + .../symfony/polyfill-apcu/composer.json | 8 +- 376 files changed, 10144 insertions(+), 15497 deletions(-) delete mode 100644 advancedcontentfilter/vendor/container-interop/container-interop/.gitignore delete mode 100644 advancedcontentfilter/vendor/container-interop/container-interop/LICENSE delete mode 100644 advancedcontentfilter/vendor/container-interop/container-interop/README.md delete mode 100644 advancedcontentfilter/vendor/container-interop/container-interop/composer.json delete mode 100644 advancedcontentfilter/vendor/container-interop/container-interop/docs/ContainerInterface-meta.md delete mode 100644 advancedcontentfilter/vendor/container-interop/container-interop/docs/ContainerInterface.md delete mode 100644 advancedcontentfilter/vendor/container-interop/container-interop/docs/Delegate-lookup-meta.md delete mode 100644 advancedcontentfilter/vendor/container-interop/container-interop/docs/Delegate-lookup.md delete mode 100644 advancedcontentfilter/vendor/container-interop/container-interop/docs/images/interoperating_containers.png delete mode 100644 advancedcontentfilter/vendor/container-interop/container-interop/docs/images/priority.png delete mode 100644 advancedcontentfilter/vendor/container-interop/container-interop/docs/images/side_by_side_containers.png delete mode 100644 advancedcontentfilter/vendor/container-interop/container-interop/src/Interop/Container/ContainerInterface.php delete mode 100644 advancedcontentfilter/vendor/container-interop/container-interop/src/Interop/Container/Exception/ContainerException.php delete mode 100644 advancedcontentfilter/vendor/container-interop/container-interop/src/Interop/Container/Exception/NotFoundException.php delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/.gitignore delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/.travis.yml delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/CHANGELOG delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/README.rst delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/composer.json delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/ext/pimple/.gitignore delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/ext/pimple/README.md delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/ext/pimple/config.m4 delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/ext/pimple/config.w32 delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/ext/pimple/php_pimple.h delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/ext/pimple/pimple.c delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/ext/pimple/pimple_compat.h delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/001.phpt delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/002.phpt delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/003.phpt delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/004.phpt delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/005.phpt delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/006.phpt delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/007.phpt delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/008.phpt delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/009.phpt delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/010.phpt delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/011.phpt delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/012.phpt delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/013.phpt delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/014.phpt delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/015.phpt delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/016.phpt delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/017.phpt delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/017_1.phpt delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/018.phpt delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/019.phpt delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/bench.phpb delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/bench_shared.phpb delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/phpunit.xml.dist delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Container.php delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Exception/ExpectedInvokableException.php delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Exception/FrozenServiceException.php delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Exception/InvalidServiceIdentifierException.php delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Exception/UnknownIdentifierException.php delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Psr11/Container.php delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Psr11/ServiceLocator.php delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/src/Pimple/ServiceIterator.php delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/src/Pimple/ServiceProviderInterface.php delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Invokable.php delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/NonInvokable.php delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/PimpleServiceProvider.php delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Service.php delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Tests/PimpleTest.php delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Tests/Psr11/ContainerTest.php delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Tests/Psr11/ServiceLocatorTest.php delete mode 100644 advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Tests/ServiceIteratorTest.php rename advancedcontentfilter/vendor/{pimple/pimple => psr/http-factory}/LICENSE (87%) create mode 100644 advancedcontentfilter/vendor/psr/http-factory/README.md create mode 100644 advancedcontentfilter/vendor/psr/http-factory/composer.json create mode 100644 advancedcontentfilter/vendor/psr/http-factory/src/RequestFactoryInterface.php create mode 100644 advancedcontentfilter/vendor/psr/http-factory/src/ResponseFactoryInterface.php create mode 100644 advancedcontentfilter/vendor/psr/http-factory/src/ServerRequestFactoryInterface.php create mode 100644 advancedcontentfilter/vendor/psr/http-factory/src/StreamFactoryInterface.php create mode 100644 advancedcontentfilter/vendor/psr/http-factory/src/UploadedFileFactoryInterface.php create mode 100644 advancedcontentfilter/vendor/psr/http-factory/src/UriFactoryInterface.php create mode 100644 advancedcontentfilter/vendor/psr/http-message/docs/PSR7-Interfaces.md create mode 100644 advancedcontentfilter/vendor/psr/http-message/docs/PSR7-Usage.md create mode 100644 advancedcontentfilter/vendor/psr/http-server-handler/LICENSE create mode 100644 advancedcontentfilter/vendor/psr/http-server-handler/README.md create mode 100644 advancedcontentfilter/vendor/psr/http-server-handler/composer.json create mode 100644 advancedcontentfilter/vendor/psr/http-server-handler/src/RequestHandlerInterface.php create mode 100644 advancedcontentfilter/vendor/psr/http-server-middleware/LICENSE create mode 100644 advancedcontentfilter/vendor/psr/http-server-middleware/README.md create mode 100644 advancedcontentfilter/vendor/psr/http-server-middleware/composer.json create mode 100644 advancedcontentfilter/vendor/psr/http-server-middleware/src/MiddlewareInterface.php delete mode 100644 advancedcontentfilter/vendor/psr/log/.gitignore create mode 100644 advancedcontentfilter/vendor/psr/log/Psr/Log/Test/DummyTest.php create mode 100644 advancedcontentfilter/vendor/psr/log/Psr/Log/Test/TestLogger.php create mode 100644 advancedcontentfilter/vendor/slim/slim/CHANGELOG.md create mode 100644 advancedcontentfilter/vendor/slim/slim/MAINTAINERS.md create mode 100644 advancedcontentfilter/vendor/slim/slim/SECURITY.md delete mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/CallableResolverAwareTrait.php delete mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Collection.php delete mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Container.php delete mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/DefaultServicesProvider.php delete mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/DeferredCallable.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Error/AbstractErrorRenderer.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Error/Renderers/HtmlErrorRenderer.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Error/Renderers/JsonErrorRenderer.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Error/Renderers/PlainTextErrorRenderer.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Error/Renderers/XmlErrorRenderer.php delete mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Exception/ContainerException.php delete mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Exception/ContainerValueNotFoundException.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Exception/HttpBadRequestException.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Exception/HttpException.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Exception/HttpForbiddenException.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Exception/HttpGoneException.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Exception/HttpInternalServerErrorException.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Exception/HttpMethodNotAllowedException.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Exception/HttpNotFoundException.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Exception/HttpNotImplementedException.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Exception/HttpSpecializedException.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Exception/HttpUnauthorizedException.php delete mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Exception/InvalidMethodException.php delete mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Exception/MethodNotAllowedException.php delete mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Exception/NotFoundException.php delete mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Exception/SlimException.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Factory/AppFactory.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Factory/Psr17/GuzzlePsr17Factory.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Factory/Psr17/HttpSoftPsr17Factory.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Factory/Psr17/LaminasDiactorosPsr17Factory.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Factory/Psr17/NyholmPsr17Factory.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Factory/Psr17/Psr17Factory.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Factory/Psr17/Psr17FactoryProvider.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Factory/Psr17/ServerRequestCreator.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Factory/Psr17/SlimHttpPsr17Factory.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Factory/Psr17/SlimHttpServerRequestCreator.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Factory/Psr17/SlimPsr17Factory.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Factory/ServerRequestCreatorFactory.php delete mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Handlers/AbstractError.php delete mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Handlers/AbstractHandler.php delete mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Handlers/Error.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Handlers/ErrorHandler.php delete mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Handlers/NotAllowed.php delete mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Handlers/NotFound.php delete mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Handlers/PhpError.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Handlers/Strategies/RequestHandler.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponseNamedArgs.php delete mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Http/Body.php delete mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Http/Cookies.php delete mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Http/Environment.php delete mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Http/Headers.php delete mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Http/Message.php delete mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Http/Request.php delete mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Http/RequestBody.php delete mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Http/Response.php delete mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Http/Stream.php delete mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Http/UploadedFile.php delete mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Http/Uri.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Interfaces/AdvancedCallableResolverInterface.php delete mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Interfaces/CollectionInterface.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Interfaces/DispatcherInterface.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Interfaces/ErrorHandlerInterface.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Interfaces/ErrorRendererInterface.php delete mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Interfaces/Http/CookiesInterface.php delete mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Interfaces/Http/EnvironmentInterface.php delete mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Interfaces/Http/HeadersInterface.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Interfaces/MiddlewareDispatcherInterface.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Interfaces/Psr17FactoryInterface.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Interfaces/Psr17FactoryProviderInterface.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Interfaces/RequestHandlerInvocationStrategyInterface.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Interfaces/RouteCollectorInterface.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Interfaces/RouteCollectorProxyInterface.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Interfaces/RouteParserInterface.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Interfaces/RouteResolverInterface.php delete mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Interfaces/RouterInterface.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Interfaces/ServerRequestCreatorInterface.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Logger.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Middleware/BodyParsingMiddleware.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Middleware/ContentLengthMiddleware.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Middleware/ErrorMiddleware.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Middleware/MethodOverrideMiddleware.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Middleware/OutputBufferingMiddleware.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Middleware/RoutingMiddleware.php delete mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/MiddlewareAwareTrait.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/MiddlewareDispatcher.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/ResponseEmitter.php delete mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Routable.php delete mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Route.php delete mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/RouteGroup.php delete mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Router.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Routing/Dispatcher.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Routing/FastRouteDispatcher.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Routing/Route.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Routing/RouteCollector.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Routing/RouteCollectorProxy.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Routing/RouteContext.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Routing/RouteGroup.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Routing/RouteParser.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Routing/RouteResolver.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Routing/RouteRunner.php create mode 100644 advancedcontentfilter/vendor/slim/slim/Slim/Routing/RoutingResults.php create mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PredisRedisClusterAdapterTest.php create mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/RedisClusterAdapterTest.php create mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TagAwareAndProxyAdapterIntegrationTest.php create mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Simple/MemcachedCacheTextModeTest.php create mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Simple/RedisClusterCacheTest.php create mode 100644 advancedcontentfilter/vendor/symfony/polyfill-apcu/bootstrap80.php diff --git a/advancedcontentfilter/advancedcontentfilter.php b/advancedcontentfilter/advancedcontentfilter.php index f2927f574..55bc50056 100644 --- a/advancedcontentfilter/advancedcontentfilter.php +++ b/advancedcontentfilter/advancedcontentfilter.php @@ -190,7 +190,7 @@ function advancedcontentfilter_module() {} function advancedcontentfilter_init() { if (DI::args()->getArgc() > 1 && DI::args()->getArgv()[1] == 'api') { - $slim = new \Slim\App(); + $slim = \Slim\Factory\AppFactory::create(); require __DIR__ . '/src/middlewares.php'; @@ -305,7 +305,7 @@ function advancedcontentfilter_build_fields($data) * API */ -function advancedcontentfilter_get_rules() +function advancedcontentfilter_get_rules(ServerRequestInterface $request, ResponseInterface $response) { if (!DI::userSession()->getLocalUserId()) { throw new HTTPException\UnauthorizedException(DI::l10n()->t('You must be logged in to use this method')); @@ -313,7 +313,8 @@ function advancedcontentfilter_get_rules() $rules = DBA::toArray(DBA::select('advancedcontentfilter_rules', [], ['uid' => DI::userSession()->getLocalUserId()])); - return json_encode($rules); + $response->getBody()->write(json_encode($rules)); + return $response->withHeader('Content-Type', 'application/json'); } function advancedcontentfilter_get_rules_id(ServerRequestInterface $request, ResponseInterface $response, $args) @@ -324,10 +325,11 @@ function advancedcontentfilter_get_rules_id(ServerRequestInterface $request, Res $rule = DBA::selectFirst('advancedcontentfilter_rules', [], ['id' => $args['id'], 'uid' => DI::userSession()->getLocalUserId()]); - return json_encode($rule); + $response->getBody()->write(json_encode($rule)); + return $response->withHeader('Content-Type', 'application/json'); } -function advancedcontentfilter_post_rules(ServerRequestInterface $request) +function advancedcontentfilter_post_rules(ServerRequestInterface $request, ResponseInterface $response) { if (!DI::userSession()->getLocalUserId()) { throw new HTTPException\UnauthorizedException(DI::l10n()->t('You must be logged in to use this method')); @@ -360,7 +362,8 @@ function advancedcontentfilter_post_rules(ServerRequestInterface $request) DI::cache()->delete('rules_' . DI::userSession()->getLocalUserId()); - return json_encode(['message' => DI::l10n()->t('Rule successfully added'), 'rule' => $rule]); + $response->getBody()->write(json_encode(['message' => DI::l10n()->t('Rule successfully added'), 'rule' => $rule])); + return $response->withHeader('Content-Type', 'application/json'); } function advancedcontentfilter_put_rules_id(ServerRequestInterface $request, ResponseInterface $response, $args) @@ -391,7 +394,8 @@ function advancedcontentfilter_put_rules_id(ServerRequestInterface $request, Res DI::cache()->delete('rules_' . DI::userSession()->getLocalUserId()); - return json_encode(['message' => DI::l10n()->t('Rule successfully updated')]); + $response->getBody()->write(json_encode(['message' => DI::l10n()->t('Rule successfully updated')])); + return $response->withHeader('Content-Type', 'application/json'); } function advancedcontentfilter_delete_rules_id(ServerRequestInterface $request, ResponseInterface $response, $args) @@ -414,7 +418,8 @@ function advancedcontentfilter_delete_rules_id(ServerRequestInterface $request, DI::cache()->delete('rules_' . DI::userSession()->getLocalUserId()); - return json_encode(['message' => DI::l10n()->t('Rule successfully deleted')]); + $response->getBody()->write(json_encode(['message' => DI::l10n()->t('Rule successfully deleted')])); + return $response->withHeader('Content-Type', 'application/json'); } function advancedcontentfilter_get_variables_guid(ServerRequestInterface $request, ResponseInterface $response, $args) @@ -437,7 +442,8 @@ function advancedcontentfilter_get_variables_guid(ServerRequestInterface $reques $return = advancedcontentfilter_get_filter_fields(advancedcontentfilter_prepare_item_row($item_row)); - return json_encode(['variables' => str_replace('\\\'', '\'', var_export($return, true))]); + $response->getBody()->write(json_encode(['variables' => str_replace('\\\'', '\'', var_export($return, true))])); + return $response->withHeader('Content-Type', 'application/json'); } /** diff --git a/advancedcontentfilter/composer.json b/advancedcontentfilter/composer.json index 93b19cd59..ceb152e79 100644 --- a/advancedcontentfilter/composer.json +++ b/advancedcontentfilter/composer.json @@ -11,8 +11,7 @@ } ], "require": { - "php": ">=5.6.0", - "slim/slim": "^3.1", + "slim/slim": "^4", "symfony/expression-language": "^3.4" }, "license": "3-clause BSD license", diff --git a/advancedcontentfilter/composer.lock b/advancedcontentfilter/composer.lock index 774b5ec8f..83d61074d 100644 --- a/advancedcontentfilter/composer.lock +++ b/advancedcontentfilter/composer.lock @@ -4,40 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "d0e3662dd9d910ffe4f71d325bc39319", + "content-hash": "3e87f0369e4799fc35d98f399c67f1e9", "packages": [ - { - "name": "container-interop/container-interop", - "version": "1.2.0", - "source": { - "type": "git", - "url": "https://github.com/container-interop/container-interop.git", - "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/container-interop/container-interop/zipball/79cbf1341c22ec75643d841642dd5d6acd83bdb8", - "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8", - "shasum": "" - }, - "require": { - "psr/container": "^1.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Interop\\Container\\": "src/Interop/Container/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Promoting the interoperability of container objects (DIC, SL, etc.)", - "homepage": "https://github.com/container-interop/container-interop", - "abandoned": "psr/container", - "time": "2017-02-14T19:40:03+00:00" - }, { "name": "nikic/fast-route", "version": "v1.3.0", @@ -84,56 +52,6 @@ ], "time": "2018-02-13T20:26:39+00:00" }, - { - "name": "pimple/pimple", - "version": "v3.2.3", - "source": { - "type": "git", - "url": "https://github.com/silexphp/Pimple.git", - "reference": "9e403941ef9d65d20cba7d54e29fe906db42cf32" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/silexphp/Pimple/zipball/9e403941ef9d65d20cba7d54e29fe906db42cf32", - "reference": "9e403941ef9d65d20cba7d54e29fe906db42cf32", - "shasum": "" - }, - "require": { - "php": ">=5.3.0", - "psr/container": "^1.0" - }, - "require-dev": { - "symfony/phpunit-bridge": "^3.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.2.x-dev" - } - }, - "autoload": { - "psr-0": { - "Pimple": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - } - ], - "description": "Pimple, a simple Dependency Injection Container", - "homepage": "http://pimple.sensiolabs.org", - "keywords": [ - "container", - "dependency injection" - ], - "time": "2018-01-21T07:42:36+00:00" - }, { "name": "psr/cache", "version": "1.0.1", @@ -182,25 +100,25 @@ }, { "name": "psr/container", - "version": "1.0.0", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/php-fig/container.git", - "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", - "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=7.4.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -215,7 +133,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "description": "Common Container Interface (PHP FIG PSR-11)", @@ -227,24 +145,25 @@ "container-interop", "psr" ], - "time": "2017-02-14T16:28:37+00:00" + "time": "2021-11-05T16:47:00+00:00" }, { - "name": "psr/http-message", - "version": "1.0.1", + "name": "psr/http-factory", + "version": "1.0.2", "source": { "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + "url": "https://github.com/php-fig/http-factory.git", + "reference": "e616d01114759c4c489f93b099585439f795fe35" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35", + "reference": "e616d01114759c4c489f93b099585439f795fe35", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=7.0.0", + "psr/http-message": "^1.0 || ^2.0" }, "type": "library", "extra": { @@ -261,6 +180,57 @@ "license": [ "MIT" ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "time": "2023-04-10T20:10:41+00:00" + }, + { + "name": "psr/http-message", + "version": "1.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/cb6ce4845ce34a8ad9e68117c10ee90a29919eba", + "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], "authors": [ { "name": "PHP-FIG", @@ -277,20 +247,126 @@ "request", "response" ], - "time": "2016-08-06T14:39:51+00:00" + "time": "2023-04-04T09:50:52+00:00" }, { - "name": "psr/log", - "version": "1.1.2", + "name": "psr/http-server-handler", + "version": "1.0.2", "source": { "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801" + "url": "https://github.com/php-fig/http-server-handler.git", + "reference": "84c4fb66179be4caaf8e97bd239203245302e7d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/446d54b4cb6bf489fc9d75f55843658e6f25d801", - "reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801", + "url": "https://api.github.com/repos/php-fig/http-server-handler/zipball/84c4fb66179be4caaf8e97bd239203245302e7d4", + "reference": "84c4fb66179be4caaf8e97bd239203245302e7d4", + "shasum": "" + }, + "require": { + "php": ">=7.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Server\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP server-side request handler", + "keywords": [ + "handler", + "http", + "http-interop", + "psr", + "psr-15", + "psr-7", + "request", + "response", + "server" + ], + "time": "2023-04-10T20:06:20+00:00" + }, + { + "name": "psr/http-server-middleware", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-server-middleware.git", + "reference": "c1481f747daaa6a0782775cd6a8c26a1bf4a3829" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-server-middleware/zipball/c1481f747daaa6a0782775cd6a8c26a1bf4a3829", + "reference": "c1481f747daaa6a0782775cd6a8c26a1bf4a3829", + "shasum": "" + }, + "require": { + "php": ">=7.0", + "psr/http-message": "^1.0 || ^2.0", + "psr/http-server-handler": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Server\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP server-side middleware", + "keywords": [ + "http", + "http-interop", + "middleware", + "psr", + "psr-15", + "psr-7", + "request", + "response" + ], + "time": "2023-04-11T06:14:47+00:00" + }, + { + "name": "psr/log", + "version": "1.1.4", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11", "shasum": "" }, "require": { @@ -314,7 +390,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "description": "Common interface for logging libraries", @@ -324,7 +400,7 @@ "psr", "psr-3" ], - "time": "2019-11-01T11:05:21+00:00" + "time": "2021-05-03T11:20:27+00:00" }, { "name": "psr/simple-cache", @@ -376,32 +452,51 @@ }, { "name": "slim/slim", - "version": "3.9.2", + "version": "4.12.0", "source": { "type": "git", "url": "https://github.com/slimphp/Slim.git", - "reference": "4086d0106cf5a7135c69fce4161fe355a8feb118" + "reference": "e9e99c2b24398b967841c6c4c3048622cc7e2b18" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/slimphp/Slim/zipball/4086d0106cf5a7135c69fce4161fe355a8feb118", - "reference": "4086d0106cf5a7135c69fce4161fe355a8feb118", + "url": "https://api.github.com/repos/slimphp/Slim/zipball/e9e99c2b24398b967841c6c4c3048622cc7e2b18", + "reference": "e9e99c2b24398b967841c6c4c3048622cc7e2b18", "shasum": "" }, "require": { - "container-interop/container-interop": "^1.2", - "nikic/fast-route": "^1.0", - "php": ">=5.5.0", - "pimple/pimple": "^3.0", - "psr/container": "^1.0", - "psr/http-message": "^1.0" - }, - "provide": { - "psr/http-message-implementation": "1.0" + "ext-json": "*", + "nikic/fast-route": "^1.3", + "php": "^7.4 || ^8.0", + "psr/container": "^1.0 || ^2.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1", + "psr/http-server-handler": "^1.0", + "psr/http-server-middleware": "^1.0", + "psr/log": "^1.1 || ^2.0 || ^3.0" }, "require-dev": { - "phpunit/phpunit": "^4.0", - "squizlabs/php_codesniffer": "^2.5" + "adriansuter/php-autoload-override": "^1.4", + "ext-simplexml": "*", + "guzzlehttp/psr7": "^2.5", + "httpsoft/http-message": "^1.1", + "httpsoft/http-server-request": "^1.1", + "laminas/laminas-diactoros": "^2.17", + "nyholm/psr7": "^1.8", + "nyholm/psr7-server": "^1.0", + "phpspec/prophecy": "^1.17", + "phpspec/prophecy-phpunit": "^2.0", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^9.6", + "slim/http": "^1.3", + "slim/psr7": "^1.6", + "squizlabs/php_codesniffer": "^3.7" + }, + "suggest": { + "ext-simplexml": "Needed to support XML format in BodyParsingMiddleware", + "ext-xml": "Needed to support XML format in BodyParsingMiddleware", + "php-di/php-di": "PHP-DI is the recommended container library to be used with Slim", + "slim/psr7": "Slim PSR-7 implementation. See https://www.slimframework.com/docs/v4/start/installation.html for more information." }, "type": "library", "autoload": { @@ -414,49 +509,64 @@ "MIT" ], "authors": [ - { - "name": "Rob Allen", - "email": "rob@akrabat.com", - "homepage": "http://akrabat.com" - }, { "name": "Josh Lockhart", "email": "hello@joshlockhart.com", "homepage": "https://joshlockhart.com" }, - { - "name": "Gabriel Manricks", - "email": "gmanricks@me.com", - "homepage": "http://gabrielmanricks.com" - }, { "name": "Andrew Smith", "email": "a.smith@silentworks.co.uk", "homepage": "http://silentworks.co.uk" + }, + { + "name": "Rob Allen", + "email": "rob@akrabat.com", + "homepage": "http://akrabat.com" + }, + { + "name": "Pierre Berube", + "email": "pierre@lgse.com", + "homepage": "http://www.lgse.com" + }, + { + "name": "Gabriel Manricks", + "email": "gmanricks@me.com", + "homepage": "http://gabrielmanricks.com" } ], "description": "Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs", - "homepage": "https://slimframework.com", + "homepage": "https://www.slimframework.com", "keywords": [ "api", "framework", "micro", "router" ], - "time": "2017-11-26T19:13:09+00:00" + "funding": [ + { + "url": "https://opencollective.com/slimphp", + "type": "open_collective" + }, + { + "url": "https://tidelift.com/funding/github/packagist/slim/slim", + "type": "tidelift" + } + ], + "time": "2023-07-23T04:54:29+00:00" }, { "name": "symfony/cache", - "version": "v3.4.36", + "version": "v3.4.47", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "3d9f46a6960fd5cd7f030f86adc5b4b63bcfa4e3" + "reference": "a7a14c4832760bd1fbd31be2859ffedc9b6ff813" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/3d9f46a6960fd5cd7f030f86adc5b4b63bcfa4e3", - "reference": "3d9f46a6960fd5cd7f030f86adc5b4b63bcfa4e3", + "url": "https://api.github.com/repos/symfony/cache/zipball/a7a14c4832760bd1fbd31be2859ffedc9b6ff813", + "reference": "a7a14c4832760bd1fbd31be2859ffedc9b6ff813", "shasum": "" }, "require": { @@ -475,16 +585,11 @@ }, "require-dev": { "cache/integration-tests": "dev-master", - "doctrine/cache": "~1.6", - "doctrine/dbal": "~2.4", - "predis/predis": "~1.0" + "doctrine/cache": "^1.6", + "doctrine/dbal": "^2.4|^3.0", + "predis/predis": "^1.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, "autoload": { "psr-4": { "Symfony\\Component\\Cache\\": "" @@ -513,32 +618,42 @@ "caching", "psr6" ], - "time": "2019-12-01T10:45:41+00:00" + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-10-24T10:57:07+00:00" }, { "name": "symfony/expression-language", - "version": "v3.4.8", + "version": "v3.4.47", "source": { "type": "git", "url": "https://github.com/symfony/expression-language.git", - "reference": "867e4d1f5d4e52435a8ffff6b24fd6a801582241" + "reference": "de38e66398fca1fcb9c48e80279910e6889cb28f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/expression-language/zipball/867e4d1f5d4e52435a8ffff6b24fd6a801582241", - "reference": "867e4d1f5d4e52435a8ffff6b24fd6a801582241", + "url": "https://api.github.com/repos/symfony/expression-language/zipball/de38e66398fca1fcb9c48e80279910e6889cb28f", + "reference": "de38e66398fca1fcb9c48e80279910e6889cb28f", "shasum": "" }, "require": { "php": "^5.5.9|>=7.0.8", - "symfony/cache": "~3.1|~4.0" + "symfony/cache": "~3.1|~4.0", + "symfony/polyfill-php70": "~1.6" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, "autoload": { "psr-4": { "Symfony\\Component\\ExpressionLanguage\\": "" @@ -563,38 +678,56 @@ ], "description": "Symfony ExpressionLanguage Component", "homepage": "https://symfony.com", - "time": "2018-01-03T07:37:34+00:00" + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-10-24T10:57:07+00:00" }, { "name": "symfony/polyfill-apcu", - "version": "v1.13.1", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-apcu.git", - "reference": "a8e961c841b9ec52927a87914f8820a1ad8f8116" + "reference": "c6c2c0f5f4cb0b100c5dfea807ef5cd27bbe9899" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-apcu/zipball/a8e961c841b9ec52927a87914f8820a1ad8f8116", - "reference": "a8e961c841b9ec52927a87914f8820a1ad8f8116", + "url": "https://api.github.com/repos/symfony/polyfill-apcu/zipball/c6c2c0f5f4cb0b100c5dfea807ef5cd27bbe9899", + "reference": "c6c2c0f5f4cb0b100c5dfea807ef5cd27bbe9899", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.13-dev" + "dev-main": "1.28-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } }, "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Apcu\\": "" - }, "files": [ "bootstrap.php" - ] + ], + "psr-4": { + "Symfony\\Polyfill\\Apcu\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -619,7 +752,86 @@ "portable", "shim" ], - "time": "2019-11-27T13:56:44+00:00" + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-01-26T09:26:14+00:00" + }, + { + "name": "symfony/polyfill-php70", + "version": "v1.20.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php70.git", + "reference": "5f03a781d984aae42cebd18e7912fa80f02ee644" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/5f03a781d984aae42cebd18e7912fa80f02ee644", + "reference": "5f03a781d984aae42cebd18e7912fa80f02ee644", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "metapackage", + "extra": { + "branch-alias": { + "dev-main": "1.20-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-10-23T14:02:19+00:00" } ], "packages-dev": [], @@ -631,5 +843,6 @@ "platform": { "php": ">=5.6.0" }, - "platform-dev": [] + "platform-dev": [], + "plugin-api-version": "1.1.0" } diff --git a/advancedcontentfilter/src/middlewares.php b/advancedcontentfilter/src/middlewares.php index dffb93632..84dd6ed8e 100644 --- a/advancedcontentfilter/src/middlewares.php +++ b/advancedcontentfilter/src/middlewares.php @@ -21,31 +21,12 @@ use Friendica\DI; -$container = $slim->getContainer(); +/** @var $slim \Slim\App */ -// Error handler based off https://stackoverflow.com/a/48135009/757392 -$container['errorHandler'] = function () { - return function(Psr\Http\Message\RequestInterface $request, Psr\Http\Message\ResponseInterface $response, Exception $exception) - { - $responseCode = 500; +/** + * The routing middleware should be added before the ErrorMiddleware + * Otherwise exceptions thrown from it will not be handled + */ +$slim->addRoutingMiddleware(); - if (is_a($exception, 'Friendica\Network\HTTPException')) { - $responseCode = $exception->getCode(); - } - - $errors['message'] = $exception->getMessage(); - - $errors['responseCode'] = $responseCode; - - return $response - ->withStatus($responseCode) - ->withJson($errors); - }; -}; - -$container['notFoundHandler'] = function () { - return function () - { - throw new \Friendica\Network\HTTPException\NotFoundException(DI::l10n()->t('Method not found')); - }; -}; +$errorMiddleware = $slim->addErrorMiddleware(true, true, true); diff --git a/advancedcontentfilter/src/routes.php b/advancedcontentfilter/src/routes.php index 09077bdae..a46f1b4b5 100644 --- a/advancedcontentfilter/src/routes.php +++ b/advancedcontentfilter/src/routes.php @@ -20,20 +20,17 @@ */ /* @var $slim Slim\App */ -$slim->group('/advancedcontentfilter/api', function () { - /* @var $this Slim\App */ - $this->group('/rules', function () { - /* @var $this Slim\App */ - $this->get('', 'advancedcontentfilter_get_rules'); - $this->post('', 'advancedcontentfilter_post_rules'); +$slim->group('/advancedcontentfilter/api', function (\Slim\Routing\RouteCollectorProxy $app) { + $app->group('/rules', function (\Slim\Routing\RouteCollectorProxy $app) { + $app->get('', 'advancedcontentfilter_get_rules'); + $app->post('', 'advancedcontentfilter_post_rules'); - $this->get('/{id}', 'advancedcontentfilter_get_rules_id'); - $this->put('/{id}', 'advancedcontentfilter_put_rules_id'); - $this->delete('/{id}', 'advancedcontentfilter_delete_rules_id'); + $app->get('/{id}', 'advancedcontentfilter_get_rules_id'); + $app->put('/{id}', 'advancedcontentfilter_put_rules_id'); + $app->delete('/{id}', 'advancedcontentfilter_delete_rules_id'); }); - $this->group('/variables', function () { - /* @var $this Slim\App */ - $this->get('/{guid}', 'advancedcontentfilter_get_variables_guid'); + $app->group('/variables', function (\Slim\Routing\RouteCollectorProxy $app) { + $app->get('/{guid}', 'advancedcontentfilter_get_variables_guid'); }); }); diff --git a/advancedcontentfilter/vendor/composer/ClassLoader.php b/advancedcontentfilter/vendor/composer/ClassLoader.php index dc02dfb11..03b9bb9c4 100644 --- a/advancedcontentfilter/vendor/composer/ClassLoader.php +++ b/advancedcontentfilter/vendor/composer/ClassLoader.php @@ -60,7 +60,7 @@ class ClassLoader public function getPrefixes() { if (!empty($this->prefixesPsr0)) { - return call_user_func_array('array_merge', $this->prefixesPsr0); + return call_user_func_array('array_merge', array_values($this->prefixesPsr0)); } return array(); @@ -279,7 +279,7 @@ class ClassLoader */ public function setApcuPrefix($apcuPrefix) { - $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null; + $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null; } /** @@ -377,7 +377,7 @@ class ClassLoader $subPath = $class; while (false !== $lastPos = strrpos($subPath, '\\')) { $subPath = substr($subPath, 0, $lastPos); - $search = $subPath.'\\'; + $search = $subPath . '\\'; if (isset($this->prefixDirsPsr4[$search])) { $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); foreach ($this->prefixDirsPsr4[$search] as $dir) { diff --git a/advancedcontentfilter/vendor/composer/autoload_classmap.php b/advancedcontentfilter/vendor/composer/autoload_classmap.php index 4f884be1d..aa3de8a37 100644 --- a/advancedcontentfilter/vendor/composer/autoload_classmap.php +++ b/advancedcontentfilter/vendor/composer/autoload_classmap.php @@ -23,27 +23,6 @@ return array( 'FastRoute\\RouteCollector' => $vendorDir . '/nikic/fast-route/src/RouteCollector.php', 'FastRoute\\RouteParser' => $vendorDir . '/nikic/fast-route/src/RouteParser.php', 'FastRoute\\RouteParser\\Std' => $vendorDir . '/nikic/fast-route/src/RouteParser/Std.php', - 'Interop\\Container\\ContainerInterface' => $vendorDir . '/container-interop/container-interop/src/Interop/Container/ContainerInterface.php', - 'Interop\\Container\\Exception\\ContainerException' => $vendorDir . '/container-interop/container-interop/src/Interop/Container/Exception/ContainerException.php', - 'Interop\\Container\\Exception\\NotFoundException' => $vendorDir . '/container-interop/container-interop/src/Interop/Container/Exception/NotFoundException.php', - 'Pimple\\Container' => $vendorDir . '/pimple/pimple/src/Pimple/Container.php', - 'Pimple\\Exception\\ExpectedInvokableException' => $vendorDir . '/pimple/pimple/src/Pimple/Exception/ExpectedInvokableException.php', - 'Pimple\\Exception\\FrozenServiceException' => $vendorDir . '/pimple/pimple/src/Pimple/Exception/FrozenServiceException.php', - 'Pimple\\Exception\\InvalidServiceIdentifierException' => $vendorDir . '/pimple/pimple/src/Pimple/Exception/InvalidServiceIdentifierException.php', - 'Pimple\\Exception\\UnknownIdentifierException' => $vendorDir . '/pimple/pimple/src/Pimple/Exception/UnknownIdentifierException.php', - 'Pimple\\Psr11\\Container' => $vendorDir . '/pimple/pimple/src/Pimple/Psr11/Container.php', - 'Pimple\\Psr11\\ServiceLocator' => $vendorDir . '/pimple/pimple/src/Pimple/Psr11/ServiceLocator.php', - 'Pimple\\ServiceIterator' => $vendorDir . '/pimple/pimple/src/Pimple/ServiceIterator.php', - 'Pimple\\ServiceProviderInterface' => $vendorDir . '/pimple/pimple/src/Pimple/ServiceProviderInterface.php', - 'Pimple\\Tests\\Fixtures\\Invokable' => $vendorDir . '/pimple/pimple/src/Pimple/Tests/Fixtures/Invokable.php', - 'Pimple\\Tests\\Fixtures\\NonInvokable' => $vendorDir . '/pimple/pimple/src/Pimple/Tests/Fixtures/NonInvokable.php', - 'Pimple\\Tests\\Fixtures\\PimpleServiceProvider' => $vendorDir . '/pimple/pimple/src/Pimple/Tests/Fixtures/PimpleServiceProvider.php', - 'Pimple\\Tests\\Fixtures\\Service' => $vendorDir . '/pimple/pimple/src/Pimple/Tests/Fixtures/Service.php', - 'Pimple\\Tests\\PimpleServiceProviderInterfaceTest' => $vendorDir . '/pimple/pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php', - 'Pimple\\Tests\\PimpleTest' => $vendorDir . '/pimple/pimple/src/Pimple/Tests/PimpleTest.php', - 'Pimple\\Tests\\Psr11\\ContainerTest' => $vendorDir . '/pimple/pimple/src/Pimple/Tests/Psr11/ContainerTest.php', - 'Pimple\\Tests\\Psr11\\ServiceLocatorTest' => $vendorDir . '/pimple/pimple/src/Pimple/Tests/Psr11/ServiceLocatorTest.php', - 'Pimple\\Tests\\ServiceIteratorTest' => $vendorDir . '/pimple/pimple/src/Pimple/Tests/ServiceIteratorTest.php', 'Psr\\Cache\\CacheException' => $vendorDir . '/psr/cache/src/CacheException.php', 'Psr\\Cache\\CacheItemInterface' => $vendorDir . '/psr/cache/src/CacheItemInterface.php', 'Psr\\Cache\\CacheItemPoolInterface' => $vendorDir . '/psr/cache/src/CacheItemPoolInterface.php', @@ -52,12 +31,20 @@ return array( 'Psr\\Container\\ContainerInterface' => $vendorDir . '/psr/container/src/ContainerInterface.php', 'Psr\\Container\\NotFoundExceptionInterface' => $vendorDir . '/psr/container/src/NotFoundExceptionInterface.php', 'Psr\\Http\\Message\\MessageInterface' => $vendorDir . '/psr/http-message/src/MessageInterface.php', + 'Psr\\Http\\Message\\RequestFactoryInterface' => $vendorDir . '/psr/http-factory/src/RequestFactoryInterface.php', 'Psr\\Http\\Message\\RequestInterface' => $vendorDir . '/psr/http-message/src/RequestInterface.php', + 'Psr\\Http\\Message\\ResponseFactoryInterface' => $vendorDir . '/psr/http-factory/src/ResponseFactoryInterface.php', 'Psr\\Http\\Message\\ResponseInterface' => $vendorDir . '/psr/http-message/src/ResponseInterface.php', + 'Psr\\Http\\Message\\ServerRequestFactoryInterface' => $vendorDir . '/psr/http-factory/src/ServerRequestFactoryInterface.php', 'Psr\\Http\\Message\\ServerRequestInterface' => $vendorDir . '/psr/http-message/src/ServerRequestInterface.php', + 'Psr\\Http\\Message\\StreamFactoryInterface' => $vendorDir . '/psr/http-factory/src/StreamFactoryInterface.php', 'Psr\\Http\\Message\\StreamInterface' => $vendorDir . '/psr/http-message/src/StreamInterface.php', + 'Psr\\Http\\Message\\UploadedFileFactoryInterface' => $vendorDir . '/psr/http-factory/src/UploadedFileFactoryInterface.php', 'Psr\\Http\\Message\\UploadedFileInterface' => $vendorDir . '/psr/http-message/src/UploadedFileInterface.php', + 'Psr\\Http\\Message\\UriFactoryInterface' => $vendorDir . '/psr/http-factory/src/UriFactoryInterface.php', 'Psr\\Http\\Message\\UriInterface' => $vendorDir . '/psr/http-message/src/UriInterface.php', + 'Psr\\Http\\Server\\MiddlewareInterface' => $vendorDir . '/psr/http-server-middleware/src/MiddlewareInterface.php', + 'Psr\\Http\\Server\\RequestHandlerInterface' => $vendorDir . '/psr/http-server-handler/src/RequestHandlerInterface.php', 'Psr\\Log\\AbstractLogger' => $vendorDir . '/psr/log/Psr/Log/AbstractLogger.php', 'Psr\\Log\\InvalidArgumentException' => $vendorDir . '/psr/log/Psr/Log/InvalidArgumentException.php', 'Psr\\Log\\LogLevel' => $vendorDir . '/psr/log/Psr/Log/LogLevel.php', @@ -66,57 +53,83 @@ return array( 'Psr\\Log\\LoggerInterface' => $vendorDir . '/psr/log/Psr/Log/LoggerInterface.php', 'Psr\\Log\\LoggerTrait' => $vendorDir . '/psr/log/Psr/Log/LoggerTrait.php', 'Psr\\Log\\NullLogger' => $vendorDir . '/psr/log/Psr/Log/NullLogger.php', - 'Psr\\Log\\Test\\DummyTest' => $vendorDir . '/psr/log/Psr/Log/Test/LoggerInterfaceTest.php', + 'Psr\\Log\\Test\\DummyTest' => $vendorDir . '/psr/log/Psr/Log/Test/DummyTest.php', 'Psr\\Log\\Test\\LoggerInterfaceTest' => $vendorDir . '/psr/log/Psr/Log/Test/LoggerInterfaceTest.php', + 'Psr\\Log\\Test\\TestLogger' => $vendorDir . '/psr/log/Psr/Log/Test/TestLogger.php', 'Psr\\SimpleCache\\CacheException' => $vendorDir . '/psr/simple-cache/src/CacheException.php', 'Psr\\SimpleCache\\CacheInterface' => $vendorDir . '/psr/simple-cache/src/CacheInterface.php', 'Psr\\SimpleCache\\InvalidArgumentException' => $vendorDir . '/psr/simple-cache/src/InvalidArgumentException.php', 'Slim\\App' => $vendorDir . '/slim/slim/Slim/App.php', 'Slim\\CallableResolver' => $vendorDir . '/slim/slim/Slim/CallableResolver.php', - 'Slim\\CallableResolverAwareTrait' => $vendorDir . '/slim/slim/Slim/CallableResolverAwareTrait.php', - 'Slim\\Collection' => $vendorDir . '/slim/slim/Slim/Collection.php', - 'Slim\\Container' => $vendorDir . '/slim/slim/Slim/Container.php', - 'Slim\\DefaultServicesProvider' => $vendorDir . '/slim/slim/Slim/DefaultServicesProvider.php', - 'Slim\\DeferredCallable' => $vendorDir . '/slim/slim/Slim/DeferredCallable.php', - 'Slim\\Exception\\ContainerException' => $vendorDir . '/slim/slim/Slim/Exception/ContainerException.php', - 'Slim\\Exception\\ContainerValueNotFoundException' => $vendorDir . '/slim/slim/Slim/Exception/ContainerValueNotFoundException.php', - 'Slim\\Exception\\InvalidMethodException' => $vendorDir . '/slim/slim/Slim/Exception/InvalidMethodException.php', - 'Slim\\Exception\\MethodNotAllowedException' => $vendorDir . '/slim/slim/Slim/Exception/MethodNotAllowedException.php', - 'Slim\\Exception\\NotFoundException' => $vendorDir . '/slim/slim/Slim/Exception/NotFoundException.php', - 'Slim\\Exception\\SlimException' => $vendorDir . '/slim/slim/Slim/Exception/SlimException.php', - 'Slim\\Handlers\\AbstractError' => $vendorDir . '/slim/slim/Slim/Handlers/AbstractError.php', - 'Slim\\Handlers\\AbstractHandler' => $vendorDir . '/slim/slim/Slim/Handlers/AbstractHandler.php', - 'Slim\\Handlers\\Error' => $vendorDir . '/slim/slim/Slim/Handlers/Error.php', - 'Slim\\Handlers\\NotAllowed' => $vendorDir . '/slim/slim/Slim/Handlers/NotAllowed.php', - 'Slim\\Handlers\\NotFound' => $vendorDir . '/slim/slim/Slim/Handlers/NotFound.php', - 'Slim\\Handlers\\PhpError' => $vendorDir . '/slim/slim/Slim/Handlers/PhpError.php', + 'Slim\\Error\\AbstractErrorRenderer' => $vendorDir . '/slim/slim/Slim/Error/AbstractErrorRenderer.php', + 'Slim\\Error\\Renderers\\HtmlErrorRenderer' => $vendorDir . '/slim/slim/Slim/Error/Renderers/HtmlErrorRenderer.php', + 'Slim\\Error\\Renderers\\JsonErrorRenderer' => $vendorDir . '/slim/slim/Slim/Error/Renderers/JsonErrorRenderer.php', + 'Slim\\Error\\Renderers\\PlainTextErrorRenderer' => $vendorDir . '/slim/slim/Slim/Error/Renderers/PlainTextErrorRenderer.php', + 'Slim\\Error\\Renderers\\XmlErrorRenderer' => $vendorDir . '/slim/slim/Slim/Error/Renderers/XmlErrorRenderer.php', + 'Slim\\Exception\\HttpBadRequestException' => $vendorDir . '/slim/slim/Slim/Exception/HttpBadRequestException.php', + 'Slim\\Exception\\HttpException' => $vendorDir . '/slim/slim/Slim/Exception/HttpException.php', + 'Slim\\Exception\\HttpForbiddenException' => $vendorDir . '/slim/slim/Slim/Exception/HttpForbiddenException.php', + 'Slim\\Exception\\HttpGoneException' => $vendorDir . '/slim/slim/Slim/Exception/HttpGoneException.php', + 'Slim\\Exception\\HttpInternalServerErrorException' => $vendorDir . '/slim/slim/Slim/Exception/HttpInternalServerErrorException.php', + 'Slim\\Exception\\HttpMethodNotAllowedException' => $vendorDir . '/slim/slim/Slim/Exception/HttpMethodNotAllowedException.php', + 'Slim\\Exception\\HttpNotFoundException' => $vendorDir . '/slim/slim/Slim/Exception/HttpNotFoundException.php', + 'Slim\\Exception\\HttpNotImplementedException' => $vendorDir . '/slim/slim/Slim/Exception/HttpNotImplementedException.php', + 'Slim\\Exception\\HttpSpecializedException' => $vendorDir . '/slim/slim/Slim/Exception/HttpSpecializedException.php', + 'Slim\\Exception\\HttpUnauthorizedException' => $vendorDir . '/slim/slim/Slim/Exception/HttpUnauthorizedException.php', + 'Slim\\Factory\\AppFactory' => $vendorDir . '/slim/slim/Slim/Factory/AppFactory.php', + 'Slim\\Factory\\Psr17\\GuzzlePsr17Factory' => $vendorDir . '/slim/slim/Slim/Factory/Psr17/GuzzlePsr17Factory.php', + 'Slim\\Factory\\Psr17\\HttpSoftPsr17Factory' => $vendorDir . '/slim/slim/Slim/Factory/Psr17/HttpSoftPsr17Factory.php', + 'Slim\\Factory\\Psr17\\LaminasDiactorosPsr17Factory' => $vendorDir . '/slim/slim/Slim/Factory/Psr17/LaminasDiactorosPsr17Factory.php', + 'Slim\\Factory\\Psr17\\NyholmPsr17Factory' => $vendorDir . '/slim/slim/Slim/Factory/Psr17/NyholmPsr17Factory.php', + 'Slim\\Factory\\Psr17\\Psr17Factory' => $vendorDir . '/slim/slim/Slim/Factory/Psr17/Psr17Factory.php', + 'Slim\\Factory\\Psr17\\Psr17FactoryProvider' => $vendorDir . '/slim/slim/Slim/Factory/Psr17/Psr17FactoryProvider.php', + 'Slim\\Factory\\Psr17\\ServerRequestCreator' => $vendorDir . '/slim/slim/Slim/Factory/Psr17/ServerRequestCreator.php', + 'Slim\\Factory\\Psr17\\SlimHttpPsr17Factory' => $vendorDir . '/slim/slim/Slim/Factory/Psr17/SlimHttpPsr17Factory.php', + 'Slim\\Factory\\Psr17\\SlimHttpServerRequestCreator' => $vendorDir . '/slim/slim/Slim/Factory/Psr17/SlimHttpServerRequestCreator.php', + 'Slim\\Factory\\Psr17\\SlimPsr17Factory' => $vendorDir . '/slim/slim/Slim/Factory/Psr17/SlimPsr17Factory.php', + 'Slim\\Factory\\ServerRequestCreatorFactory' => $vendorDir . '/slim/slim/Slim/Factory/ServerRequestCreatorFactory.php', + 'Slim\\Handlers\\ErrorHandler' => $vendorDir . '/slim/slim/Slim/Handlers/ErrorHandler.php', + 'Slim\\Handlers\\Strategies\\RequestHandler' => $vendorDir . '/slim/slim/Slim/Handlers/Strategies/RequestHandler.php', 'Slim\\Handlers\\Strategies\\RequestResponse' => $vendorDir . '/slim/slim/Slim/Handlers/Strategies/RequestResponse.php', 'Slim\\Handlers\\Strategies\\RequestResponseArgs' => $vendorDir . '/slim/slim/Slim/Handlers/Strategies/RequestResponseArgs.php', - 'Slim\\Http\\Body' => $vendorDir . '/slim/slim/Slim/Http/Body.php', - 'Slim\\Http\\Cookies' => $vendorDir . '/slim/slim/Slim/Http/Cookies.php', - 'Slim\\Http\\Environment' => $vendorDir . '/slim/slim/Slim/Http/Environment.php', - 'Slim\\Http\\Headers' => $vendorDir . '/slim/slim/Slim/Http/Headers.php', - 'Slim\\Http\\Message' => $vendorDir . '/slim/slim/Slim/Http/Message.php', - 'Slim\\Http\\Request' => $vendorDir . '/slim/slim/Slim/Http/Request.php', - 'Slim\\Http\\RequestBody' => $vendorDir . '/slim/slim/Slim/Http/RequestBody.php', - 'Slim\\Http\\Response' => $vendorDir . '/slim/slim/Slim/Http/Response.php', - 'Slim\\Http\\Stream' => $vendorDir . '/slim/slim/Slim/Http/Stream.php', - 'Slim\\Http\\UploadedFile' => $vendorDir . '/slim/slim/Slim/Http/UploadedFile.php', - 'Slim\\Http\\Uri' => $vendorDir . '/slim/slim/Slim/Http/Uri.php', + 'Slim\\Handlers\\Strategies\\RequestResponseNamedArgs' => $vendorDir . '/slim/slim/Slim/Handlers/Strategies/RequestResponseNamedArgs.php', + 'Slim\\Interfaces\\AdvancedCallableResolverInterface' => $vendorDir . '/slim/slim/Slim/Interfaces/AdvancedCallableResolverInterface.php', 'Slim\\Interfaces\\CallableResolverInterface' => $vendorDir . '/slim/slim/Slim/Interfaces/CallableResolverInterface.php', - 'Slim\\Interfaces\\CollectionInterface' => $vendorDir . '/slim/slim/Slim/Interfaces/CollectionInterface.php', - 'Slim\\Interfaces\\Http\\CookiesInterface' => $vendorDir . '/slim/slim/Slim/Interfaces/Http/CookiesInterface.php', - 'Slim\\Interfaces\\Http\\EnvironmentInterface' => $vendorDir . '/slim/slim/Slim/Interfaces/Http/EnvironmentInterface.php', - 'Slim\\Interfaces\\Http\\HeadersInterface' => $vendorDir . '/slim/slim/Slim/Interfaces/Http/HeadersInterface.php', + 'Slim\\Interfaces\\DispatcherInterface' => $vendorDir . '/slim/slim/Slim/Interfaces/DispatcherInterface.php', + 'Slim\\Interfaces\\ErrorHandlerInterface' => $vendorDir . '/slim/slim/Slim/Interfaces/ErrorHandlerInterface.php', + 'Slim\\Interfaces\\ErrorRendererInterface' => $vendorDir . '/slim/slim/Slim/Interfaces/ErrorRendererInterface.php', 'Slim\\Interfaces\\InvocationStrategyInterface' => $vendorDir . '/slim/slim/Slim/Interfaces/InvocationStrategyInterface.php', + 'Slim\\Interfaces\\MiddlewareDispatcherInterface' => $vendorDir . '/slim/slim/Slim/Interfaces/MiddlewareDispatcherInterface.php', + 'Slim\\Interfaces\\Psr17FactoryInterface' => $vendorDir . '/slim/slim/Slim/Interfaces/Psr17FactoryInterface.php', + 'Slim\\Interfaces\\Psr17FactoryProviderInterface' => $vendorDir . '/slim/slim/Slim/Interfaces/Psr17FactoryProviderInterface.php', + 'Slim\\Interfaces\\RequestHandlerInvocationStrategyInterface' => $vendorDir . '/slim/slim/Slim/Interfaces/RequestHandlerInvocationStrategyInterface.php', + 'Slim\\Interfaces\\RouteCollectorInterface' => $vendorDir . '/slim/slim/Slim/Interfaces/RouteCollectorInterface.php', + 'Slim\\Interfaces\\RouteCollectorProxyInterface' => $vendorDir . '/slim/slim/Slim/Interfaces/RouteCollectorProxyInterface.php', 'Slim\\Interfaces\\RouteGroupInterface' => $vendorDir . '/slim/slim/Slim/Interfaces/RouteGroupInterface.php', 'Slim\\Interfaces\\RouteInterface' => $vendorDir . '/slim/slim/Slim/Interfaces/RouteInterface.php', - 'Slim\\Interfaces\\RouterInterface' => $vendorDir . '/slim/slim/Slim/Interfaces/RouterInterface.php', - 'Slim\\MiddlewareAwareTrait' => $vendorDir . '/slim/slim/Slim/MiddlewareAwareTrait.php', - 'Slim\\Routable' => $vendorDir . '/slim/slim/Slim/Routable.php', - 'Slim\\Route' => $vendorDir . '/slim/slim/Slim/Route.php', - 'Slim\\RouteGroup' => $vendorDir . '/slim/slim/Slim/RouteGroup.php', - 'Slim\\Router' => $vendorDir . '/slim/slim/Slim/Router.php', + 'Slim\\Interfaces\\RouteParserInterface' => $vendorDir . '/slim/slim/Slim/Interfaces/RouteParserInterface.php', + 'Slim\\Interfaces\\RouteResolverInterface' => $vendorDir . '/slim/slim/Slim/Interfaces/RouteResolverInterface.php', + 'Slim\\Interfaces\\ServerRequestCreatorInterface' => $vendorDir . '/slim/slim/Slim/Interfaces/ServerRequestCreatorInterface.php', + 'Slim\\Logger' => $vendorDir . '/slim/slim/Slim/Logger.php', + 'Slim\\MiddlewareDispatcher' => $vendorDir . '/slim/slim/Slim/MiddlewareDispatcher.php', + 'Slim\\Middleware\\BodyParsingMiddleware' => $vendorDir . '/slim/slim/Slim/Middleware/BodyParsingMiddleware.php', + 'Slim\\Middleware\\ContentLengthMiddleware' => $vendorDir . '/slim/slim/Slim/Middleware/ContentLengthMiddleware.php', + 'Slim\\Middleware\\ErrorMiddleware' => $vendorDir . '/slim/slim/Slim/Middleware/ErrorMiddleware.php', + 'Slim\\Middleware\\MethodOverrideMiddleware' => $vendorDir . '/slim/slim/Slim/Middleware/MethodOverrideMiddleware.php', + 'Slim\\Middleware\\OutputBufferingMiddleware' => $vendorDir . '/slim/slim/Slim/Middleware/OutputBufferingMiddleware.php', + 'Slim\\Middleware\\RoutingMiddleware' => $vendorDir . '/slim/slim/Slim/Middleware/RoutingMiddleware.php', + 'Slim\\ResponseEmitter' => $vendorDir . '/slim/slim/Slim/ResponseEmitter.php', + 'Slim\\Routing\\Dispatcher' => $vendorDir . '/slim/slim/Slim/Routing/Dispatcher.php', + 'Slim\\Routing\\FastRouteDispatcher' => $vendorDir . '/slim/slim/Slim/Routing/FastRouteDispatcher.php', + 'Slim\\Routing\\Route' => $vendorDir . '/slim/slim/Slim/Routing/Route.php', + 'Slim\\Routing\\RouteCollector' => $vendorDir . '/slim/slim/Slim/Routing/RouteCollector.php', + 'Slim\\Routing\\RouteCollectorProxy' => $vendorDir . '/slim/slim/Slim/Routing/RouteCollectorProxy.php', + 'Slim\\Routing\\RouteContext' => $vendorDir . '/slim/slim/Slim/Routing/RouteContext.php', + 'Slim\\Routing\\RouteGroup' => $vendorDir . '/slim/slim/Slim/Routing/RouteGroup.php', + 'Slim\\Routing\\RouteParser' => $vendorDir . '/slim/slim/Slim/Routing/RouteParser.php', + 'Slim\\Routing\\RouteResolver' => $vendorDir . '/slim/slim/Slim/Routing/RouteResolver.php', + 'Slim\\Routing\\RouteRunner' => $vendorDir . '/slim/slim/Slim/Routing/RouteRunner.php', + 'Slim\\Routing\\RoutingResults' => $vendorDir . '/slim/slim/Slim/Routing/RoutingResults.php', 'Symfony\\Component\\Cache\\Adapter\\AbstractAdapter' => $vendorDir . '/symfony/cache/Adapter/AbstractAdapter.php', 'Symfony\\Component\\Cache\\Adapter\\AdapterInterface' => $vendorDir . '/symfony/cache/Adapter/AdapterInterface.php', 'Symfony\\Component\\Cache\\Adapter\\ApcuAdapter' => $vendorDir . '/symfony/cache/Adapter/ApcuAdapter.php', diff --git a/advancedcontentfilter/vendor/composer/autoload_namespaces.php b/advancedcontentfilter/vendor/composer/autoload_namespaces.php index c3cd02297..b7fc0125d 100644 --- a/advancedcontentfilter/vendor/composer/autoload_namespaces.php +++ b/advancedcontentfilter/vendor/composer/autoload_namespaces.php @@ -6,5 +6,4 @@ $vendorDir = dirname(dirname(__FILE__)); $baseDir = dirname($vendorDir); return array( - 'Pimple' => array($vendorDir . '/pimple/pimple/src'), ); diff --git a/advancedcontentfilter/vendor/composer/autoload_psr4.php b/advancedcontentfilter/vendor/composer/autoload_psr4.php index f466cc18f..876065857 100644 --- a/advancedcontentfilter/vendor/composer/autoload_psr4.php +++ b/advancedcontentfilter/vendor/composer/autoload_psr4.php @@ -12,9 +12,9 @@ return array( 'Slim\\' => array($vendorDir . '/slim/slim/Slim'), 'Psr\\SimpleCache\\' => array($vendorDir . '/psr/simple-cache/src'), 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'), - 'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'), + 'Psr\\Http\\Server\\' => array($vendorDir . '/psr/http-server-handler/src', $vendorDir . '/psr/http-server-middleware/src'), + 'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-factory/src', $vendorDir . '/psr/http-message/src'), 'Psr\\Container\\' => array($vendorDir . '/psr/container/src'), 'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'), - 'Interop\\Container\\' => array($vendorDir . '/container-interop/container-interop/src/Interop/Container'), 'FastRoute\\' => array($vendorDir . '/nikic/fast-route/src'), ); diff --git a/advancedcontentfilter/vendor/composer/autoload_real.php b/advancedcontentfilter/vendor/composer/autoload_real.php index 6d7169aeb..d6532d7d4 100644 --- a/advancedcontentfilter/vendor/composer/autoload_real.php +++ b/advancedcontentfilter/vendor/composer/autoload_real.php @@ -13,6 +13,9 @@ class ComposerAutoloaderInitAdvancedContentFilterAddon } } + /** + * @return \Composer\Autoload\ClassLoader + */ public static function getLoader() { if (null !== self::$loader) { diff --git a/advancedcontentfilter/vendor/composer/autoload_static.php b/advancedcontentfilter/vendor/composer/autoload_static.php index e7c2f8de4..917d3d90a 100644 --- a/advancedcontentfilter/vendor/composer/autoload_static.php +++ b/advancedcontentfilter/vendor/composer/autoload_static.php @@ -23,14 +23,11 @@ class ComposerStaticInitAdvancedContentFilterAddon array ( 'Psr\\SimpleCache\\' => 16, 'Psr\\Log\\' => 8, + 'Psr\\Http\\Server\\' => 16, 'Psr\\Http\\Message\\' => 17, 'Psr\\Container\\' => 14, 'Psr\\Cache\\' => 10, ), - 'I' => - array ( - 'Interop\\Container\\' => 18, - ), 'F' => array ( 'FastRoute\\' => 10, @@ -62,9 +59,15 @@ class ComposerStaticInitAdvancedContentFilterAddon array ( 0 => __DIR__ . '/..' . '/psr/log/Psr/Log', ), + 'Psr\\Http\\Server\\' => + array ( + 0 => __DIR__ . '/..' . '/psr/http-server-handler/src', + 1 => __DIR__ . '/..' . '/psr/http-server-middleware/src', + ), 'Psr\\Http\\Message\\' => array ( - 0 => __DIR__ . '/..' . '/psr/http-message/src', + 0 => __DIR__ . '/..' . '/psr/http-factory/src', + 1 => __DIR__ . '/..' . '/psr/http-message/src', ), 'Psr\\Container\\' => array ( @@ -74,26 +77,12 @@ class ComposerStaticInitAdvancedContentFilterAddon array ( 0 => __DIR__ . '/..' . '/psr/cache/src', ), - 'Interop\\Container\\' => - array ( - 0 => __DIR__ . '/..' . '/container-interop/container-interop/src/Interop/Container', - ), 'FastRoute\\' => array ( 0 => __DIR__ . '/..' . '/nikic/fast-route/src', ), ); - public static $prefixesPsr0 = array ( - 'P' => - array ( - 'Pimple' => - array ( - 0 => __DIR__ . '/..' . '/pimple/pimple/src', - ), - ), - ); - public static $classMap = array ( 'FastRoute\\BadRouteException' => __DIR__ . '/..' . '/nikic/fast-route/src/BadRouteException.php', 'FastRoute\\DataGenerator' => __DIR__ . '/..' . '/nikic/fast-route/src/DataGenerator.php', @@ -112,27 +101,6 @@ class ComposerStaticInitAdvancedContentFilterAddon 'FastRoute\\RouteCollector' => __DIR__ . '/..' . '/nikic/fast-route/src/RouteCollector.php', 'FastRoute\\RouteParser' => __DIR__ . '/..' . '/nikic/fast-route/src/RouteParser.php', 'FastRoute\\RouteParser\\Std' => __DIR__ . '/..' . '/nikic/fast-route/src/RouteParser/Std.php', - 'Interop\\Container\\ContainerInterface' => __DIR__ . '/..' . '/container-interop/container-interop/src/Interop/Container/ContainerInterface.php', - 'Interop\\Container\\Exception\\ContainerException' => __DIR__ . '/..' . '/container-interop/container-interop/src/Interop/Container/Exception/ContainerException.php', - 'Interop\\Container\\Exception\\NotFoundException' => __DIR__ . '/..' . '/container-interop/container-interop/src/Interop/Container/Exception/NotFoundException.php', - 'Pimple\\Container' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Container.php', - 'Pimple\\Exception\\ExpectedInvokableException' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Exception/ExpectedInvokableException.php', - 'Pimple\\Exception\\FrozenServiceException' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Exception/FrozenServiceException.php', - 'Pimple\\Exception\\InvalidServiceIdentifierException' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Exception/InvalidServiceIdentifierException.php', - 'Pimple\\Exception\\UnknownIdentifierException' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Exception/UnknownIdentifierException.php', - 'Pimple\\Psr11\\Container' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Psr11/Container.php', - 'Pimple\\Psr11\\ServiceLocator' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Psr11/ServiceLocator.php', - 'Pimple\\ServiceIterator' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/ServiceIterator.php', - 'Pimple\\ServiceProviderInterface' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/ServiceProviderInterface.php', - 'Pimple\\Tests\\Fixtures\\Invokable' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Tests/Fixtures/Invokable.php', - 'Pimple\\Tests\\Fixtures\\NonInvokable' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Tests/Fixtures/NonInvokable.php', - 'Pimple\\Tests\\Fixtures\\PimpleServiceProvider' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Tests/Fixtures/PimpleServiceProvider.php', - 'Pimple\\Tests\\Fixtures\\Service' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Tests/Fixtures/Service.php', - 'Pimple\\Tests\\PimpleServiceProviderInterfaceTest' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php', - 'Pimple\\Tests\\PimpleTest' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Tests/PimpleTest.php', - 'Pimple\\Tests\\Psr11\\ContainerTest' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Tests/Psr11/ContainerTest.php', - 'Pimple\\Tests\\Psr11\\ServiceLocatorTest' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Tests/Psr11/ServiceLocatorTest.php', - 'Pimple\\Tests\\ServiceIteratorTest' => __DIR__ . '/..' . '/pimple/pimple/src/Pimple/Tests/ServiceIteratorTest.php', 'Psr\\Cache\\CacheException' => __DIR__ . '/..' . '/psr/cache/src/CacheException.php', 'Psr\\Cache\\CacheItemInterface' => __DIR__ . '/..' . '/psr/cache/src/CacheItemInterface.php', 'Psr\\Cache\\CacheItemPoolInterface' => __DIR__ . '/..' . '/psr/cache/src/CacheItemPoolInterface.php', @@ -141,12 +109,20 @@ class ComposerStaticInitAdvancedContentFilterAddon 'Psr\\Container\\ContainerInterface' => __DIR__ . '/..' . '/psr/container/src/ContainerInterface.php', 'Psr\\Container\\NotFoundExceptionInterface' => __DIR__ . '/..' . '/psr/container/src/NotFoundExceptionInterface.php', 'Psr\\Http\\Message\\MessageInterface' => __DIR__ . '/..' . '/psr/http-message/src/MessageInterface.php', + 'Psr\\Http\\Message\\RequestFactoryInterface' => __DIR__ . '/..' . '/psr/http-factory/src/RequestFactoryInterface.php', 'Psr\\Http\\Message\\RequestInterface' => __DIR__ . '/..' . '/psr/http-message/src/RequestInterface.php', + 'Psr\\Http\\Message\\ResponseFactoryInterface' => __DIR__ . '/..' . '/psr/http-factory/src/ResponseFactoryInterface.php', 'Psr\\Http\\Message\\ResponseInterface' => __DIR__ . '/..' . '/psr/http-message/src/ResponseInterface.php', + 'Psr\\Http\\Message\\ServerRequestFactoryInterface' => __DIR__ . '/..' . '/psr/http-factory/src/ServerRequestFactoryInterface.php', 'Psr\\Http\\Message\\ServerRequestInterface' => __DIR__ . '/..' . '/psr/http-message/src/ServerRequestInterface.php', + 'Psr\\Http\\Message\\StreamFactoryInterface' => __DIR__ . '/..' . '/psr/http-factory/src/StreamFactoryInterface.php', 'Psr\\Http\\Message\\StreamInterface' => __DIR__ . '/..' . '/psr/http-message/src/StreamInterface.php', + 'Psr\\Http\\Message\\UploadedFileFactoryInterface' => __DIR__ . '/..' . '/psr/http-factory/src/UploadedFileFactoryInterface.php', 'Psr\\Http\\Message\\UploadedFileInterface' => __DIR__ . '/..' . '/psr/http-message/src/UploadedFileInterface.php', + 'Psr\\Http\\Message\\UriFactoryInterface' => __DIR__ . '/..' . '/psr/http-factory/src/UriFactoryInterface.php', 'Psr\\Http\\Message\\UriInterface' => __DIR__ . '/..' . '/psr/http-message/src/UriInterface.php', + 'Psr\\Http\\Server\\MiddlewareInterface' => __DIR__ . '/..' . '/psr/http-server-middleware/src/MiddlewareInterface.php', + 'Psr\\Http\\Server\\RequestHandlerInterface' => __DIR__ . '/..' . '/psr/http-server-handler/src/RequestHandlerInterface.php', 'Psr\\Log\\AbstractLogger' => __DIR__ . '/..' . '/psr/log/Psr/Log/AbstractLogger.php', 'Psr\\Log\\InvalidArgumentException' => __DIR__ . '/..' . '/psr/log/Psr/Log/InvalidArgumentException.php', 'Psr\\Log\\LogLevel' => __DIR__ . '/..' . '/psr/log/Psr/Log/LogLevel.php', @@ -155,57 +131,83 @@ class ComposerStaticInitAdvancedContentFilterAddon 'Psr\\Log\\LoggerInterface' => __DIR__ . '/..' . '/psr/log/Psr/Log/LoggerInterface.php', 'Psr\\Log\\LoggerTrait' => __DIR__ . '/..' . '/psr/log/Psr/Log/LoggerTrait.php', 'Psr\\Log\\NullLogger' => __DIR__ . '/..' . '/psr/log/Psr/Log/NullLogger.php', - 'Psr\\Log\\Test\\DummyTest' => __DIR__ . '/..' . '/psr/log/Psr/Log/Test/LoggerInterfaceTest.php', + 'Psr\\Log\\Test\\DummyTest' => __DIR__ . '/..' . '/psr/log/Psr/Log/Test/DummyTest.php', 'Psr\\Log\\Test\\LoggerInterfaceTest' => __DIR__ . '/..' . '/psr/log/Psr/Log/Test/LoggerInterfaceTest.php', + 'Psr\\Log\\Test\\TestLogger' => __DIR__ . '/..' . '/psr/log/Psr/Log/Test/TestLogger.php', 'Psr\\SimpleCache\\CacheException' => __DIR__ . '/..' . '/psr/simple-cache/src/CacheException.php', 'Psr\\SimpleCache\\CacheInterface' => __DIR__ . '/..' . '/psr/simple-cache/src/CacheInterface.php', 'Psr\\SimpleCache\\InvalidArgumentException' => __DIR__ . '/..' . '/psr/simple-cache/src/InvalidArgumentException.php', 'Slim\\App' => __DIR__ . '/..' . '/slim/slim/Slim/App.php', 'Slim\\CallableResolver' => __DIR__ . '/..' . '/slim/slim/Slim/CallableResolver.php', - 'Slim\\CallableResolverAwareTrait' => __DIR__ . '/..' . '/slim/slim/Slim/CallableResolverAwareTrait.php', - 'Slim\\Collection' => __DIR__ . '/..' . '/slim/slim/Slim/Collection.php', - 'Slim\\Container' => __DIR__ . '/..' . '/slim/slim/Slim/Container.php', - 'Slim\\DefaultServicesProvider' => __DIR__ . '/..' . '/slim/slim/Slim/DefaultServicesProvider.php', - 'Slim\\DeferredCallable' => __DIR__ . '/..' . '/slim/slim/Slim/DeferredCallable.php', - 'Slim\\Exception\\ContainerException' => __DIR__ . '/..' . '/slim/slim/Slim/Exception/ContainerException.php', - 'Slim\\Exception\\ContainerValueNotFoundException' => __DIR__ . '/..' . '/slim/slim/Slim/Exception/ContainerValueNotFoundException.php', - 'Slim\\Exception\\InvalidMethodException' => __DIR__ . '/..' . '/slim/slim/Slim/Exception/InvalidMethodException.php', - 'Slim\\Exception\\MethodNotAllowedException' => __DIR__ . '/..' . '/slim/slim/Slim/Exception/MethodNotAllowedException.php', - 'Slim\\Exception\\NotFoundException' => __DIR__ . '/..' . '/slim/slim/Slim/Exception/NotFoundException.php', - 'Slim\\Exception\\SlimException' => __DIR__ . '/..' . '/slim/slim/Slim/Exception/SlimException.php', - 'Slim\\Handlers\\AbstractError' => __DIR__ . '/..' . '/slim/slim/Slim/Handlers/AbstractError.php', - 'Slim\\Handlers\\AbstractHandler' => __DIR__ . '/..' . '/slim/slim/Slim/Handlers/AbstractHandler.php', - 'Slim\\Handlers\\Error' => __DIR__ . '/..' . '/slim/slim/Slim/Handlers/Error.php', - 'Slim\\Handlers\\NotAllowed' => __DIR__ . '/..' . '/slim/slim/Slim/Handlers/NotAllowed.php', - 'Slim\\Handlers\\NotFound' => __DIR__ . '/..' . '/slim/slim/Slim/Handlers/NotFound.php', - 'Slim\\Handlers\\PhpError' => __DIR__ . '/..' . '/slim/slim/Slim/Handlers/PhpError.php', + 'Slim\\Error\\AbstractErrorRenderer' => __DIR__ . '/..' . '/slim/slim/Slim/Error/AbstractErrorRenderer.php', + 'Slim\\Error\\Renderers\\HtmlErrorRenderer' => __DIR__ . '/..' . '/slim/slim/Slim/Error/Renderers/HtmlErrorRenderer.php', + 'Slim\\Error\\Renderers\\JsonErrorRenderer' => __DIR__ . '/..' . '/slim/slim/Slim/Error/Renderers/JsonErrorRenderer.php', + 'Slim\\Error\\Renderers\\PlainTextErrorRenderer' => __DIR__ . '/..' . '/slim/slim/Slim/Error/Renderers/PlainTextErrorRenderer.php', + 'Slim\\Error\\Renderers\\XmlErrorRenderer' => __DIR__ . '/..' . '/slim/slim/Slim/Error/Renderers/XmlErrorRenderer.php', + 'Slim\\Exception\\HttpBadRequestException' => __DIR__ . '/..' . '/slim/slim/Slim/Exception/HttpBadRequestException.php', + 'Slim\\Exception\\HttpException' => __DIR__ . '/..' . '/slim/slim/Slim/Exception/HttpException.php', + 'Slim\\Exception\\HttpForbiddenException' => __DIR__ . '/..' . '/slim/slim/Slim/Exception/HttpForbiddenException.php', + 'Slim\\Exception\\HttpGoneException' => __DIR__ . '/..' . '/slim/slim/Slim/Exception/HttpGoneException.php', + 'Slim\\Exception\\HttpInternalServerErrorException' => __DIR__ . '/..' . '/slim/slim/Slim/Exception/HttpInternalServerErrorException.php', + 'Slim\\Exception\\HttpMethodNotAllowedException' => __DIR__ . '/..' . '/slim/slim/Slim/Exception/HttpMethodNotAllowedException.php', + 'Slim\\Exception\\HttpNotFoundException' => __DIR__ . '/..' . '/slim/slim/Slim/Exception/HttpNotFoundException.php', + 'Slim\\Exception\\HttpNotImplementedException' => __DIR__ . '/..' . '/slim/slim/Slim/Exception/HttpNotImplementedException.php', + 'Slim\\Exception\\HttpSpecializedException' => __DIR__ . '/..' . '/slim/slim/Slim/Exception/HttpSpecializedException.php', + 'Slim\\Exception\\HttpUnauthorizedException' => __DIR__ . '/..' . '/slim/slim/Slim/Exception/HttpUnauthorizedException.php', + 'Slim\\Factory\\AppFactory' => __DIR__ . '/..' . '/slim/slim/Slim/Factory/AppFactory.php', + 'Slim\\Factory\\Psr17\\GuzzlePsr17Factory' => __DIR__ . '/..' . '/slim/slim/Slim/Factory/Psr17/GuzzlePsr17Factory.php', + 'Slim\\Factory\\Psr17\\HttpSoftPsr17Factory' => __DIR__ . '/..' . '/slim/slim/Slim/Factory/Psr17/HttpSoftPsr17Factory.php', + 'Slim\\Factory\\Psr17\\LaminasDiactorosPsr17Factory' => __DIR__ . '/..' . '/slim/slim/Slim/Factory/Psr17/LaminasDiactorosPsr17Factory.php', + 'Slim\\Factory\\Psr17\\NyholmPsr17Factory' => __DIR__ . '/..' . '/slim/slim/Slim/Factory/Psr17/NyholmPsr17Factory.php', + 'Slim\\Factory\\Psr17\\Psr17Factory' => __DIR__ . '/..' . '/slim/slim/Slim/Factory/Psr17/Psr17Factory.php', + 'Slim\\Factory\\Psr17\\Psr17FactoryProvider' => __DIR__ . '/..' . '/slim/slim/Slim/Factory/Psr17/Psr17FactoryProvider.php', + 'Slim\\Factory\\Psr17\\ServerRequestCreator' => __DIR__ . '/..' . '/slim/slim/Slim/Factory/Psr17/ServerRequestCreator.php', + 'Slim\\Factory\\Psr17\\SlimHttpPsr17Factory' => __DIR__ . '/..' . '/slim/slim/Slim/Factory/Psr17/SlimHttpPsr17Factory.php', + 'Slim\\Factory\\Psr17\\SlimHttpServerRequestCreator' => __DIR__ . '/..' . '/slim/slim/Slim/Factory/Psr17/SlimHttpServerRequestCreator.php', + 'Slim\\Factory\\Psr17\\SlimPsr17Factory' => __DIR__ . '/..' . '/slim/slim/Slim/Factory/Psr17/SlimPsr17Factory.php', + 'Slim\\Factory\\ServerRequestCreatorFactory' => __DIR__ . '/..' . '/slim/slim/Slim/Factory/ServerRequestCreatorFactory.php', + 'Slim\\Handlers\\ErrorHandler' => __DIR__ . '/..' . '/slim/slim/Slim/Handlers/ErrorHandler.php', + 'Slim\\Handlers\\Strategies\\RequestHandler' => __DIR__ . '/..' . '/slim/slim/Slim/Handlers/Strategies/RequestHandler.php', 'Slim\\Handlers\\Strategies\\RequestResponse' => __DIR__ . '/..' . '/slim/slim/Slim/Handlers/Strategies/RequestResponse.php', 'Slim\\Handlers\\Strategies\\RequestResponseArgs' => __DIR__ . '/..' . '/slim/slim/Slim/Handlers/Strategies/RequestResponseArgs.php', - 'Slim\\Http\\Body' => __DIR__ . '/..' . '/slim/slim/Slim/Http/Body.php', - 'Slim\\Http\\Cookies' => __DIR__ . '/..' . '/slim/slim/Slim/Http/Cookies.php', - 'Slim\\Http\\Environment' => __DIR__ . '/..' . '/slim/slim/Slim/Http/Environment.php', - 'Slim\\Http\\Headers' => __DIR__ . '/..' . '/slim/slim/Slim/Http/Headers.php', - 'Slim\\Http\\Message' => __DIR__ . '/..' . '/slim/slim/Slim/Http/Message.php', - 'Slim\\Http\\Request' => __DIR__ . '/..' . '/slim/slim/Slim/Http/Request.php', - 'Slim\\Http\\RequestBody' => __DIR__ . '/..' . '/slim/slim/Slim/Http/RequestBody.php', - 'Slim\\Http\\Response' => __DIR__ . '/..' . '/slim/slim/Slim/Http/Response.php', - 'Slim\\Http\\Stream' => __DIR__ . '/..' . '/slim/slim/Slim/Http/Stream.php', - 'Slim\\Http\\UploadedFile' => __DIR__ . '/..' . '/slim/slim/Slim/Http/UploadedFile.php', - 'Slim\\Http\\Uri' => __DIR__ . '/..' . '/slim/slim/Slim/Http/Uri.php', + 'Slim\\Handlers\\Strategies\\RequestResponseNamedArgs' => __DIR__ . '/..' . '/slim/slim/Slim/Handlers/Strategies/RequestResponseNamedArgs.php', + 'Slim\\Interfaces\\AdvancedCallableResolverInterface' => __DIR__ . '/..' . '/slim/slim/Slim/Interfaces/AdvancedCallableResolverInterface.php', 'Slim\\Interfaces\\CallableResolverInterface' => __DIR__ . '/..' . '/slim/slim/Slim/Interfaces/CallableResolverInterface.php', - 'Slim\\Interfaces\\CollectionInterface' => __DIR__ . '/..' . '/slim/slim/Slim/Interfaces/CollectionInterface.php', - 'Slim\\Interfaces\\Http\\CookiesInterface' => __DIR__ . '/..' . '/slim/slim/Slim/Interfaces/Http/CookiesInterface.php', - 'Slim\\Interfaces\\Http\\EnvironmentInterface' => __DIR__ . '/..' . '/slim/slim/Slim/Interfaces/Http/EnvironmentInterface.php', - 'Slim\\Interfaces\\Http\\HeadersInterface' => __DIR__ . '/..' . '/slim/slim/Slim/Interfaces/Http/HeadersInterface.php', + 'Slim\\Interfaces\\DispatcherInterface' => __DIR__ . '/..' . '/slim/slim/Slim/Interfaces/DispatcherInterface.php', + 'Slim\\Interfaces\\ErrorHandlerInterface' => __DIR__ . '/..' . '/slim/slim/Slim/Interfaces/ErrorHandlerInterface.php', + 'Slim\\Interfaces\\ErrorRendererInterface' => __DIR__ . '/..' . '/slim/slim/Slim/Interfaces/ErrorRendererInterface.php', 'Slim\\Interfaces\\InvocationStrategyInterface' => __DIR__ . '/..' . '/slim/slim/Slim/Interfaces/InvocationStrategyInterface.php', + 'Slim\\Interfaces\\MiddlewareDispatcherInterface' => __DIR__ . '/..' . '/slim/slim/Slim/Interfaces/MiddlewareDispatcherInterface.php', + 'Slim\\Interfaces\\Psr17FactoryInterface' => __DIR__ . '/..' . '/slim/slim/Slim/Interfaces/Psr17FactoryInterface.php', + 'Slim\\Interfaces\\Psr17FactoryProviderInterface' => __DIR__ . '/..' . '/slim/slim/Slim/Interfaces/Psr17FactoryProviderInterface.php', + 'Slim\\Interfaces\\RequestHandlerInvocationStrategyInterface' => __DIR__ . '/..' . '/slim/slim/Slim/Interfaces/RequestHandlerInvocationStrategyInterface.php', + 'Slim\\Interfaces\\RouteCollectorInterface' => __DIR__ . '/..' . '/slim/slim/Slim/Interfaces/RouteCollectorInterface.php', + 'Slim\\Interfaces\\RouteCollectorProxyInterface' => __DIR__ . '/..' . '/slim/slim/Slim/Interfaces/RouteCollectorProxyInterface.php', 'Slim\\Interfaces\\RouteGroupInterface' => __DIR__ . '/..' . '/slim/slim/Slim/Interfaces/RouteGroupInterface.php', 'Slim\\Interfaces\\RouteInterface' => __DIR__ . '/..' . '/slim/slim/Slim/Interfaces/RouteInterface.php', - 'Slim\\Interfaces\\RouterInterface' => __DIR__ . '/..' . '/slim/slim/Slim/Interfaces/RouterInterface.php', - 'Slim\\MiddlewareAwareTrait' => __DIR__ . '/..' . '/slim/slim/Slim/MiddlewareAwareTrait.php', - 'Slim\\Routable' => __DIR__ . '/..' . '/slim/slim/Slim/Routable.php', - 'Slim\\Route' => __DIR__ . '/..' . '/slim/slim/Slim/Route.php', - 'Slim\\RouteGroup' => __DIR__ . '/..' . '/slim/slim/Slim/RouteGroup.php', - 'Slim\\Router' => __DIR__ . '/..' . '/slim/slim/Slim/Router.php', + 'Slim\\Interfaces\\RouteParserInterface' => __DIR__ . '/..' . '/slim/slim/Slim/Interfaces/RouteParserInterface.php', + 'Slim\\Interfaces\\RouteResolverInterface' => __DIR__ . '/..' . '/slim/slim/Slim/Interfaces/RouteResolverInterface.php', + 'Slim\\Interfaces\\ServerRequestCreatorInterface' => __DIR__ . '/..' . '/slim/slim/Slim/Interfaces/ServerRequestCreatorInterface.php', + 'Slim\\Logger' => __DIR__ . '/..' . '/slim/slim/Slim/Logger.php', + 'Slim\\MiddlewareDispatcher' => __DIR__ . '/..' . '/slim/slim/Slim/MiddlewareDispatcher.php', + 'Slim\\Middleware\\BodyParsingMiddleware' => __DIR__ . '/..' . '/slim/slim/Slim/Middleware/BodyParsingMiddleware.php', + 'Slim\\Middleware\\ContentLengthMiddleware' => __DIR__ . '/..' . '/slim/slim/Slim/Middleware/ContentLengthMiddleware.php', + 'Slim\\Middleware\\ErrorMiddleware' => __DIR__ . '/..' . '/slim/slim/Slim/Middleware/ErrorMiddleware.php', + 'Slim\\Middleware\\MethodOverrideMiddleware' => __DIR__ . '/..' . '/slim/slim/Slim/Middleware/MethodOverrideMiddleware.php', + 'Slim\\Middleware\\OutputBufferingMiddleware' => __DIR__ . '/..' . '/slim/slim/Slim/Middleware/OutputBufferingMiddleware.php', + 'Slim\\Middleware\\RoutingMiddleware' => __DIR__ . '/..' . '/slim/slim/Slim/Middleware/RoutingMiddleware.php', + 'Slim\\ResponseEmitter' => __DIR__ . '/..' . '/slim/slim/Slim/ResponseEmitter.php', + 'Slim\\Routing\\Dispatcher' => __DIR__ . '/..' . '/slim/slim/Slim/Routing/Dispatcher.php', + 'Slim\\Routing\\FastRouteDispatcher' => __DIR__ . '/..' . '/slim/slim/Slim/Routing/FastRouteDispatcher.php', + 'Slim\\Routing\\Route' => __DIR__ . '/..' . '/slim/slim/Slim/Routing/Route.php', + 'Slim\\Routing\\RouteCollector' => __DIR__ . '/..' . '/slim/slim/Slim/Routing/RouteCollector.php', + 'Slim\\Routing\\RouteCollectorProxy' => __DIR__ . '/..' . '/slim/slim/Slim/Routing/RouteCollectorProxy.php', + 'Slim\\Routing\\RouteContext' => __DIR__ . '/..' . '/slim/slim/Slim/Routing/RouteContext.php', + 'Slim\\Routing\\RouteGroup' => __DIR__ . '/..' . '/slim/slim/Slim/Routing/RouteGroup.php', + 'Slim\\Routing\\RouteParser' => __DIR__ . '/..' . '/slim/slim/Slim/Routing/RouteParser.php', + 'Slim\\Routing\\RouteResolver' => __DIR__ . '/..' . '/slim/slim/Slim/Routing/RouteResolver.php', + 'Slim\\Routing\\RouteRunner' => __DIR__ . '/..' . '/slim/slim/Slim/Routing/RouteRunner.php', + 'Slim\\Routing\\RoutingResults' => __DIR__ . '/..' . '/slim/slim/Slim/Routing/RoutingResults.php', 'Symfony\\Component\\Cache\\Adapter\\AbstractAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/AbstractAdapter.php', 'Symfony\\Component\\Cache\\Adapter\\AdapterInterface' => __DIR__ . '/..' . '/symfony/cache/Adapter/AdapterInterface.php', 'Symfony\\Component\\Cache\\Adapter\\ApcuAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/ApcuAdapter.php', @@ -294,7 +296,6 @@ class ComposerStaticInitAdvancedContentFilterAddon return \Closure::bind(function () use ($loader) { $loader->prefixLengthsPsr4 = ComposerStaticInitAdvancedContentFilterAddon::$prefixLengthsPsr4; $loader->prefixDirsPsr4 = ComposerStaticInitAdvancedContentFilterAddon::$prefixDirsPsr4; - $loader->prefixesPsr0 = ComposerStaticInitAdvancedContentFilterAddon::$prefixesPsr0; $loader->classMap = ComposerStaticInitAdvancedContentFilterAddon::$classMap; }, null, ClassLoader::class); diff --git a/advancedcontentfilter/vendor/composer/installed.json b/advancedcontentfilter/vendor/composer/installed.json index 8e6b80dcf..1a84a8fdb 100644 --- a/advancedcontentfilter/vendor/composer/installed.json +++ b/advancedcontentfilter/vendor/composer/installed.json @@ -1,37 +1,4 @@ [ - { - "name": "container-interop/container-interop", - "version": "1.2.0", - "version_normalized": "1.2.0.0", - "source": { - "type": "git", - "url": "https://github.com/container-interop/container-interop.git", - "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/container-interop/container-interop/zipball/79cbf1341c22ec75643d841642dd5d6acd83bdb8", - "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8", - "shasum": "" - }, - "require": { - "psr/container": "^1.0" - }, - "time": "2017-02-14T19:40:03+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Interop\\Container\\": "src/Interop/Container/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Promoting the interoperability of container objects (DIC, SL, etc.)", - "homepage": "https://github.com/container-interop/container-interop" - }, { "name": "nikic/fast-route", "version": "v1.3.0", @@ -80,58 +47,6 @@ "routing" ] }, - { - "name": "pimple/pimple", - "version": "v3.2.3", - "version_normalized": "3.2.3.0", - "source": { - "type": "git", - "url": "https://github.com/silexphp/Pimple.git", - "reference": "9e403941ef9d65d20cba7d54e29fe906db42cf32" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/silexphp/Pimple/zipball/9e403941ef9d65d20cba7d54e29fe906db42cf32", - "reference": "9e403941ef9d65d20cba7d54e29fe906db42cf32", - "shasum": "" - }, - "require": { - "php": ">=5.3.0", - "psr/container": "^1.0" - }, - "require-dev": { - "symfony/phpunit-bridge": "^3.2" - }, - "time": "2018-01-21T07:42:36+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.2.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-0": { - "Pimple": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - } - ], - "description": "Pimple, a simple Dependency Injection Container", - "homepage": "http://pimple.sensiolabs.org", - "keywords": [ - "container", - "dependency injection" - ] - }, { "name": "psr/cache", "version": "1.0.1", @@ -182,27 +97,27 @@ }, { "name": "psr/container", - "version": "1.0.0", - "version_normalized": "1.0.0.0", + "version": "2.0.2", + "version_normalized": "2.0.2.0", "source": { "type": "git", "url": "https://github.com/php-fig/container.git", - "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", - "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=7.4.0" }, - "time": "2017-02-14T16:28:37+00:00", + "time": "2021-11-05T16:47:00+00:00", "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.0.x-dev" } }, "installation-source": "dist", @@ -218,7 +133,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "description": "Common Container Interface (PHP FIG PSR-11)", @@ -232,24 +147,25 @@ ] }, { - "name": "psr/http-message", - "version": "1.0.1", - "version_normalized": "1.0.1.0", + "name": "psr/http-factory", + "version": "1.0.2", + "version_normalized": "1.0.2.0", "source": { "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + "url": "https://github.com/php-fig/http-factory.git", + "reference": "e616d01114759c4c489f93b099585439f795fe35" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35", + "reference": "e616d01114759c4c489f93b099585439f795fe35", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=7.0.0", + "psr/http-message": "^1.0 || ^2.0" }, - "time": "2016-08-06T14:39:51+00:00", + "time": "2023-04-10T20:10:41+00:00", "type": "library", "extra": { "branch-alias": { @@ -266,6 +182,59 @@ "license": [ "MIT" ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ] + }, + { + "name": "psr/http-message", + "version": "1.1", + "version_normalized": "1.1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/cb6ce4845ce34a8ad9e68117c10ee90a29919eba", + "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "time": "2023-04-04T09:50:52+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], "authors": [ { "name": "PHP-FIG", @@ -284,28 +253,138 @@ ] }, { - "name": "psr/log", + "name": "psr/http-server-handler", "version": "1.0.2", "version_normalized": "1.0.2.0", "source": { "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" + "url": "https://github.com/php-fig/http-server-handler.git", + "reference": "84c4fb66179be4caaf8e97bd239203245302e7d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "url": "https://api.github.com/repos/php-fig/http-server-handler/zipball/84c4fb66179be4caaf8e97bd239203245302e7d4", + "reference": "84c4fb66179be4caaf8e97bd239203245302e7d4", + "shasum": "" + }, + "require": { + "php": ">=7.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "time": "2023-04-10T20:06:20+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Http\\Server\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP server-side request handler", + "keywords": [ + "handler", + "http", + "http-interop", + "psr", + "psr-15", + "psr-7", + "request", + "response", + "server" + ] + }, + { + "name": "psr/http-server-middleware", + "version": "1.0.2", + "version_normalized": "1.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-server-middleware.git", + "reference": "c1481f747daaa6a0782775cd6a8c26a1bf4a3829" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-server-middleware/zipball/c1481f747daaa6a0782775cd6a8c26a1bf4a3829", + "reference": "c1481f747daaa6a0782775cd6a8c26a1bf4a3829", + "shasum": "" + }, + "require": { + "php": ">=7.0", + "psr/http-message": "^1.0 || ^2.0", + "psr/http-server-handler": "^1.0" + }, + "time": "2023-04-11T06:14:47+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Http\\Server\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP server-side middleware", + "keywords": [ + "http", + "http-interop", + "middleware", + "psr", + "psr-15", + "psr-7", + "request", + "response" + ] + }, + { + "name": "psr/log", + "version": "1.1.4", + "version_normalized": "1.1.4.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11", "shasum": "" }, "require": { "php": ">=5.3.0" }, - "time": "2016-10-10T12:19:37+00:00", + "time": "2021-05-03T11:20:27+00:00", "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.1.x-dev" } }, "installation-source": "dist", @@ -321,7 +400,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "description": "Common interface for logging libraries", @@ -384,35 +463,54 @@ }, { "name": "slim/slim", - "version": "3.9.2", - "version_normalized": "3.9.2.0", + "version": "4.12.0", + "version_normalized": "4.12.0.0", "source": { "type": "git", "url": "https://github.com/slimphp/Slim.git", - "reference": "4086d0106cf5a7135c69fce4161fe355a8feb118" + "reference": "e9e99c2b24398b967841c6c4c3048622cc7e2b18" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/slimphp/Slim/zipball/4086d0106cf5a7135c69fce4161fe355a8feb118", - "reference": "4086d0106cf5a7135c69fce4161fe355a8feb118", + "url": "https://api.github.com/repos/slimphp/Slim/zipball/e9e99c2b24398b967841c6c4c3048622cc7e2b18", + "reference": "e9e99c2b24398b967841c6c4c3048622cc7e2b18", "shasum": "" }, "require": { - "container-interop/container-interop": "^1.2", - "nikic/fast-route": "^1.0", - "php": ">=5.5.0", - "pimple/pimple": "^3.0", - "psr/container": "^1.0", - "psr/http-message": "^1.0" - }, - "provide": { - "psr/http-message-implementation": "1.0" + "ext-json": "*", + "nikic/fast-route": "^1.3", + "php": "^7.4 || ^8.0", + "psr/container": "^1.0 || ^2.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1", + "psr/http-server-handler": "^1.0", + "psr/http-server-middleware": "^1.0", + "psr/log": "^1.1 || ^2.0 || ^3.0" }, "require-dev": { - "phpunit/phpunit": "^4.0", - "squizlabs/php_codesniffer": "^2.5" + "adriansuter/php-autoload-override": "^1.4", + "ext-simplexml": "*", + "guzzlehttp/psr7": "^2.5", + "httpsoft/http-message": "^1.1", + "httpsoft/http-server-request": "^1.1", + "laminas/laminas-diactoros": "^2.17", + "nyholm/psr7": "^1.8", + "nyholm/psr7-server": "^1.0", + "phpspec/prophecy": "^1.17", + "phpspec/prophecy-phpunit": "^2.0", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^9.6", + "slim/http": "^1.3", + "slim/psr7": "^1.6", + "squizlabs/php_codesniffer": "^3.7" }, - "time": "2017-11-26T19:13:09+00:00", + "suggest": { + "ext-simplexml": "Needed to support XML format in BodyParsingMiddleware", + "ext-xml": "Needed to support XML format in BodyParsingMiddleware", + "php-di/php-di": "PHP-DI is the recommended container library to be used with Slim", + "slim/psr7": "Slim PSR-7 implementation. See https://www.slimframework.com/docs/v4/start/installation.html for more information." + }, + "time": "2023-07-23T04:54:29+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -425,49 +523,64 @@ "MIT" ], "authors": [ - { - "name": "Rob Allen", - "email": "rob@akrabat.com", - "homepage": "http://akrabat.com" - }, { "name": "Josh Lockhart", "email": "hello@joshlockhart.com", "homepage": "https://joshlockhart.com" }, - { - "name": "Gabriel Manricks", - "email": "gmanricks@me.com", - "homepage": "http://gabrielmanricks.com" - }, { "name": "Andrew Smith", "email": "a.smith@silentworks.co.uk", "homepage": "http://silentworks.co.uk" + }, + { + "name": "Rob Allen", + "email": "rob@akrabat.com", + "homepage": "http://akrabat.com" + }, + { + "name": "Pierre Berube", + "email": "pierre@lgse.com", + "homepage": "http://www.lgse.com" + }, + { + "name": "Gabriel Manricks", + "email": "gmanricks@me.com", + "homepage": "http://gabrielmanricks.com" } ], "description": "Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs", - "homepage": "https://slimframework.com", + "homepage": "https://www.slimframework.com", "keywords": [ "api", "framework", "micro", "router" + ], + "funding": [ + { + "url": "https://opencollective.com/slimphp", + "type": "open_collective" + }, + { + "url": "https://tidelift.com/funding/github/packagist/slim/slim", + "type": "tidelift" + } ] }, { "name": "symfony/cache", - "version": "v3.4.8", - "version_normalized": "3.4.8.0", + "version": "v3.4.47", + "version_normalized": "3.4.47.0", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "13255ddd056e49f3154747943f8ee175d555d394" + "reference": "a7a14c4832760bd1fbd31be2859ffedc9b6ff813" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/13255ddd056e49f3154747943f8ee175d555d394", - "reference": "13255ddd056e49f3154747943f8ee175d555d394", + "url": "https://api.github.com/repos/symfony/cache/zipball/a7a14c4832760bd1fbd31be2859ffedc9b6ff813", + "reference": "a7a14c4832760bd1fbd31be2859ffedc9b6ff813", "shasum": "" }, "require": { @@ -486,17 +599,12 @@ }, "require-dev": { "cache/integration-tests": "dev-master", - "doctrine/cache": "~1.6", - "doctrine/dbal": "~2.4", - "predis/predis": "~1.0" + "doctrine/cache": "^1.6", + "doctrine/dbal": "^2.4|^3.0", + "predis/predis": "^1.0" }, - "time": "2018-04-02T14:35:16+00:00", + "time": "2020-10-24T10:57:07+00:00", "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, "installation-source": "dist", "autoload": { "psr-4": { @@ -525,34 +633,44 @@ "keywords": [ "caching", "psr6" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } ] }, { "name": "symfony/expression-language", - "version": "v3.4.8", - "version_normalized": "3.4.8.0", + "version": "v3.4.47", + "version_normalized": "3.4.47.0", "source": { "type": "git", "url": "https://github.com/symfony/expression-language.git", - "reference": "867e4d1f5d4e52435a8ffff6b24fd6a801582241" + "reference": "de38e66398fca1fcb9c48e80279910e6889cb28f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/expression-language/zipball/867e4d1f5d4e52435a8ffff6b24fd6a801582241", - "reference": "867e4d1f5d4e52435a8ffff6b24fd6a801582241", + "url": "https://api.github.com/repos/symfony/expression-language/zipball/de38e66398fca1fcb9c48e80279910e6889cb28f", + "reference": "de38e66398fca1fcb9c48e80279910e6889cb28f", "shasum": "" }, "require": { "php": "^5.5.9|>=7.0.8", - "symfony/cache": "~3.1|~4.0" + "symfony/cache": "~3.1|~4.0", + "symfony/polyfill-php70": "~1.6" }, - "time": "2018-01-03T07:37:34+00:00", + "time": "2020-10-24T10:57:07+00:00", "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, "installation-source": "dist", "autoload": { "psr-4": { @@ -577,41 +695,59 @@ } ], "description": "Symfony ExpressionLanguage Component", - "homepage": "https://symfony.com" + "homepage": "https://symfony.com", + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ] }, { "name": "symfony/polyfill-apcu", - "version": "v1.7.0", - "version_normalized": "1.7.0.0", + "version": "v1.28.0", + "version_normalized": "1.28.0.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-apcu.git", - "reference": "e8ae2136ddb53dea314df56fcd88e318ab936c00" + "reference": "c6c2c0f5f4cb0b100c5dfea807ef5cd27bbe9899" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-apcu/zipball/e8ae2136ddb53dea314df56fcd88e318ab936c00", - "reference": "e8ae2136ddb53dea314df56fcd88e318ab936c00", + "url": "https://api.github.com/repos/symfony/polyfill-apcu/zipball/c6c2c0f5f4cb0b100c5dfea807ef5cd27bbe9899", + "reference": "c6c2c0f5f4cb0b100c5dfea807ef5cd27bbe9899", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=7.1" }, - "time": "2018-01-30T19:27:44+00:00", + "time": "2023-01-26T09:26:14+00:00", "type": "library", "extra": { "branch-alias": { - "dev-master": "1.7-dev" + "dev-main": "1.28-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } }, "installation-source": "dist", "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Apcu\\": "" - }, "files": [ "bootstrap.php" - ] + ], + "psr-4": { + "Symfony\\Polyfill\\Apcu\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -635,6 +771,86 @@ "polyfill", "portable", "shim" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ] + }, + { + "name": "symfony/polyfill-php70", + "version": "v1.20.0", + "version_normalized": "1.20.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php70.git", + "reference": "5f03a781d984aae42cebd18e7912fa80f02ee644" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/5f03a781d984aae42cebd18e7912fa80f02ee644", + "reference": "5f03a781d984aae42cebd18e7912fa80f02ee644", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "time": "2020-10-23T14:02:19+00:00", + "type": "metapackage", + "extra": { + "branch-alias": { + "dev-main": "1.20-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } ] } ] diff --git a/advancedcontentfilter/vendor/container-interop/container-interop/.gitignore b/advancedcontentfilter/vendor/container-interop/container-interop/.gitignore deleted file mode 100644 index b2395aa05..000000000 --- a/advancedcontentfilter/vendor/container-interop/container-interop/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -composer.lock -composer.phar -/vendor/ diff --git a/advancedcontentfilter/vendor/container-interop/container-interop/LICENSE b/advancedcontentfilter/vendor/container-interop/container-interop/LICENSE deleted file mode 100644 index 7671d9020..000000000 --- a/advancedcontentfilter/vendor/container-interop/container-interop/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013 container-interop - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/advancedcontentfilter/vendor/container-interop/container-interop/README.md b/advancedcontentfilter/vendor/container-interop/container-interop/README.md deleted file mode 100644 index cdd7a44c8..000000000 --- a/advancedcontentfilter/vendor/container-interop/container-interop/README.md +++ /dev/null @@ -1,148 +0,0 @@ -# Container Interoperability - -[![Latest Stable Version](https://poser.pugx.org/container-interop/container-interop/v/stable.png)](https://packagist.org/packages/container-interop/container-interop) -[![Total Downloads](https://poser.pugx.org/container-interop/container-interop/downloads.svg)](https://packagist.org/packages/container-interop/container-interop) - -## Deprecation warning! - -Starting Feb. 13th 2017, container-interop is officially deprecated in favor of [PSR-11](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-11-container.md). -Container-interop has been the test-bed of PSR-11. From v1.2, container-interop directly extends PSR-11 interfaces. -Therefore, all containers implementing container-interop are now *de-facto* compatible with PSR-11. - -- Projects implementing container-interop interfaces are encouraged to directly implement PSR-11 interfaces instead. -- Projects consuming container-interop interfaces are very strongly encouraged to directly type-hint on PSR-11 interfaces, in order to be compatible with PSR-11 containers that are not compatible with container-interop. - -Regarding the delegate lookup feature, that is present in container-interop and not in PSR-11, the feature is actually a design pattern. It is therefore not deprecated. Documentation regarding this design pattern will be migrated from this repository into a separate website in the future. - -## About - -*container-interop* tries to identify and standardize features in *container* objects (service locators, -dependency injection containers, etc.) to achieve interoperability. - -Through discussions and trials, we try to create a standard, made of common interfaces but also recommendations. - -If PHP projects that provide container implementations begin to adopt these common standards, then PHP -applications and projects that use containers can depend on the common interfaces instead of specific -implementations. This facilitates a high-level of interoperability and flexibility that allows users to consume -*any* container implementation that can be adapted to these interfaces. - -The work done in this project is not officially endorsed by the [PHP-FIG](http://www.php-fig.org/), but it is being -worked on by members of PHP-FIG and other good developers. We adhere to the spirit and ideals of PHP-FIG, and hope -this project will pave the way for one or more future PSRs. - - -## Installation - -You can install this package through Composer: - -```json -composer require container-interop/container-interop -``` - -The packages adheres to the [SemVer](http://semver.org/) specification, and there will be full backward compatibility -between minor versions. - -## Standards - -### Available - -- [`ContainerInterface`](src/Interop/Container/ContainerInterface.php). -[Description](docs/ContainerInterface.md) [Meta Document](docs/ContainerInterface-meta.md). -Describes the interface of a container that exposes methods to read its entries. -- [*Delegate lookup feature*](docs/Delegate-lookup.md). -[Meta Document](docs/Delegate-lookup-meta.md). -Describes the ability for a container to delegate the lookup of its dependencies to a third-party container. This -feature lets several containers work together in a single application. - -### Proposed - -View open [request for comments](https://github.com/container-interop/container-interop/labels/RFC) - -## Compatible projects - -### Projects implementing `ContainerInterface` - -- [Acclimate](https://github.com/jeremeamia/acclimate-container): Adapters for - Aura.Di, Laravel, Nette DI, Pimple, Symfony DI, ZF2 Service manager, ZF2 - Dependency injection and any container using `ArrayAccess` -- [Aura.Di](https://github.com/auraphp/Aura.Di) -- [auryn-container-interop](https://github.com/elazar/auryn-container-interop) -- [Burlap](https://github.com/codeeverything/burlap) -- [Chernozem](https://github.com/pyrsmk/Chernozem) -- [Data Manager](https://github.com/chrismichaels84/data-manager) -- [Disco](https://github.com/bitexpert/disco) -- [InDI](https://github.com/idealogica/indi) -- [League/Container](http://container.thephpleague.com/) -- [Mouf](http://mouf-php.com) -- [Njasm Container](https://github.com/njasm/container) -- [PHP-DI](http://php-di.org) -- [Picotainer](https://github.com/thecodingmachine/picotainer) -- [PimpleInterop](https://github.com/moufmouf/pimple-interop) -- [Pimple3-ContainerInterop](https://github.com/Sam-Burns/pimple3-containerinterop) (using Pimple v3) -- [SitePoint Container](https://github.com/sitepoint/Container) -- [Thruster Container](https://github.com/ThrusterIO/container) (PHP7 only) -- [Ultra-Lite Container](https://github.com/ultra-lite/container) -- [Unbox](https://github.com/mindplay-dk/unbox) -- [XStatic](https://github.com/jeremeamia/xstatic) -- [Zend\ServiceManager](https://github.com/zendframework/zend-servicemanager) -- [Zit](https://github.com/inxilpro/Zit) - -### Projects implementing the *delegate lookup* feature - -- [Aura.Di](https://github.com/auraphp/Aura.Di) -- [Burlap](https://github.com/codeeverything/burlap) -- [Chernozem](https://github.com/pyrsmk/Chernozem) -- [InDI](https://github.com/idealogica/indi) -- [League/Container](http://container.thephpleague.com/) -- [Mouf](http://mouf-php.com) -- [Picotainer](https://github.com/thecodingmachine/picotainer) -- [PHP-DI](http://php-di.org) -- [PimpleInterop](https://github.com/moufmouf/pimple-interop) -- [Ultra-Lite Container](https://github.com/ultra-lite/container) - -### Middlewares implementing `ContainerInterface` - -- [Alias-Container](https://github.com/thecodingmachine/alias-container): add - aliases support to any container -- [Prefixer-Container](https://github.com/thecodingmachine/prefixer-container): - dynamically prefix identifiers -- [Lazy-Container](https://github.com/snapshotpl/lazy-container): lazy services - -### Projects using `ContainerInterface` - -The list below contains only a sample of all the projects consuming `ContainerInterface`. For a more complete list have a look [here](http://packanalyst.com/class?q=Interop%5CContainer%5CContainerInterface). - -| | Downloads | -| --- | --- | -| [Adroit](https://github.com/bitexpert/adroit) | ![](https://img.shields.io/packagist/dt/bitexpert/adroit.svg) | -| [Behat](https://github.com/Behat/Behat/pull/974) | ![](https://img.shields.io/packagist/dt/behat/behat.svg) | -| [blast-facades](https://github.com/phpthinktank/blast-facades): Minimize complexity and represent dependencies as facades. | ![](https://img.shields.io/packagist/dt/blast/facades.svg) | -| [interop.silex.di](https://github.com/thecodingmachine/interop.silex.di): an extension to [Silex](http://silex.sensiolabs.org/) that adds support for any *container-interop* compatible container | ![](https://img.shields.io/packagist/dt/mouf/interop.silex.di.svg) | -| [mindplay/walkway](https://github.com/mindplay-dk/walkway): a modular request router | ![](https://img.shields.io/packagist/dt/mindplay/walkway.svg) | -| [mindplay/middleman](https://github.com/mindplay-dk/middleman): minimalist PSR-7 middleware dispatcher | ![](https://img.shields.io/packagist/dt/mindplay/middleman.svg) | -| [PHP-DI/Invoker](https://github.com/PHP-DI/Invoker): extensible and configurable invoker/dispatcher | ![](https://img.shields.io/packagist/dt/php-di/invoker.svg) | -| [Prophiler](https://github.com/fabfuel/prophiler) | ![](https://img.shields.io/packagist/dt/fabfuel/prophiler.svg) | -| [Silly](https://github.com/mnapoli/silly): CLI micro-framework | ![](https://img.shields.io/packagist/dt/mnapoli/silly.svg) | -| [Slim v3](https://github.com/slimphp/Slim) | ![](https://img.shields.io/packagist/dt/slim/slim.svg) | -| [Splash](http://mouf-php.com/packages/mouf/mvc.splash-common/version/8.0-dev/README.md) | ![](https://img.shields.io/packagist/dt/mouf/mvc.splash-common.svg) | -| [Woohoo Labs. Harmony](https://github.com/woohoolabs/harmony): a flexible micro-framework | ![](https://img.shields.io/packagist/dt/woohoolabs/harmony.svg) | -| [zend-expressive](https://github.com/zendframework/zend-expressive) | ![](https://img.shields.io/packagist/dt/zendframework/zend-expressive.svg) | - - -## Workflow - -Everyone is welcome to join and contribute. - -The general workflow looks like this: - -1. Someone opens a discussion (GitHub issue) to suggest an interface -1. Feedback is gathered -1. The interface is added to a development branch -1. We release alpha versions so that the interface can be experimented with -1. Discussions and edits ensue until the interface is deemed stable by a general consensus -1. A new minor version of the package is released - -We try to not break BC by creating new interfaces instead of editing existing ones. - -While we currently work on interfaces, we are open to anything that might help towards interoperability, may that -be code, best practices, etc. diff --git a/advancedcontentfilter/vendor/container-interop/container-interop/composer.json b/advancedcontentfilter/vendor/container-interop/container-interop/composer.json deleted file mode 100644 index 855f76672..000000000 --- a/advancedcontentfilter/vendor/container-interop/container-interop/composer.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "name": "container-interop/container-interop", - "type": "library", - "description": "Promoting the interoperability of container objects (DIC, SL, etc.)", - "homepage": "https://github.com/container-interop/container-interop", - "license": "MIT", - "autoload": { - "psr-4": { - "Interop\\Container\\": "src/Interop/Container/" - } - }, - "require": { - "psr/container": "^1.0" - } -} diff --git a/advancedcontentfilter/vendor/container-interop/container-interop/docs/ContainerInterface-meta.md b/advancedcontentfilter/vendor/container-interop/container-interop/docs/ContainerInterface-meta.md deleted file mode 100644 index 59f3d5599..000000000 --- a/advancedcontentfilter/vendor/container-interop/container-interop/docs/ContainerInterface-meta.md +++ /dev/null @@ -1,114 +0,0 @@ -# ContainerInterface Meta Document - -## Introduction - -This document describes the process and discussions that lead to the `ContainerInterface`. -Its goal is to explain the reasons behind each decision. - -## Goal - -The goal set by `ContainerInterface` is to standardize how frameworks and libraries make use of a -container to obtain objects and parameters. - -By standardizing such a behavior, frameworks and libraries using the `ContainerInterface` -could work with any compatible container. -That would allow end users to choose their own container based on their own preferences. - -It is important to distinguish the two usages of a container: - -- configuring entries -- fetching entries - -Most of the time, those two sides are not used by the same party. -While it is often end users who tend to configure entries, it is generally the framework that fetch -entries to build the application. - -This is why this interface focuses only on how entries can be fetched from a container. - -## Interface name - -The interface name has been thoroughly discussed and was decided by a vote. - -The list of options considered with their respective votes are: - -- `ContainerInterface`: +8 -- `ProviderInterface`: +2 -- `LocatorInterface`: 0 -- `ReadableContainerInterface`: -5 -- `ServiceLocatorInterface`: -6 -- `ObjectFactory`: -6 -- `ObjectStore`: -8 -- `ConsumerInterface`: -9 - -[Full results of the vote](https://github.com/container-interop/container-interop/wiki/%231-interface-name:-Vote) - -The complete discussion can be read in [the issue #1](https://github.com/container-interop/container-interop/issues/1). - -## Interface methods - -The choice of which methods the interface would contain was made after a statistical analysis of existing containers. -The results of this analysis are available [in this document](https://gist.github.com/mnapoli/6159681). - -The summary of the analysis showed that: - -- all containers offer a method to get an entry by its id -- a large majority name such method `get()` -- for all containers, the `get()` method has 1 mandatory parameter of type string -- some containers have an optional additional argument for `get()`, but it doesn't have the same purpose between containers -- a large majority of the containers offer a method to test if it can return an entry by its id -- a majority name such method `has()` -- for all containers offering `has()`, the method has exactly 1 parameter of type string -- a large majority of the containers throw an exception rather than returning null when an entry is not found in `get()` -- a large majority of the containers don't implement `ArrayAccess` - -The question of whether to include methods to define entries has been discussed in -[issue #1](https://github.com/container-interop/container-interop/issues/1). -It has been judged that such methods do not belong in the interface described here because it is out of its scope -(see the "Goal" section). - -As a result, the `ContainerInterface` contains two methods: - -- `get()`, returning anything, with one mandatory string parameter. Should throw an exception if the entry is not found. -- `has()`, returning a boolean, with one mandatory string parameter. - -### Number of parameters in `get()` method - -While `ContainerInterface` only defines one mandatory parameter in `get()`, it is not incompatible with -existing containers that have additional optional parameters. PHP allows an implementation to offer more parameters -as long as they are optional, because the implementation *does* satisfy the interface. - -This issue has been discussed in [issue #6](https://github.com/container-interop/container-interop/issues/6). - -### Type of the `$id` parameter - -The type of the `$id` parameter in `get()` and `has()` has been discussed in -[issue #6](https://github.com/container-interop/container-interop/issues/6). -While `string` is used in all the containers that were analyzed, it was suggested that allowing -anything (such as objects) could allow containers to offer a more advanced query API. - -An example given was to use the container as an object builder. The `$id` parameter would then be an -object that would describe how to create an instance. - -The conclusion of the discussion was that this was beyond the scope of getting entries from a container without -knowing how the container provided them, and it was more fit for a factory. - -## Contributors - -Are listed here all people that contributed in the discussions or votes, by alphabetical order: - -- [Amy Stephen](https://github.com/AmyStephen) -- [David Négrier](https://github.com/moufmouf) -- [Don Gilbert](https://github.com/dongilbert) -- [Jason Judge](https://github.com/judgej) -- [Jeremy Lindblom](https://github.com/jeremeamia) -- [Marco Pivetta](https://github.com/Ocramius) -- [Matthieu Napoli](https://github.com/mnapoli) -- [Paul M. Jones](https://github.com/pmjones) -- [Stephan Hochdörfer](https://github.com/shochdoerfer) -- [Taylor Otwell](https://github.com/taylorotwell) - -## Relevant links - -- [`ContainerInterface.php`](https://github.com/container-interop/container-interop/blob/master/src/Interop/Container/ContainerInterface.php) -- [List of all issues](https://github.com/container-interop/container-interop/issues?labels=ContainerInterface&milestone=&page=1&state=closed) -- [Vote for the interface name](https://github.com/container-interop/container-interop/wiki/%231-interface-name:-Vote) diff --git a/advancedcontentfilter/vendor/container-interop/container-interop/docs/ContainerInterface.md b/advancedcontentfilter/vendor/container-interop/container-interop/docs/ContainerInterface.md deleted file mode 100644 index bda973d6f..000000000 --- a/advancedcontentfilter/vendor/container-interop/container-interop/docs/ContainerInterface.md +++ /dev/null @@ -1,158 +0,0 @@ -Container interface -=================== - -This document describes a common interface for dependency injection containers. - -The goal set by `ContainerInterface` is to standardize how frameworks and libraries make use of a -container to obtain objects and parameters (called *entries* in the rest of this document). - -The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", -"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be -interpreted as described in [RFC 2119][]. - -The word `implementor` in this document is to be interpreted as someone -implementing the `ContainerInterface` in a dependency injection-related library or framework. -Users of dependency injections containers (DIC) are referred to as `user`. - -[RFC 2119]: http://tools.ietf.org/html/rfc2119 - -1. Specification ------------------ - -### 1.1 Basics - -- The `Interop\Container\ContainerInterface` exposes two methods : `get` and `has`. - -- `get` takes one mandatory parameter: an entry identifier. It MUST be a string. - A call to `get` can return anything (a *mixed* value), or throws an exception if the identifier - is not known to the container. Two successive calls to `get` with the same - identifier SHOULD return the same value. However, depending on the `implementor` - design and/or `user` configuration, different values might be returned, so - `user` SHOULD NOT rely on getting the same value on 2 successive calls. - While `ContainerInterface` only defines one mandatory parameter in `get()`, implementations - MAY accept additional optional parameters. - -- `has` takes one unique parameter: an entry identifier. It MUST return `true` - if an entry identifier is known to the container and `false` if it is not. - `has($id)` returning true does not mean that `get($id)` will not throw an exception. - It does however mean that `get($id)` will not throw a `NotFoundException`. - -### 1.2 Exceptions - -Exceptions directly thrown by the container MUST implement the -[`Interop\Container\Exception\ContainerException`](../src/Interop/Container/Exception/ContainerException.php). - -A call to the `get` method with a non-existing id SHOULD throw a -[`Interop\Container\Exception\NotFoundException`](../src/Interop/Container/Exception/NotFoundException.php). - -### 1.3 Additional features - -This section describes additional features that MAY be added to a container. Containers are not -required to implement these features to respect the ContainerInterface. - -#### 1.3.1 Delegate lookup feature - -The goal of the *delegate lookup* feature is to allow several containers to share entries. -Containers implementing this feature can perform dependency lookups in other containers. - -Containers implementing this feature will offer a greater lever of interoperability -with other containers. Implementation of this feature is therefore RECOMMENDED. - -A container implementing this feature: - -- MUST implement the `ContainerInterface` -- MUST provide a way to register a delegate container (using a constructor parameter, or a setter, - or any possible way). The delegate container MUST implement the `ContainerInterface`. - -When a container is configured to use a delegate container for dependencies: - -- Calls to the `get` method should only return an entry if the entry is part of the container. - If the entry is not part of the container, an exception should be thrown - (as requested by the `ContainerInterface`). -- Calls to the `has` method should only return `true` if the entry is part of the container. - If the entry is not part of the container, `false` should be returned. -- If the fetched entry has dependencies, **instead** of performing - the dependency lookup in the container, the lookup is performed on the *delegate container*. - -Important! By default, the lookup SHOULD be performed on the delegate container **only**, not on the container itself. - -It is however allowed for containers to provide exception cases for special entries, and a way to lookup -into the same container (or another container) instead of the delegate container. - -2. Package ----------- - -The interfaces and classes described as well as relevant exception are provided as part of the -[container-interop/container-interop](https://packagist.org/packages/container-interop/container-interop) package. - -3. `Interop\Container\ContainerInterface` ------------------------------------------ - -```php -setParentContainer($this); - } - } - ... - } -} - -``` - -**Cons:** - -Cons have been extensively discussed [here](https://github.com/container-interop/container-interop/pull/8#issuecomment-51721777). -Basically, forcing a setter into an interface is a bad idea. Setters are similar to constructor arguments, -and it's a bad idea to standardize a constructor: how the delegate container is configured into a container is an implementation detail. This outweights the benefits of the interface. - -### 4.4 Alternative: no exception case for delegate lookups - -Originally, the proposed wording for delegate lookup calls was: - -> Important! The lookup MUST be performed on the delegate container **only**, not on the container itself. - -This was later replaced by: - -> Important! By default, the lookup SHOULD be performed on the delegate container **only**, not on the container itself. -> -> It is however allowed for containers to provide exception cases for special entries, and a way to lookup -> into the same container (or another container) instead of the delegate container. - -Exception cases have been allowed to avoid breaking dependencies with some services that must be provided -by the container (on @njasm proposal). This was proposed here: https://github.com/container-interop/container-interop/pull/20#issuecomment-56597235 - -### 4.5 Alternative: having one of the containers act as the composite container - -In real-life scenarios, we usually have a big framework (Symfony 2, Zend Framework 2, etc...) and we want to -add another DI container to this container. Most of the time, the "big" framework will be responsible for -creating the controller's instances, using it's own DI container. Until *container-interop* is fully adopted, -the "big" framework will not be aware of the existence of a composite container that it should use instead -of its own container. - -For this real-life use cases, @mnapoli and @moufmouf proposed to extend the "big" framework's DI container -to make it act as a composite container. - -This has been discussed [here](https://github.com/container-interop/container-interop/pull/8#issuecomment-40367194) -and [here](http://mouf-php.com/container-interop-whats-next#solution4). - -This was implemented in Symfony 2 using: - -- [interop.symfony.di](https://github.com/thecodingmachine/interop.symfony.di/tree/v0.1.0) -- [framework interop](https://github.com/mnapoli/framework-interop/) - -This was implemented in Silex using: - -- [interop.silex.di](https://github.com/thecodingmachine/interop.silex.di) - -Having a container act as the composite container is not part of the delegate lookup standard because it is -simply a temporary design pattern used to make existing frameworks that do not support yet ContainerInterop -play nice with other DI containers. - - -5. Implementations ------------------- - -The following projects already implement the delegate lookup feature: - -- [Mouf](http://mouf-php.com), through the [`setDelegateLookupContainer` method](https://github.com/thecodingmachine/mouf/blob/2.0/src/Mouf/MoufManager.php#L2120) -- [PHP-DI](http://php-di.org/), through the [`$wrapperContainer` parameter of the constructor](https://github.com/mnapoli/PHP-DI/blob/master/src/DI/Container.php#L72) -- [pimple-interop](https://github.com/moufmouf/pimple-interop), through the [`$container` parameter of the constructor](https://github.com/moufmouf/pimple-interop/blob/master/src/Interop/Container/Pimple/PimpleInterop.php#L62) - -6. People ---------- - -Are listed here all people that contributed in the discussions, by alphabetical order: - -- [Alexandru Pătrănescu](https://github.com/drealecs) -- [Ben Peachey](https://github.com/potherca) -- [David Négrier](https://github.com/moufmouf) -- [Jeremy Lindblom](https://github.com/jeremeamia) -- [Marco Pivetta](https://github.com/Ocramius) -- [Matthieu Napoli](https://github.com/mnapoli) -- [Nelson J Morais](https://github.com/njasm) -- [Phil Sturgeon](https://github.com/philsturgeon) -- [Stephan Hochdörfer](https://github.com/shochdoerfer) - -7. Relevant Links ------------------ - -_**Note:** Order descending chronologically._ - -- [Pull request on the delegate lookup feature](https://github.com/container-interop/container-interop/pull/20) -- [Pull request on the interface idea](https://github.com/container-interop/container-interop/pull/8) -- [Original article exposing the delegate lookup idea along many others](http://mouf-php.com/container-interop-whats-next) - diff --git a/advancedcontentfilter/vendor/container-interop/container-interop/docs/Delegate-lookup.md b/advancedcontentfilter/vendor/container-interop/container-interop/docs/Delegate-lookup.md deleted file mode 100644 index f64a8f785..000000000 --- a/advancedcontentfilter/vendor/container-interop/container-interop/docs/Delegate-lookup.md +++ /dev/null @@ -1,60 +0,0 @@ -Delegate lookup feature -======================= - -This document describes a standard for dependency injection containers. - -The goal set by the *delegate lookup* feature is to allow several containers to share entries. -Containers implementing this feature can perform dependency lookups in other containers. - -Containers implementing this feature will offer a greater lever of interoperability -with other containers. Implementation of this feature is therefore RECOMMENDED. - -The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", -"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be -interpreted as described in [RFC 2119][]. - -The word `implementor` in this document is to be interpreted as someone -implementing the delegate lookup feature in a dependency injection-related library or framework. -Users of dependency injections containers (DIC) are referred to as `user`. - -[RFC 2119]: http://tools.ietf.org/html/rfc2119 - -1. Vocabulary -------------- - -In a dependency injection container, the container is used to fetch entries. -Entries can have dependencies on other entries. Usually, these other entries are fetched by the container. - -The *delegate lookup* feature is the ability for a container to fetch dependencies in -another container. In the rest of the document, the word "container" will reference the container -implemented by the implementor. The word "delegate container" will reference the container we are -fetching the dependencies from. - -2. Specification ----------------- - -A container implementing the *delegate lookup* feature: - -- MUST implement the [`ContainerInterface`](ContainerInterface.md) -- MUST provide a way to register a delegate container (using a constructor parameter, or a setter, - or any possible way). The delegate container MUST implement the [`ContainerInterface`](ContainerInterface.md). - -When a container is configured to use a delegate container for dependencies: - -- Calls to the `get` method should only return an entry if the entry is part of the container. - If the entry is not part of the container, an exception should be thrown - (as requested by the [`ContainerInterface`](ContainerInterface.md)). -- Calls to the `has` method should only return `true` if the entry is part of the container. - If the entry is not part of the container, `false` should be returned. -- If the fetched entry has dependencies, **instead** of performing - the dependency lookup in the container, the lookup is performed on the *delegate container*. - -Important: By default, the dependency lookups SHOULD be performed on the delegate container **only**, not on the container itself. - -It is however allowed for containers to provide exception cases for special entries, and a way to lookup -into the same container (or another container) instead of the delegate container. - -3. Package / Interface ----------------------- - -This feature is not tied to any code, interface or package. diff --git a/advancedcontentfilter/vendor/container-interop/container-interop/docs/images/interoperating_containers.png b/advancedcontentfilter/vendor/container-interop/container-interop/docs/images/interoperating_containers.png deleted file mode 100644 index 1d3fdd0ddbea28d77c08cfb65834ec11357be5fb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25738 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 lDg62tY5@ou6EsiaCMAN!E;xV!uGoVl#pK=> `php --ini | grep "Loaded Configuration" | sed -e "s|.*:\s*||"`; fi - -script: - - cd ext/pimple - - if [ "$PIMPLE_EXT" == "yes" ]; then yes n | make test | tee output ; grep -E 'Tests failed +. +0' output; fi - - if [ "$PIMPLE_EXT" == "yes" ]; then export SYMFONY_DEPRECATIONS_HELPER=weak; fi - - cd ../.. - - ./vendor/bin/simple-phpunit - -matrix: - include: - - php: hhvm - dist: trusty - env: PIMPLE_EXT=no - exclude: - - php: 7.0 - env: PIMPLE_EXT=yes - - php: 7.1 - env: PIMPLE_EXT=yes diff --git a/advancedcontentfilter/vendor/pimple/pimple/CHANGELOG b/advancedcontentfilter/vendor/pimple/pimple/CHANGELOG deleted file mode 100644 index ba56760c1..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/CHANGELOG +++ /dev/null @@ -1,59 +0,0 @@ -* 3.2.3 (2017-XX-XX) - - * n/a - -* 3.2.2 (2017-07-23) - - * reverted extending a protected closure throws an exception (deprecated it instead) - -* 3.2.1 (2017-07-17) - - * fixed PHP error - -* 3.2.0 (2017-07-17) - - * added a PSR-11 service locator - * added a PSR-11 wrapper - * added ServiceIterator - * fixed extending a protected closure (now throws InvalidServiceIdentifierException) - -* 3.1.0 (2017-07-03) - - * deprecated the C extension - * added support for PSR-11 exceptions - -* 3.0.2 (2015-09-11) - - * refactored the C extension - * minor non-significant changes - -* 3.0.1 (2015-07-30) - - * simplified some code - * fixed a segfault in the C extension - -* 3.0.0 (2014-07-24) - - * removed the Pimple class alias (use Pimple\Container instead) - -* 2.1.1 (2014-07-24) - - * fixed compiler warnings for the C extension - * fixed code when dealing with circular references - -* 2.1.0 (2014-06-24) - - * moved the Pimple to Pimple\Container (with a BC layer -- Pimple is now a - deprecated alias which will be removed in Pimple 3.0) - * added Pimple\ServiceProviderInterface (and Pimple::register()) - -* 2.0.0 (2014-02-10) - - * changed extend to automatically re-assign the extended service and keep it as shared or factory - (to keep BC, extend still returns the extended service) - * changed services to be shared by default (use factory() for factory - services) - -* 1.0.0 - - * initial version diff --git a/advancedcontentfilter/vendor/pimple/pimple/README.rst b/advancedcontentfilter/vendor/pimple/pimple/README.rst deleted file mode 100644 index a03b6d3a4..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/README.rst +++ /dev/null @@ -1,326 +0,0 @@ -Pimple -====== - -.. caution:: - - This is the documentation for Pimple 3.x. If you are using Pimple 1.x, read - the `Pimple 1.x documentation`_. Reading the Pimple 1.x code is also a good - way to learn more about how to create a simple Dependency Injection - Container (recent versions of Pimple are more focused on performance). - -Pimple is a small Dependency Injection Container for PHP. - -Installation ------------- - -Before using Pimple in your project, add it to your ``composer.json`` file: - -.. code-block:: bash - - $ ./composer.phar require pimple/pimple "^3.0" - -Usage ------ - -Creating a container is a matter of creating a ``Container`` instance: - -.. code-block:: php - - use Pimple\Container; - - $container = new Container(); - -As many other dependency injection containers, Pimple manages two different -kind of data: **services** and **parameters**. - -Defining Services -~~~~~~~~~~~~~~~~~ - -A service is an object that does something as part of a larger system. Examples -of services: a database connection, a templating engine, or a mailer. Almost -any **global** object can be a service. - -Services are defined by **anonymous functions** that return an instance of an -object: - -.. code-block:: php - - // define some services - $container['session_storage'] = function ($c) { - return new SessionStorage('SESSION_ID'); - }; - - $container['session'] = function ($c) { - return new Session($c['session_storage']); - }; - -Notice that the anonymous function has access to the current container -instance, allowing references to other services or parameters. - -As objects are only created when you get them, the order of the definitions -does not matter. - -Using the defined services is also very easy: - -.. code-block:: php - - // get the session object - $session = $container['session']; - - // the above call is roughly equivalent to the following code: - // $storage = new SessionStorage('SESSION_ID'); - // $session = new Session($storage); - -Defining Factory Services -~~~~~~~~~~~~~~~~~~~~~~~~~ - -By default, each time you get a service, Pimple returns the **same instance** -of it. If you want a different instance to be returned for all calls, wrap your -anonymous function with the ``factory()`` method - -.. code-block:: php - - $container['session'] = $container->factory(function ($c) { - return new Session($c['session_storage']); - }); - -Now, each call to ``$container['session']`` returns a new instance of the -session. - -Defining Parameters -~~~~~~~~~~~~~~~~~~~ - -Defining a parameter allows to ease the configuration of your container from -the outside and to store global values: - -.. code-block:: php - - // define some parameters - $container['cookie_name'] = 'SESSION_ID'; - $container['session_storage_class'] = 'SessionStorage'; - -If you change the ``session_storage`` service definition like below: - -.. code-block:: php - - $container['session_storage'] = function ($c) { - return new $c['session_storage_class']($c['cookie_name']); - }; - -You can now easily change the cookie name by overriding the -``cookie_name`` parameter instead of redefining the service -definition. - -Protecting Parameters -~~~~~~~~~~~~~~~~~~~~~ - -Because Pimple sees anonymous functions as service definitions, you need to -wrap anonymous functions with the ``protect()`` method to store them as -parameters: - -.. code-block:: php - - $container['random_func'] = $container->protect(function () { - return rand(); - }); - -Modifying Services after Definition -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -In some cases you may want to modify a service definition after it has been -defined. You can use the ``extend()`` method to define additional code to be -run on your service just after it is created: - -.. code-block:: php - - $container['session_storage'] = function ($c) { - return new $c['session_storage_class']($c['cookie_name']); - }; - - $container->extend('session_storage', function ($storage, $c) { - $storage->...(); - - return $storage; - }); - -The first argument is the name of the service to extend, the second a function -that gets access to the object instance and the container. - -Extending a Container -~~~~~~~~~~~~~~~~~~~~~ - -If you use the same libraries over and over, you might want to reuse some -services from one project to the next one; package your services into a -**provider** by implementing ``Pimple\ServiceProviderInterface``: - -.. code-block:: php - - use Pimple\Container; - - class FooProvider implements Pimple\ServiceProviderInterface - { - public function register(Container $pimple) - { - // register some services and parameters - // on $pimple - } - } - -Then, register the provider on a Container: - -.. code-block:: php - - $pimple->register(new FooProvider()); - -Fetching the Service Creation Function -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -When you access an object, Pimple automatically calls the anonymous function -that you defined, which creates the service object for you. If you want to get -raw access to this function, you can use the ``raw()`` method: - -.. code-block:: php - - $container['session'] = function ($c) { - return new Session($c['session_storage']); - }; - - $sessionFunction = $container->raw('session'); - -PSR-11 compatibility --------------------- - -For historical reasons, the ``Container`` class does not implement the PSR-11 -``ContainerInterface``. However, Pimple provides a helper class that will let -you decouple your code from the Pimple container class. - -The PSR-11 container class -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The ``Pimple\Psr11\Container`` class lets you access the content of an -underlying Pimple container using ``Psr\Container\ContainerInterface`` -methods: - -.. code-block:: php - - use Pimple\Container; - use Pimple\Psr11\Container as PsrContainer; - - $container = new Container(); - $container['service'] = function ($c) { - return new Service(); - }; - $psr11 = new PsrContainer($container); - - $controller = function (PsrContainer $container) { - $service = $container->get('service'); - }; - $controller($psr11); - -Using the PSR-11 ServiceLocator -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Sometimes, a service needs access to several other services without being sure -that all of them will actually be used. In those cases, you may want the -instantiation of the services to be lazy. - -The traditional solution is to inject the entire service container to get only -the services really needed. However, this is not recommended because it gives -services a too broad access to the rest of the application and it hides their -actual dependencies. - -The ``ServiceLocator`` is intended to solve this problem by giving access to a -set of predefined services while instantiating them only when actually needed. - -It also allows you to make your services available under a different name than -the one used to register them. For instance, you may want to use an object -that expects an instance of ``EventDispatcherInterface`` to be available under -the name ``event_dispatcher`` while your event dispatcher has been -registered under the name ``dispatcher``: - -.. code-block:: php - - use Monolog\Logger; - use Pimple\Psr11\ServiceLocator; - use Psr\Container\ContainerInterface; - use Symfony\Component\EventDispatcher\EventDispatcher; - - class MyService - { - /** - * "logger" must be an instance of Psr\Log\LoggerInterface - * "event_dispatcher" must be an instance of Symfony\Component\EventDispatcher\EventDispatcherInterface - */ - private $services; - - public function __construct(ContainerInterface $services) - { - $this->services = $services; - } - } - - $container['logger'] = function ($c) { - return new Monolog\Logger(); - }; - $container['dispatcher'] = function () { - return new EventDispatcher(); - }; - - $container['service'] = function ($c) { - $locator = new ServiceLocator($c, array('logger', 'event_dispatcher' => 'dispatcher')); - - return new MyService($locator); - }; - -Referencing a Collection of Services Lazily -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Passing a collection of services instances in an array may prove inefficient -if the class that consumes the collection only needs to iterate over it at a -later stage, when one of its method is called. It can also lead to problems -if there is a circular dependency between one of the services stored in the -collection and the class that consumes it. - -The ``ServiceIterator`` class helps you solve these issues. It receives a -list of service names during instantiation and will retrieve the services -when iterated over: - -.. code-block:: php - - use Pimple\Container; - use Pimple\ServiceIterator; - - class AuthorizationService - { - private $voters; - - public function __construct($voters) - { - $this->voters = $voters; - } - - public function canAccess($resource) - { - foreach ($this->voters as $voter) { - if (true === $voter->canAccess($resource) { - return true; - } - } - - return false; - } - } - - $container = new Container(); - - $container['voter1'] = function ($c) { - return new SomeVoter(); - } - $container['voter2'] = function ($c) { - return new SomeOtherVoter($c['auth']); - } - $container['auth'] = function ($c) { - return new AuthorizationService(new ServiceIterator($c, array('voter1', 'voter2')); - } - -.. _Pimple 1.x documentation: https://github.com/silexphp/Pimple/tree/1.1 diff --git a/advancedcontentfilter/vendor/pimple/pimple/composer.json b/advancedcontentfilter/vendor/pimple/pimple/composer.json deleted file mode 100644 index dabf190a9..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/composer.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "name": "pimple/pimple", - "type": "library", - "description": "Pimple, a simple Dependency Injection Container", - "keywords": ["dependency injection", "container"], - "homepage": "http://pimple.sensiolabs.org", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - } - ], - "require": { - "php": ">=5.3.0", - "psr/container": "^1.0" - }, - "require-dev": { - "symfony/phpunit-bridge": "^3.2" - }, - "autoload": { - "psr-0": { "Pimple": "src/" } - }, - "extra": { - "branch-alias": { - "dev-master": "3.2.x-dev" - } - } -} diff --git a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/.gitignore b/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/.gitignore deleted file mode 100644 index 1861088ac..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/.gitignore +++ /dev/null @@ -1,30 +0,0 @@ -*.sw* -.deps -Makefile -Makefile.fragments -Makefile.global -Makefile.objects -acinclude.m4 -aclocal.m4 -build/ -config.cache -config.guess -config.h -config.h.in -config.log -config.nice -config.status -config.sub -configure -configure.in -install-sh -libtool -ltmain.sh -missing -mkinstalldirs -run-tests.php -*.loT -.libs/ -modules/ -*.la -*.lo diff --git a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/README.md b/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/README.md deleted file mode 100644 index 7b39eb292..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/README.md +++ /dev/null @@ -1,12 +0,0 @@ -This is Pimple 2 implemented in C - -* PHP >= 5.3 -* Not tested under Windows, might work - -Install -======= - - > phpize - > ./configure - > make - > make install diff --git a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/config.m4 b/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/config.m4 deleted file mode 100644 index 3a6e9aaeb..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/config.m4 +++ /dev/null @@ -1,63 +0,0 @@ -dnl $Id$ -dnl config.m4 for extension pimple - -dnl Comments in this file start with the string 'dnl'. -dnl Remove where necessary. This file will not work -dnl without editing. - -dnl If your extension references something external, use with: - -dnl PHP_ARG_WITH(pimple, for pimple support, -dnl Make sure that the comment is aligned: -dnl [ --with-pimple Include pimple support]) - -dnl Otherwise use enable: - -PHP_ARG_ENABLE(pimple, whether to enable pimple support, -dnl Make sure that the comment is aligned: -[ --enable-pimple Enable pimple support]) - -if test "$PHP_PIMPLE" != "no"; then - dnl Write more examples of tests here... - - dnl # --with-pimple -> check with-path - dnl SEARCH_PATH="/usr/local /usr" # you might want to change this - dnl SEARCH_FOR="/include/pimple.h" # you most likely want to change this - dnl if test -r $PHP_PIMPLE/$SEARCH_FOR; then # path given as parameter - dnl PIMPLE_DIR=$PHP_PIMPLE - dnl else # search default path list - dnl AC_MSG_CHECKING([for pimple files in default path]) - dnl for i in $SEARCH_PATH ; do - dnl if test -r $i/$SEARCH_FOR; then - dnl PIMPLE_DIR=$i - dnl AC_MSG_RESULT(found in $i) - dnl fi - dnl done - dnl fi - dnl - dnl if test -z "$PIMPLE_DIR"; then - dnl AC_MSG_RESULT([not found]) - dnl AC_MSG_ERROR([Please reinstall the pimple distribution]) - dnl fi - - dnl # --with-pimple -> add include path - dnl PHP_ADD_INCLUDE($PIMPLE_DIR/include) - - dnl # --with-pimple -> check for lib and symbol presence - dnl LIBNAME=pimple # you may want to change this - dnl LIBSYMBOL=pimple # you most likely want to change this - - dnl PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL, - dnl [ - dnl PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $PIMPLE_DIR/lib, PIMPLE_SHARED_LIBADD) - dnl AC_DEFINE(HAVE_PIMPLELIB,1,[ ]) - dnl ],[ - dnl AC_MSG_ERROR([wrong pimple lib version or lib not found]) - dnl ],[ - dnl -L$PIMPLE_DIR/lib -lm - dnl ]) - dnl - dnl PHP_SUBST(PIMPLE_SHARED_LIBADD) - - PHP_NEW_EXTENSION(pimple, pimple.c, $ext_shared) -fi diff --git a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/config.w32 b/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/config.w32 deleted file mode 100644 index 39857b325..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/config.w32 +++ /dev/null @@ -1,13 +0,0 @@ -// $Id$ -// vim:ft=javascript - -// If your extension references something external, use ARG_WITH -// ARG_WITH("pimple", "for pimple support", "no"); - -// Otherwise, use ARG_ENABLE -// ARG_ENABLE("pimple", "enable pimple support", "no"); - -if (PHP_PIMPLE != "no") { - EXTENSION("pimple", "pimple.c"); -} - diff --git a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/php_pimple.h b/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/php_pimple.h deleted file mode 100644 index eed7c1731..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/php_pimple.h +++ /dev/null @@ -1,137 +0,0 @@ - -/* - * This file is part of Pimple. - * - * Copyright (c) 2014 Fabien Potencier - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is furnished - * to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef PHP_PIMPLE_H -#define PHP_PIMPLE_H - -extern zend_module_entry pimple_module_entry; -#define phpext_pimple_ptr &pimple_module_entry - -#ifdef PHP_WIN32 -# define PHP_PIMPLE_API __declspec(dllexport) -#elif defined(__GNUC__) && __GNUC__ >= 4 -# define PHP_PIMPLE_API __attribute__ ((visibility("default"))) -#else -# define PHP_PIMPLE_API -#endif - -#ifdef ZTS -#include "TSRM.h" -#endif - -#define PIMPLE_VERSION "3.2.3-DEV" - -#define PIMPLE_NS "Pimple" -#define PSR_CONTAINER_NS "Psr\\Container" -#define PIMPLE_EXCEPTION_NS "Pimple\\Exception" - -#define PIMPLE_DEFAULT_ZVAL_CACHE_NUM 5 -#define PIMPLE_DEFAULT_ZVAL_VALUES_NUM 10 - -#define PIMPLE_DEPRECATE do { \ - int er = EG(error_reporting); \ - EG(error_reporting) = 0;\ - php_error(E_DEPRECATED, "The Pimple C extension is deprecated since version 3.1 and will be removed in 4.0."); \ - EG(error_reporting) = er; \ -} while (0); - -zend_module_entry *get_module(void); - -PHP_MINIT_FUNCTION(pimple); -PHP_MINFO_FUNCTION(pimple); - -PHP_METHOD(FrozenServiceException, __construct); -PHP_METHOD(InvalidServiceIdentifierException, __construct); -PHP_METHOD(UnknownIdentifierException, __construct); - -PHP_METHOD(Pimple, __construct); -PHP_METHOD(Pimple, factory); -PHP_METHOD(Pimple, protect); -PHP_METHOD(Pimple, raw); -PHP_METHOD(Pimple, extend); -PHP_METHOD(Pimple, keys); -PHP_METHOD(Pimple, register); -PHP_METHOD(Pimple, offsetSet); -PHP_METHOD(Pimple, offsetUnset); -PHP_METHOD(Pimple, offsetGet); -PHP_METHOD(Pimple, offsetExists); - -PHP_METHOD(PimpleClosure, invoker); - -typedef struct _pimple_bucket_value { - zval *value; /* Must be the first element */ - zval *raw; - zend_object_handle handle_num; - enum { - PIMPLE_IS_PARAM = 0, - PIMPLE_IS_SERVICE = 2 - } type; - zend_bool initialized; - zend_fcall_info_cache fcc; -} pimple_bucket_value; - -typedef struct _pimple_object { - zend_object zobj; - HashTable values; - HashTable factories; - HashTable protected; -} pimple_object; - -typedef struct _pimple_closure_object { - zend_object zobj; - zval *callable; - zval *factory; -} pimple_closure_object; - -static const char sensiolabs_logo[] = ""; - -static void pimple_exception_call_parent_constructor(zval *this_ptr, const char *format, const char *arg1 TSRMLS_DC); - -static int pimple_zval_to_pimpleval(zval *_zval, pimple_bucket_value *_pimple_bucket_value TSRMLS_DC); -static int pimple_zval_is_valid_callback(zval *_zval, pimple_bucket_value *_pimple_bucket_value TSRMLS_DC); - -static void pimple_bucket_dtor(pimple_bucket_value *bucket); -static void pimple_free_bucket(pimple_bucket_value *bucket); - -static zval *pimple_object_read_dimension(zval *object, zval *offset, int type TSRMLS_DC); -static void pimple_object_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC); -static int pimple_object_has_dimension(zval *object, zval *offset, int check_empty TSRMLS_DC); -static void pimple_object_unset_dimension(zval *object, zval *offset TSRMLS_DC); -static zend_object_value pimple_object_create(zend_class_entry *ce TSRMLS_DC); -static void pimple_free_object_storage(pimple_object *obj TSRMLS_DC); - -static void pimple_closure_free_object_storage(pimple_closure_object *obj TSRMLS_DC); -static zend_object_value pimple_closure_object_create(zend_class_entry *ce TSRMLS_DC); -static zend_function *pimple_closure_get_constructor(zval * TSRMLS_DC); -static int pimple_closure_get_closure(zval *obj, zend_class_entry **ce_ptr, union _zend_function **fptr_ptr, zval **zobj_ptr TSRMLS_DC); - -#ifdef ZTS -#define PIMPLE_G(v) TSRMG(pimple_globals_id, zend_pimple_globals *, v) -#else -#define PIMPLE_G(v) (pimple_globals.v) -#endif - -#endif /* PHP_PIMPLE_H */ - diff --git a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/pimple.c b/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/pimple.c deleted file mode 100644 index c80499b39..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/pimple.c +++ /dev/null @@ -1,1114 +0,0 @@ - -/* - * This file is part of Pimple. - * - * Copyright (c) 2014 Fabien Potencier - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is furnished - * to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "php.h" -#include "php_ini.h" -#include "ext/standard/info.h" -#include "php_pimple.h" -#include "pimple_compat.h" -#include "zend_interfaces.h" -#include "zend.h" -#include "Zend/zend_closures.h" -#include "ext/spl/spl_exceptions.h" -#include "Zend/zend_exceptions.h" -#include "main/php_output.h" -#include "SAPI.h" - -static zend_class_entry *pimple_ce_PsrContainerInterface; -static zend_class_entry *pimple_ce_PsrContainerExceptionInterface; -static zend_class_entry *pimple_ce_PsrNotFoundExceptionInterface; - -static zend_class_entry *pimple_ce_ExpectedInvokableException; -static zend_class_entry *pimple_ce_FrozenServiceException; -static zend_class_entry *pimple_ce_InvalidServiceIdentifierException; -static zend_class_entry *pimple_ce_UnknownIdentifierException; - -static zend_class_entry *pimple_ce; -static zend_object_handlers pimple_object_handlers; -static zend_class_entry *pimple_closure_ce; -static zend_class_entry *pimple_serviceprovider_ce; -static zend_object_handlers pimple_closure_object_handlers; -static zend_internal_function pimple_closure_invoker_function; - -#define FETCH_DIM_HANDLERS_VARS pimple_object *pimple_obj = NULL; \ - ulong index; \ - pimple_obj = (pimple_object *)zend_object_store_get_object(object TSRMLS_CC); \ - -#define PIMPLE_OBJECT_HANDLE_INHERITANCE_OBJECT_HANDLERS do { \ - if (ce != pimple_ce) { \ - zend_hash_find(&ce->function_table, ZEND_STRS("offsetget"), (void **)&function); \ - if (function->common.scope != ce) { /* if the function is not defined in this actual class */ \ - pimple_object_handlers.read_dimension = pimple_object_read_dimension; /* then overwrite the handler to use custom one */ \ - } \ - zend_hash_find(&ce->function_table, ZEND_STRS("offsetset"), (void **)&function); \ - if (function->common.scope != ce) { \ - pimple_object_handlers.write_dimension = pimple_object_write_dimension; \ - } \ - zend_hash_find(&ce->function_table, ZEND_STRS("offsetexists"), (void **)&function); \ - if (function->common.scope != ce) { \ - pimple_object_handlers.has_dimension = pimple_object_has_dimension; \ - } \ - zend_hash_find(&ce->function_table, ZEND_STRS("offsetunset"), (void **)&function); \ - if (function->common.scope != ce) { \ - pimple_object_handlers.unset_dimension = pimple_object_unset_dimension; \ - } \ - } else { \ - pimple_object_handlers.read_dimension = pimple_object_read_dimension; \ - pimple_object_handlers.write_dimension = pimple_object_write_dimension; \ - pimple_object_handlers.has_dimension = pimple_object_has_dimension; \ - pimple_object_handlers.unset_dimension = pimple_object_unset_dimension; \ - }\ - } while(0); - -#define PIMPLE_CALL_CB do { \ - zend_fcall_info_argn(&fci TSRMLS_CC, 1, &object); \ - fci.size = sizeof(fci); \ - fci.object_ptr = retval->fcc.object_ptr; \ - fci.function_name = retval->value; \ - fci.no_separation = 1; \ - fci.retval_ptr_ptr = &retval_ptr_ptr; \ -\ - zend_call_function(&fci, &retval->fcc TSRMLS_CC); \ - efree(fci.params); \ - if (EG(exception)) { \ - return EG(uninitialized_zval_ptr); \ - } \ - } while(0); - - -/* Psr\Container\ContainerInterface */ -ZEND_BEGIN_ARG_INFO_EX(arginfo_pimple_PsrContainerInterface_get, 0, 0, 1) -ZEND_ARG_INFO(0, id) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_pimple_PsrContainerInterface_has, 0, 0, 1) -ZEND_ARG_INFO(0, id) -ZEND_END_ARG_INFO() - -static const zend_function_entry pimple_ce_PsrContainerInterface_functions[] = { - PHP_ABSTRACT_ME(ContainerInterface, get, arginfo_pimple_PsrContainerInterface_get) - PHP_ABSTRACT_ME(ContainerInterface, has, arginfo_pimple_PsrContainerInterface_has) - PHP_FE_END -}; - -/* Psr\Container\ContainerExceptionInterface */ -static const zend_function_entry pimple_ce_PsrContainerExceptionInterface_functions[] = { - PHP_FE_END -}; - -/* Psr\Container\NotFoundExceptionInterface */ -static const zend_function_entry pimple_ce_PsrNotFoundExceptionInterface_functions[] = { - PHP_FE_END -}; - -/* Pimple\Exception\FrozenServiceException */ -ZEND_BEGIN_ARG_INFO_EX(arginfo_FrozenServiceException___construct, 0, 0, 1) -ZEND_ARG_INFO(0, id) -ZEND_END_ARG_INFO() - -static const zend_function_entry pimple_ce_FrozenServiceException_functions[] = { - PHP_ME(FrozenServiceException, __construct, arginfo_FrozenServiceException___construct, ZEND_ACC_PUBLIC) - PHP_FE_END -}; - -/* Pimple\Exception\InvalidServiceIdentifierException */ -ZEND_BEGIN_ARG_INFO_EX(arginfo_InvalidServiceIdentifierException___construct, 0, 0, 1) -ZEND_ARG_INFO(0, id) -ZEND_END_ARG_INFO() - -static const zend_function_entry pimple_ce_InvalidServiceIdentifierException_functions[] = { - PHP_ME(InvalidServiceIdentifierException, __construct, arginfo_InvalidServiceIdentifierException___construct, ZEND_ACC_PUBLIC) - PHP_FE_END -}; - -/* Pimple\Exception\UnknownIdentifierException */ -ZEND_BEGIN_ARG_INFO_EX(arginfo_UnknownIdentifierException___construct, 0, 0, 1) -ZEND_ARG_INFO(0, id) -ZEND_END_ARG_INFO() - -static const zend_function_entry pimple_ce_UnknownIdentifierException_functions[] = { - PHP_ME(UnknownIdentifierException, __construct, arginfo_UnknownIdentifierException___construct, ZEND_ACC_PUBLIC) - PHP_FE_END -}; - -/* Pimple\Container */ -ZEND_BEGIN_ARG_INFO_EX(arginfo___construct, 0, 0, 0) -ZEND_ARG_ARRAY_INFO(0, value, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetset, 0, 0, 2) -ZEND_ARG_INFO(0, offset) -ZEND_ARG_INFO(0, value) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetget, 0, 0, 1) -ZEND_ARG_INFO(0, offset) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetexists, 0, 0, 1) -ZEND_ARG_INFO(0, offset) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetunset, 0, 0, 1) -ZEND_ARG_INFO(0, offset) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_factory, 0, 0, 1) -ZEND_ARG_INFO(0, callable) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_protect, 0, 0, 1) -ZEND_ARG_INFO(0, callable) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_raw, 0, 0, 1) -ZEND_ARG_INFO(0, id) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_extend, 0, 0, 2) -ZEND_ARG_INFO(0, id) -ZEND_ARG_INFO(0, callable) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_keys, 0, 0, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_register, 0, 0, 1) -ZEND_ARG_OBJ_INFO(0, provider, Pimple\\ServiceProviderInterface, 0) -ZEND_ARG_ARRAY_INFO(0, values, 1) -ZEND_END_ARG_INFO() - -static const zend_function_entry pimple_ce_functions[] = { - PHP_ME(Pimple, __construct, arginfo___construct, ZEND_ACC_PUBLIC) - PHP_ME(Pimple, factory, arginfo_factory, ZEND_ACC_PUBLIC) - PHP_ME(Pimple, protect, arginfo_protect, ZEND_ACC_PUBLIC) - PHP_ME(Pimple, raw, arginfo_raw, ZEND_ACC_PUBLIC) - PHP_ME(Pimple, extend, arginfo_extend, ZEND_ACC_PUBLIC) - PHP_ME(Pimple, keys, arginfo_keys, ZEND_ACC_PUBLIC) - PHP_ME(Pimple, register, arginfo_register, ZEND_ACC_PUBLIC) - - PHP_ME(Pimple, offsetSet, arginfo_offsetset, ZEND_ACC_PUBLIC) - PHP_ME(Pimple, offsetGet, arginfo_offsetget, ZEND_ACC_PUBLIC) - PHP_ME(Pimple, offsetExists, arginfo_offsetexists, ZEND_ACC_PUBLIC) - PHP_ME(Pimple, offsetUnset, arginfo_offsetunset, ZEND_ACC_PUBLIC) - PHP_FE_END -}; - -/* Pimple\ServiceProviderInterface */ -ZEND_BEGIN_ARG_INFO_EX(arginfo_serviceprovider_register, 0, 0, 1) -ZEND_ARG_OBJ_INFO(0, pimple, Pimple\\Container, 0) -ZEND_END_ARG_INFO() - -static const zend_function_entry pimple_serviceprovider_iface_ce_functions[] = { - PHP_ABSTRACT_ME(ServiceProviderInterface, register, arginfo_serviceprovider_register) - PHP_FE_END -}; - -/* parent::__construct(sprintf("Something with %s", $arg1)) */ -static void pimple_exception_call_parent_constructor(zval *this_ptr, const char *format, const char *arg1 TSRMLS_DC) -{ - zend_class_entry *ce = Z_OBJCE_P(this_ptr); - char *message = NULL; - int message_len; - zval *constructor_arg; - - message_len = spprintf(&message, 0, format, arg1); - ALLOC_INIT_ZVAL(constructor_arg); - ZVAL_STRINGL(constructor_arg, message, message_len, 1); - - zend_call_method_with_1_params(&this_ptr, ce, &ce->parent->constructor, "__construct", NULL, constructor_arg); - - efree(message); - zval_ptr_dtor(&constructor_arg); -} - -/** - * Pass a single string parameter to exception constructor and throw - */ -static void pimple_throw_exception_string(zend_class_entry *ce, const char *message, zend_uint message_len TSRMLS_DC) -{ - zval *exception, *param; - - ALLOC_INIT_ZVAL(exception); - object_init_ex(exception, ce); - - ALLOC_INIT_ZVAL(param); - ZVAL_STRINGL(param, message, message_len, 1); - - zend_call_method_with_1_params(&exception, ce, &ce->constructor, "__construct", NULL, param); - - zend_throw_exception_object(exception TSRMLS_CC); - - zval_ptr_dtor(¶m); -} - -static void pimple_closure_free_object_storage(pimple_closure_object *obj TSRMLS_DC) -{ - zend_object_std_dtor(&obj->zobj TSRMLS_CC); - if (obj->factory) { - zval_ptr_dtor(&obj->factory); - } - if (obj->callable) { - zval_ptr_dtor(&obj->callable); - } - efree(obj); -} - -static void pimple_free_object_storage(pimple_object *obj TSRMLS_DC) -{ - zend_hash_destroy(&obj->factories); - zend_hash_destroy(&obj->protected); - zend_hash_destroy(&obj->values); - zend_object_std_dtor(&obj->zobj TSRMLS_CC); - efree(obj); -} - -static void pimple_free_bucket(pimple_bucket_value *bucket) -{ - if (bucket->raw) { - zval_ptr_dtor(&bucket->raw); - } -} - -static zend_object_value pimple_closure_object_create(zend_class_entry *ce TSRMLS_DC) -{ - zend_object_value retval; - pimple_closure_object *pimple_closure_obj = NULL; - - pimple_closure_obj = ecalloc(1, sizeof(pimple_closure_object)); - ZEND_OBJ_INIT(&pimple_closure_obj->zobj, ce); - - pimple_closure_object_handlers.get_constructor = pimple_closure_get_constructor; - retval.handlers = &pimple_closure_object_handlers; - retval.handle = zend_objects_store_put(pimple_closure_obj, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) pimple_closure_free_object_storage, NULL TSRMLS_CC); - - return retval; -} - -static zend_function *pimple_closure_get_constructor(zval *obj TSRMLS_DC) -{ - zend_error(E_ERROR, "Pimple\\ContainerClosure is an internal class and cannot be instantiated"); - - return NULL; -} - -static int pimple_closure_get_closure(zval *obj, zend_class_entry **ce_ptr, union _zend_function **fptr_ptr, zval **zobj_ptr TSRMLS_DC) -{ - *zobj_ptr = obj; - *ce_ptr = Z_OBJCE_P(obj); - *fptr_ptr = (zend_function *)&pimple_closure_invoker_function; - - return SUCCESS; -} - -static zend_object_value pimple_object_create(zend_class_entry *ce TSRMLS_DC) -{ - zend_object_value retval; - pimple_object *pimple_obj = NULL; - zend_function *function = NULL; - - pimple_obj = emalloc(sizeof(pimple_object)); - ZEND_OBJ_INIT(&pimple_obj->zobj, ce); - - PIMPLE_OBJECT_HANDLE_INHERITANCE_OBJECT_HANDLERS - - retval.handlers = &pimple_object_handlers; - retval.handle = zend_objects_store_put(pimple_obj, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) pimple_free_object_storage, NULL TSRMLS_CC); - - zend_hash_init(&pimple_obj->factories, PIMPLE_DEFAULT_ZVAL_CACHE_NUM, NULL, (dtor_func_t)pimple_bucket_dtor, 0); - zend_hash_init(&pimple_obj->protected, PIMPLE_DEFAULT_ZVAL_CACHE_NUM, NULL, (dtor_func_t)pimple_bucket_dtor, 0); - zend_hash_init(&pimple_obj->values, PIMPLE_DEFAULT_ZVAL_VALUES_NUM, NULL, (dtor_func_t)pimple_bucket_dtor, 0); - - return retval; -} - -static void pimple_object_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC) -{ - FETCH_DIM_HANDLERS_VARS - - pimple_bucket_value pimple_value = {0}, *found_value = NULL; - ulong hash; - - pimple_zval_to_pimpleval(value, &pimple_value TSRMLS_CC); - - if (!offset) {/* $p[] = 'foo' when not overloaded */ - zend_hash_next_index_insert(&pimple_obj->values, (void *)&pimple_value, sizeof(pimple_bucket_value), NULL); - Z_ADDREF_P(value); - return; - } - - switch (Z_TYPE_P(offset)) { - case IS_STRING: - hash = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); - zend_hash_quick_find(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hash, (void **)&found_value); - if (found_value && found_value->type == PIMPLE_IS_SERVICE && found_value->initialized == 1) { - pimple_free_bucket(&pimple_value); - pimple_throw_exception_string(pimple_ce_FrozenServiceException, Z_STRVAL_P(offset), Z_STRLEN_P(offset) TSRMLS_CC); - return; - } - if (zend_hash_quick_update(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hash, (void *)&pimple_value, sizeof(pimple_bucket_value), NULL) == FAILURE) { - pimple_free_bucket(&pimple_value); - return; - } - Z_ADDREF_P(value); - break; - case IS_DOUBLE: - case IS_BOOL: - case IS_LONG: - if (Z_TYPE_P(offset) == IS_DOUBLE) { - index = (ulong)Z_DVAL_P(offset); - } else { - index = Z_LVAL_P(offset); - } - zend_hash_index_find(&pimple_obj->values, index, (void **)&found_value); - if (found_value && found_value->type == PIMPLE_IS_SERVICE && found_value->initialized == 1) { - pimple_free_bucket(&pimple_value); - convert_to_string(offset); - pimple_throw_exception_string(pimple_ce_FrozenServiceException, Z_STRVAL_P(offset), Z_STRLEN_P(offset) TSRMLS_CC); - return; - } - if (zend_hash_index_update(&pimple_obj->values, index, (void *)&pimple_value, sizeof(pimple_bucket_value), NULL) == FAILURE) { - pimple_free_bucket(&pimple_value); - return; - } - Z_ADDREF_P(value); - break; - case IS_NULL: /* $p[] = 'foo' when overloaded */ - zend_hash_next_index_insert(&pimple_obj->values, (void *)&pimple_value, sizeof(pimple_bucket_value), NULL); - Z_ADDREF_P(value); - break; - default: - pimple_free_bucket(&pimple_value); - zend_error(E_WARNING, "Unsupported offset type"); - } -} - -static void pimple_object_unset_dimension(zval *object, zval *offset TSRMLS_DC) -{ - FETCH_DIM_HANDLERS_VARS - - switch (Z_TYPE_P(offset)) { - case IS_STRING: - zend_symtable_del(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); - zend_symtable_del(&pimple_obj->factories, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); - zend_symtable_del(&pimple_obj->protected, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); - break; - case IS_DOUBLE: - case IS_BOOL: - case IS_LONG: - if (Z_TYPE_P(offset) == IS_DOUBLE) { - index = (ulong)Z_DVAL_P(offset); - } else { - index = Z_LVAL_P(offset); - } - zend_hash_index_del(&pimple_obj->values, index); - zend_hash_index_del(&pimple_obj->factories, index); - zend_hash_index_del(&pimple_obj->protected, index); - break; - default: - zend_error(E_WARNING, "Unsupported offset type"); - } -} - -static int pimple_object_has_dimension(zval *object, zval *offset, int check_empty TSRMLS_DC) -{ - FETCH_DIM_HANDLERS_VARS - - pimple_bucket_value *retval = NULL; - - switch (Z_TYPE_P(offset)) { - case IS_STRING: - if (zend_symtable_find(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void **)&retval) == SUCCESS) { - switch (check_empty) { - case 0: /* isset */ - return 1; /* Differs from PHP behavior (Z_TYPE_P(retval->value) != IS_NULL;) */ - case 1: /* empty */ - default: - return zend_is_true(retval->value); - } - } - return 0; - break; - case IS_DOUBLE: - case IS_BOOL: - case IS_LONG: - if (Z_TYPE_P(offset) == IS_DOUBLE) { - index = (ulong)Z_DVAL_P(offset); - } else { - index = Z_LVAL_P(offset); - } - if (zend_hash_index_find(&pimple_obj->values, index, (void **)&retval) == SUCCESS) { - switch (check_empty) { - case 0: /* isset */ - return 1; /* Differs from PHP behavior (Z_TYPE_P(retval->value) != IS_NULL;)*/ - case 1: /* empty */ - default: - return zend_is_true(retval->value); - } - } - return 0; - break; - default: - zend_error(E_WARNING, "Unsupported offset type"); - return 0; - } -} - -static zval *pimple_object_read_dimension(zval *object, zval *offset, int type TSRMLS_DC) -{ - FETCH_DIM_HANDLERS_VARS - - pimple_bucket_value *retval = NULL; - zend_fcall_info fci = {0}; - zval *retval_ptr_ptr = NULL; - - switch (Z_TYPE_P(offset)) { - case IS_STRING: - if (zend_symtable_find(&pimple_obj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void **)&retval) == FAILURE) { - pimple_throw_exception_string(pimple_ce_UnknownIdentifierException, Z_STRVAL_P(offset), Z_STRLEN_P(offset) TSRMLS_CC); - - return EG(uninitialized_zval_ptr); - } - break; - case IS_DOUBLE: - case IS_BOOL: - case IS_LONG: - if (Z_TYPE_P(offset) == IS_DOUBLE) { - index = (ulong)Z_DVAL_P(offset); - } else { - index = Z_LVAL_P(offset); - } - if (zend_hash_index_find(&pimple_obj->values, index, (void **)&retval) == FAILURE) { - return EG(uninitialized_zval_ptr); - } - break; - case IS_NULL: /* $p[][3] = 'foo' first dim access */ - return EG(uninitialized_zval_ptr); - break; - default: - zend_error(E_WARNING, "Unsupported offset type"); - return EG(uninitialized_zval_ptr); - } - - if(retval->type == PIMPLE_IS_PARAM) { - return retval->value; - } - - if (zend_hash_index_exists(&pimple_obj->protected, retval->handle_num)) { - /* Service is protected, return the value every time */ - return retval->value; - } - - if (zend_hash_index_exists(&pimple_obj->factories, retval->handle_num)) { - /* Service is a factory, call it every time and never cache its result */ - PIMPLE_CALL_CB - Z_DELREF_P(retval_ptr_ptr); /* fetch dim addr will increment refcount */ - return retval_ptr_ptr; - } - - if (retval->initialized == 1) { - /* Service has already been called, return its cached value */ - return retval->value; - } - - ALLOC_INIT_ZVAL(retval->raw); - MAKE_COPY_ZVAL(&retval->value, retval->raw); - - PIMPLE_CALL_CB - - retval->initialized = 1; - zval_ptr_dtor(&retval->value); - retval->value = retval_ptr_ptr; - - return retval->value; -} - -static int pimple_zval_is_valid_callback(zval *_zval, pimple_bucket_value *_pimple_bucket_value TSRMLS_DC) -{ - if (Z_TYPE_P(_zval) != IS_OBJECT) { - return FAILURE; - } - - if (_pimple_bucket_value->fcc.called_scope) { - return SUCCESS; - } - - if (Z_OBJ_HANDLER_P(_zval, get_closure) && Z_OBJ_HANDLER_P(_zval, get_closure)(_zval, &_pimple_bucket_value->fcc.calling_scope, &_pimple_bucket_value->fcc.function_handler, &_pimple_bucket_value->fcc.object_ptr TSRMLS_CC) == SUCCESS) { - _pimple_bucket_value->fcc.called_scope = _pimple_bucket_value->fcc.calling_scope; - return SUCCESS; - } else { - return FAILURE; - } -} - -static int pimple_zval_to_pimpleval(zval *_zval, pimple_bucket_value *_pimple_bucket_value TSRMLS_DC) -{ - _pimple_bucket_value->value = _zval; - - if (Z_TYPE_P(_zval) != IS_OBJECT) { - return PIMPLE_IS_PARAM; - } - - if (pimple_zval_is_valid_callback(_zval, _pimple_bucket_value TSRMLS_CC) == SUCCESS) { - _pimple_bucket_value->type = PIMPLE_IS_SERVICE; - _pimple_bucket_value->handle_num = Z_OBJ_HANDLE_P(_zval); - } - - return PIMPLE_IS_SERVICE; -} - -static void pimple_bucket_dtor(pimple_bucket_value *bucket) -{ - zval_ptr_dtor(&bucket->value); - pimple_free_bucket(bucket); -} - -PHP_METHOD(FrozenServiceException, __construct) -{ - char *id = NULL; - int id_len; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &id, &id_len) == FAILURE) { - return; - } - pimple_exception_call_parent_constructor(getThis(), "Cannot override frozen service \"%s\".", id TSRMLS_CC); -} - -PHP_METHOD(InvalidServiceIdentifierException, __construct) -{ - char *id = NULL; - int id_len; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &id, &id_len) == FAILURE) { - return; - } - pimple_exception_call_parent_constructor(getThis(), "Identifier \"%s\" does not contain an object definition.", id TSRMLS_CC); -} - -PHP_METHOD(UnknownIdentifierException, __construct) -{ - char *id = NULL; - int id_len; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &id, &id_len) == FAILURE) { - return; - } - pimple_exception_call_parent_constructor(getThis(), "Identifier \"%s\" is not defined.", id TSRMLS_CC); -} - -PHP_METHOD(Pimple, protect) -{ - zval *protected = NULL; - pimple_object *pobj = NULL; - pimple_bucket_value bucket = {0}; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &protected) == FAILURE) { - return; - } - - if (pimple_zval_is_valid_callback(protected, &bucket TSRMLS_CC) == FAILURE) { - pimple_free_bucket(&bucket); - zend_throw_exception(pimple_ce_ExpectedInvokableException, "Callable is not a Closure or invokable object.", 0 TSRMLS_CC); - return; - } - - pimple_zval_to_pimpleval(protected, &bucket TSRMLS_CC); - pobj = (pimple_object *)zend_object_store_get_object(getThis() TSRMLS_CC); - - if (zend_hash_index_update(&pobj->protected, bucket.handle_num, (void *)&bucket, sizeof(pimple_bucket_value), NULL) == SUCCESS) { - Z_ADDREF_P(protected); - RETURN_ZVAL(protected, 1 , 0); - } else { - pimple_free_bucket(&bucket); - } - RETURN_FALSE; -} - -PHP_METHOD(Pimple, raw) -{ - zval *offset = NULL; - pimple_object *pobj = NULL; - pimple_bucket_value *value = NULL; - ulong index; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &offset) == FAILURE) { - return; - } - - pobj = zend_object_store_get_object(getThis() TSRMLS_CC); - - switch (Z_TYPE_P(offset)) { - case IS_STRING: - if (zend_symtable_find(&pobj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void *)&value) == FAILURE) { - pimple_throw_exception_string(pimple_ce_UnknownIdentifierException, Z_STRVAL_P(offset), Z_STRLEN_P(offset) TSRMLS_CC); - RETURN_NULL(); - } - break; - case IS_DOUBLE: - case IS_BOOL: - case IS_LONG: - if (Z_TYPE_P(offset) == IS_DOUBLE) { - index = (ulong)Z_DVAL_P(offset); - } else { - index = Z_LVAL_P(offset); - } - if (zend_hash_index_find(&pobj->values, index, (void *)&value) == FAILURE) { - RETURN_NULL(); - } - break; - case IS_NULL: - default: - zend_error(E_WARNING, "Unsupported offset type"); - } - - if (value->raw) { - RETVAL_ZVAL(value->raw, 1, 0); - } else { - RETVAL_ZVAL(value->value, 1, 0); - } -} - -PHP_METHOD(Pimple, extend) -{ - zval *offset = NULL, *callable = NULL, *pimple_closure_obj = NULL; - pimple_bucket_value bucket = {0}, *value = NULL; - pimple_object *pobj = NULL; - pimple_closure_object *pcobj = NULL; - ulong index; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &offset, &callable) == FAILURE) { - return; - } - - pobj = zend_object_store_get_object(getThis() TSRMLS_CC); - - switch (Z_TYPE_P(offset)) { - case IS_STRING: - if (zend_symtable_find(&pobj->values, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void *)&value) == FAILURE) { - pimple_throw_exception_string(pimple_ce_UnknownIdentifierException, Z_STRVAL_P(offset), Z_STRLEN_P(offset) TSRMLS_CC); - RETURN_NULL(); - } - - if (value->type != PIMPLE_IS_SERVICE) { - pimple_throw_exception_string(pimple_ce_InvalidServiceIdentifierException, Z_STRVAL_P(offset), Z_STRLEN_P(offset) TSRMLS_CC); - RETURN_NULL(); - } - if (zend_hash_index_exists(&pobj->protected, value->handle_num)) { - int er = EG(error_reporting); - EG(error_reporting) = 0; - php_error(E_DEPRECATED, "How Pimple behaves when extending protected closures will be fixed in Pimple 4. Are you sure \"%s\" should be protected?", Z_STRVAL_P(offset)); - EG(error_reporting) = er; - } - break; - case IS_DOUBLE: - case IS_BOOL: - case IS_LONG: - if (Z_TYPE_P(offset) == IS_DOUBLE) { - index = (ulong)Z_DVAL_P(offset); - } else { - index = Z_LVAL_P(offset); - } - if (zend_hash_index_find(&pobj->values, index, (void *)&value) == FAILURE) { - convert_to_string(offset); - pimple_throw_exception_string(pimple_ce_UnknownIdentifierException, Z_STRVAL_P(offset), Z_STRLEN_P(offset) TSRMLS_CC); - RETURN_NULL(); - } - if (value->type != PIMPLE_IS_SERVICE) { - convert_to_string(offset); - pimple_throw_exception_string(pimple_ce_InvalidServiceIdentifierException, Z_STRVAL_P(offset), Z_STRLEN_P(offset) TSRMLS_CC); - RETURN_NULL(); - } - if (zend_hash_index_exists(&pobj->protected, value->handle_num)) { - int er = EG(error_reporting); - EG(error_reporting) = 0; - php_error(E_DEPRECATED, "How Pimple behaves when extending protected closures will be fixed in Pimple 4. Are you sure \"%ld\" should be protected?", index); - EG(error_reporting) = er; - } - break; - case IS_NULL: - default: - zend_error(E_WARNING, "Unsupported offset type"); - } - - if (pimple_zval_is_valid_callback(callable, &bucket TSRMLS_CC) == FAILURE) { - pimple_free_bucket(&bucket); - zend_throw_exception(pimple_ce_ExpectedInvokableException, "Extension service definition is not a Closure or invokable object.", 0 TSRMLS_CC); - RETURN_NULL(); - } - pimple_free_bucket(&bucket); - - ALLOC_INIT_ZVAL(pimple_closure_obj); - object_init_ex(pimple_closure_obj, pimple_closure_ce); - - pcobj = zend_object_store_get_object(pimple_closure_obj TSRMLS_CC); - pcobj->callable = callable; - pcobj->factory = value->value; - Z_ADDREF_P(callable); - Z_ADDREF_P(value->value); - - if (zend_hash_index_exists(&pobj->factories, value->handle_num)) { - pimple_zval_to_pimpleval(pimple_closure_obj, &bucket TSRMLS_CC); - zend_hash_index_del(&pobj->factories, value->handle_num); - zend_hash_index_update(&pobj->factories, bucket.handle_num, (void *)&bucket, sizeof(pimple_bucket_value), NULL); - Z_ADDREF_P(pimple_closure_obj); - } - - pimple_object_write_dimension(getThis(), offset, pimple_closure_obj TSRMLS_CC); - - RETVAL_ZVAL(pimple_closure_obj, 1, 1); -} - -PHP_METHOD(Pimple, keys) -{ - HashPosition pos; - pimple_object *pobj = NULL; - zval **value = NULL; - zval *endval = NULL; - char *str_index = NULL; - int str_len; - ulong num_index; - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - pobj = zend_object_store_get_object(getThis() TSRMLS_CC); - array_init_size(return_value, zend_hash_num_elements(&pobj->values)); - - zend_hash_internal_pointer_reset_ex(&pobj->values, &pos); - - while(zend_hash_get_current_data_ex(&pobj->values, (void **)&value, &pos) == SUCCESS) { - MAKE_STD_ZVAL(endval); - switch (zend_hash_get_current_key_ex(&pobj->values, &str_index, (uint *)&str_len, &num_index, 0, &pos)) { - case HASH_KEY_IS_STRING: - ZVAL_STRINGL(endval, str_index, str_len - 1, 1); - zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &endval, sizeof(zval *), NULL); - break; - case HASH_KEY_IS_LONG: - ZVAL_LONG(endval, num_index); - zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &endval, sizeof(zval *), NULL); - break; - } - zend_hash_move_forward_ex(&pobj->values, &pos); - } -} - -PHP_METHOD(Pimple, factory) -{ - zval *factory = NULL; - pimple_object *pobj = NULL; - pimple_bucket_value bucket = {0}; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &factory) == FAILURE) { - return; - } - - if (pimple_zval_is_valid_callback(factory, &bucket TSRMLS_CC) == FAILURE) { - pimple_free_bucket(&bucket); - zend_throw_exception(pimple_ce_ExpectedInvokableException, "Service definition is not a Closure or invokable object.", 0 TSRMLS_CC); - return; - } - - pimple_zval_to_pimpleval(factory, &bucket TSRMLS_CC); - pobj = (pimple_object *)zend_object_store_get_object(getThis() TSRMLS_CC); - - if (zend_hash_index_update(&pobj->factories, bucket.handle_num, (void *)&bucket, sizeof(pimple_bucket_value), NULL) == SUCCESS) { - Z_ADDREF_P(factory); - RETURN_ZVAL(factory, 1 , 0); - } else { - pimple_free_bucket(&bucket); - } - - RETURN_FALSE; -} - -PHP_METHOD(Pimple, offsetSet) -{ - zval *offset = NULL, *value = NULL; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &offset, &value) == FAILURE) { - return; - } - - pimple_object_write_dimension(getThis(), offset, value TSRMLS_CC); -} - -PHP_METHOD(Pimple, offsetGet) -{ - zval *offset = NULL, *retval = NULL; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &offset) == FAILURE) { - return; - } - - retval = pimple_object_read_dimension(getThis(), offset, 0 TSRMLS_CC); - - RETVAL_ZVAL(retval, 1, 0); -} - -PHP_METHOD(Pimple, offsetUnset) -{ - zval *offset = NULL; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &offset) == FAILURE) { - return; - } - - pimple_object_unset_dimension(getThis(), offset TSRMLS_CC); -} - -PHP_METHOD(Pimple, offsetExists) -{ - zval *offset = NULL; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &offset) == FAILURE) { - return; - } - - RETVAL_BOOL(pimple_object_has_dimension(getThis(), offset, 1 TSRMLS_CC)); -} - -PHP_METHOD(Pimple, register) -{ - zval *provider; - zval **data; - zval *retval = NULL; - zval key; - - HashTable *array = NULL; - HashPosition pos; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|h", &provider, pimple_serviceprovider_ce, &array) == FAILURE) { - return; - } - - RETVAL_ZVAL(getThis(), 1, 0); - - zend_call_method_with_1_params(&provider, Z_OBJCE_P(provider), NULL, "register", &retval, getThis()); - - if (retval) { - zval_ptr_dtor(&retval); - } - - if (!array) { - return; - } - - zend_hash_internal_pointer_reset_ex(array, &pos); - - while(zend_hash_get_current_data_ex(array, (void **)&data, &pos) == SUCCESS) { - zend_hash_get_current_key_zval_ex(array, &key, &pos); - pimple_object_write_dimension(getThis(), &key, *data TSRMLS_CC); - zend_hash_move_forward_ex(array, &pos); - } -} - -PHP_METHOD(Pimple, __construct) -{ - zval *values = NULL, **pData = NULL, offset; - HashPosition pos; - char *str_index = NULL; - zend_uint str_length; - ulong num_index; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!", &values) == FAILURE) { - return; - } - - PIMPLE_DEPRECATE - - if (!values) { - return; - } - - zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(values), &pos); - while (zend_hash_has_more_elements_ex(Z_ARRVAL_P(values), &pos) == SUCCESS) { - zend_hash_get_current_data_ex(Z_ARRVAL_P(values), (void **)&pData, &pos); - zend_hash_get_current_key_ex(Z_ARRVAL_P(values), &str_index, &str_length, &num_index, 0, &pos); - INIT_ZVAL(offset); - if (zend_hash_get_current_key_type_ex(Z_ARRVAL_P(values), &pos) == HASH_KEY_IS_LONG) { - ZVAL_LONG(&offset, num_index); - } else { - ZVAL_STRINGL(&offset, str_index, (str_length - 1), 0); - } - pimple_object_write_dimension(getThis(), &offset, *pData TSRMLS_CC); - zend_hash_move_forward_ex(Z_ARRVAL_P(values), &pos); - } -} - -/* - * This is PHP code snippet handling extend()s calls : - - $extended = function ($c) use ($callable, $factory) { - return $callable($factory($c), $c); - }; - - */ -PHP_METHOD(PimpleClosure, invoker) -{ - pimple_closure_object *pcobj = NULL; - zval *arg = NULL, *retval = NULL, *newretval = NULL; - zend_fcall_info fci = {0}; - zval **args[2]; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &arg) == FAILURE) { - return; - } - - pcobj = zend_object_store_get_object(getThis() TSRMLS_CC); - - fci.function_name = pcobj->factory; - args[0] = &arg; - zend_fcall_info_argp(&fci TSRMLS_CC, 1, args); - fci.retval_ptr_ptr = &retval; - fci.size = sizeof(fci); - - if (zend_call_function(&fci, NULL TSRMLS_CC) == FAILURE || EG(exception)) { - efree(fci.params); - return; /* Should here return default zval */ - } - - efree(fci.params); - memset(&fci, 0, sizeof(fci)); - fci.size = sizeof(fci); - - fci.function_name = pcobj->callable; - args[0] = &retval; - args[1] = &arg; - zend_fcall_info_argp(&fci TSRMLS_CC, 2, args); - fci.retval_ptr_ptr = &newretval; - - if (zend_call_function(&fci, NULL TSRMLS_CC) == FAILURE || EG(exception)) { - efree(fci.params); - zval_ptr_dtor(&retval); - return; - } - - efree(fci.params); - zval_ptr_dtor(&retval); - - RETVAL_ZVAL(newretval, 1 ,1); -} - -PHP_MINIT_FUNCTION(pimple) -{ - zend_class_entry tmp_ce_PsrContainerInterface, tmp_ce_PsrContainerExceptionInterface, tmp_ce_PsrNotFoundExceptionInterface; - zend_class_entry tmp_ce_ExpectedInvokableException, tmp_ce_FrozenServiceException, tmp_ce_InvalidServiceIdentifierException, tmp_ce_UnknownIdentifierException; - zend_class_entry tmp_pimple_ce, tmp_pimple_closure_ce, tmp_pimple_serviceprovider_iface_ce; - - /* Psr\Container namespace */ - INIT_NS_CLASS_ENTRY(tmp_ce_PsrContainerInterface, PSR_CONTAINER_NS, "ContainerInterface", pimple_ce_PsrContainerInterface_functions); - INIT_NS_CLASS_ENTRY(tmp_ce_PsrContainerExceptionInterface, PSR_CONTAINER_NS, "ContainerExceptionInterface", pimple_ce_PsrContainerExceptionInterface_functions); - INIT_NS_CLASS_ENTRY(tmp_ce_PsrNotFoundExceptionInterface, PSR_CONTAINER_NS, "NotFoundExceptionInterface", pimple_ce_PsrNotFoundExceptionInterface_functions); - - pimple_ce_PsrContainerInterface = zend_register_internal_interface(&tmp_ce_PsrContainerInterface TSRMLS_CC); - pimple_ce_PsrContainerExceptionInterface = zend_register_internal_interface(&tmp_ce_PsrContainerExceptionInterface TSRMLS_CC); - pimple_ce_PsrNotFoundExceptionInterface = zend_register_internal_interface(&tmp_ce_PsrNotFoundExceptionInterface TSRMLS_CC); - - zend_class_implements(pimple_ce_PsrNotFoundExceptionInterface TSRMLS_CC, 1, pimple_ce_PsrContainerExceptionInterface); - - /* Pimple\Exception namespace */ - INIT_NS_CLASS_ENTRY(tmp_ce_ExpectedInvokableException, PIMPLE_EXCEPTION_NS, "ExpectedInvokableException", NULL); - INIT_NS_CLASS_ENTRY(tmp_ce_FrozenServiceException, PIMPLE_EXCEPTION_NS, "FrozenServiceException", pimple_ce_FrozenServiceException_functions); - INIT_NS_CLASS_ENTRY(tmp_ce_InvalidServiceIdentifierException, PIMPLE_EXCEPTION_NS, "InvalidServiceIdentifierException", pimple_ce_InvalidServiceIdentifierException_functions); - INIT_NS_CLASS_ENTRY(tmp_ce_UnknownIdentifierException, PIMPLE_EXCEPTION_NS, "UnknownIdentifierException", pimple_ce_UnknownIdentifierException_functions); - - pimple_ce_ExpectedInvokableException = zend_register_internal_class_ex(&tmp_ce_ExpectedInvokableException, spl_ce_InvalidArgumentException, NULL TSRMLS_CC); - pimple_ce_FrozenServiceException = zend_register_internal_class_ex(&tmp_ce_FrozenServiceException, spl_ce_RuntimeException, NULL TSRMLS_CC); - pimple_ce_InvalidServiceIdentifierException = zend_register_internal_class_ex(&tmp_ce_InvalidServiceIdentifierException, spl_ce_InvalidArgumentException, NULL TSRMLS_CC); - pimple_ce_UnknownIdentifierException = zend_register_internal_class_ex(&tmp_ce_UnknownIdentifierException, spl_ce_InvalidArgumentException, NULL TSRMLS_CC); - - zend_class_implements(pimple_ce_ExpectedInvokableException TSRMLS_CC, 1, pimple_ce_PsrContainerExceptionInterface); - zend_class_implements(pimple_ce_FrozenServiceException TSRMLS_CC, 1, pimple_ce_PsrContainerExceptionInterface); - zend_class_implements(pimple_ce_InvalidServiceIdentifierException TSRMLS_CC, 1, pimple_ce_PsrContainerExceptionInterface); - zend_class_implements(pimple_ce_UnknownIdentifierException TSRMLS_CC, 1, pimple_ce_PsrNotFoundExceptionInterface); - - /* Pimple namespace */ - INIT_NS_CLASS_ENTRY(tmp_pimple_ce, PIMPLE_NS, "Container", pimple_ce_functions); - INIT_NS_CLASS_ENTRY(tmp_pimple_closure_ce, PIMPLE_NS, "ContainerClosure", NULL); - INIT_NS_CLASS_ENTRY(tmp_pimple_serviceprovider_iface_ce, PIMPLE_NS, "ServiceProviderInterface", pimple_serviceprovider_iface_ce_functions); - - tmp_pimple_ce.create_object = pimple_object_create; - tmp_pimple_closure_ce.create_object = pimple_closure_object_create; - - pimple_ce = zend_register_internal_class(&tmp_pimple_ce TSRMLS_CC); - zend_class_implements(pimple_ce TSRMLS_CC, 1, zend_ce_arrayaccess); - - pimple_closure_ce = zend_register_internal_class(&tmp_pimple_closure_ce TSRMLS_CC); - pimple_closure_ce->ce_flags |= ZEND_ACC_FINAL_CLASS; - - pimple_serviceprovider_ce = zend_register_internal_interface(&tmp_pimple_serviceprovider_iface_ce TSRMLS_CC); - - memcpy(&pimple_closure_object_handlers, zend_get_std_object_handlers(), sizeof(*zend_get_std_object_handlers())); - pimple_object_handlers = std_object_handlers; - pimple_closure_object_handlers.get_closure = pimple_closure_get_closure; - - pimple_closure_invoker_function.function_name = "Pimple closure internal invoker"; - pimple_closure_invoker_function.fn_flags |= ZEND_ACC_CLOSURE; - pimple_closure_invoker_function.handler = ZEND_MN(PimpleClosure_invoker); - pimple_closure_invoker_function.num_args = 1; - pimple_closure_invoker_function.required_num_args = 1; - pimple_closure_invoker_function.scope = pimple_closure_ce; - pimple_closure_invoker_function.type = ZEND_INTERNAL_FUNCTION; - pimple_closure_invoker_function.module = &pimple_module_entry; - - return SUCCESS; -} - -PHP_MINFO_FUNCTION(pimple) -{ - php_info_print_table_start(); - php_info_print_table_header(2, "SensioLabs Pimple C support", "enabled"); - php_info_print_table_row(2, "Pimple supported version", PIMPLE_VERSION); - php_info_print_table_end(); - - php_info_print_box_start(0); - php_write((void *)ZEND_STRL("SensioLabs Pimple C support developed by Julien Pauli") TSRMLS_CC); - if (!sapi_module.phpinfo_as_text) { - php_write((void *)ZEND_STRL(sensiolabs_logo) TSRMLS_CC); - } - php_info_print_box_end(); -} - -zend_module_entry pimple_module_entry = { - STANDARD_MODULE_HEADER, - "pimple", - NULL, - PHP_MINIT(pimple), - NULL, - NULL, - NULL, - PHP_MINFO(pimple), - PIMPLE_VERSION, - STANDARD_MODULE_PROPERTIES -}; - -#ifdef COMPILE_DL_PIMPLE -ZEND_GET_MODULE(pimple) -#endif diff --git a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/pimple_compat.h b/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/pimple_compat.h deleted file mode 100644 index d234e174d..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/pimple_compat.h +++ /dev/null @@ -1,81 +0,0 @@ - -/* - * This file is part of Pimple. - * - * Copyright (c) 2014 Fabien Potencier - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is furnished - * to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef PIMPLE_COMPAT_H_ -#define PIMPLE_COMPAT_H_ - -#include "Zend/zend_extensions.h" /* for ZEND_EXTENSION_API_NO */ - -#define PHP_5_0_X_API_NO 220040412 -#define PHP_5_1_X_API_NO 220051025 -#define PHP_5_2_X_API_NO 220060519 -#define PHP_5_3_X_API_NO 220090626 -#define PHP_5_4_X_API_NO 220100525 -#define PHP_5_5_X_API_NO 220121212 -#define PHP_5_6_X_API_NO 220131226 - -#define IS_PHP_56 ZEND_EXTENSION_API_NO == PHP_5_6_X_API_NO -#define IS_AT_LEAST_PHP_56 ZEND_EXTENSION_API_NO >= PHP_5_6_X_API_NO - -#define IS_PHP_55 ZEND_EXTENSION_API_NO == PHP_5_5_X_API_NO -#define IS_AT_LEAST_PHP_55 ZEND_EXTENSION_API_NO >= PHP_5_5_X_API_NO - -#define IS_PHP_54 ZEND_EXTENSION_API_NO == PHP_5_4_X_API_NO -#define IS_AT_LEAST_PHP_54 ZEND_EXTENSION_API_NO >= PHP_5_4_X_API_NO - -#define IS_PHP_53 ZEND_EXTENSION_API_NO == PHP_5_3_X_API_NO -#define IS_AT_LEAST_PHP_53 ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO - -#if IS_PHP_53 -#define object_properties_init(obj, ce) do { \ - zend_hash_copy(obj->properties, &ce->default_properties, zval_copy_property_ctor(ce), NULL, sizeof(zval *)); \ - } while (0); -#endif - -#define ZEND_OBJ_INIT(obj, ce) do { \ - zend_object_std_init(obj, ce TSRMLS_CC); \ - object_properties_init((obj), (ce)); \ - } while(0); - -#if IS_PHP_53 || IS_PHP_54 -static void zend_hash_get_current_key_zval_ex(const HashTable *ht, zval *key, HashPosition *pos) { - Bucket *p; - - p = pos ? (*pos) : ht->pInternalPointer; - - if (!p) { - Z_TYPE_P(key) = IS_NULL; - } else if (p->nKeyLength) { - Z_TYPE_P(key) = IS_STRING; - Z_STRVAL_P(key) = estrndup(p->arKey, p->nKeyLength - 1); - Z_STRLEN_P(key) = p->nKeyLength - 1; - } else { - Z_TYPE_P(key) = IS_LONG; - Z_LVAL_P(key) = p->h; - } -} -#endif - -#endif /* PIMPLE_COMPAT_H_ */ diff --git a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/001.phpt b/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/001.phpt deleted file mode 100644 index 0809ea232..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/001.phpt +++ /dev/null @@ -1,45 +0,0 @@ ---TEST-- -Test for read_dim/write_dim handlers ---SKIPIF-- - ---FILE-- - - ---EXPECTF-- -foo -42 -foo2 -foo99 -baz -strstr \ No newline at end of file diff --git a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/002.phpt b/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/002.phpt deleted file mode 100644 index 7b56d2c1f..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/002.phpt +++ /dev/null @@ -1,15 +0,0 @@ ---TEST-- -Test for constructor ---SKIPIF-- - ---FILE-- -'foo')); -var_dump($p[42]); -?> ---EXPECT-- -NULL -string(3) "foo" diff --git a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/003.phpt b/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/003.phpt deleted file mode 100644 index a22cfa352..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/003.phpt +++ /dev/null @@ -1,16 +0,0 @@ ---TEST-- -Test empty dimensions ---SKIPIF-- - ---FILE-- - ---EXPECT-- -int(42) -string(3) "bar" \ No newline at end of file diff --git a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/004.phpt b/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/004.phpt deleted file mode 100644 index 1e1d25136..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/004.phpt +++ /dev/null @@ -1,30 +0,0 @@ ---TEST-- -Test has/unset dim handlers ---SKIPIF-- - ---FILE-- - ---EXPECT-- -int(42) -NULL -bool(true) -bool(false) -bool(true) -bool(true) \ No newline at end of file diff --git a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/005.phpt b/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/005.phpt deleted file mode 100644 index 0479ee055..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/005.phpt +++ /dev/null @@ -1,27 +0,0 @@ ---TEST-- -Test simple class inheritance ---SKIPIF-- - ---FILE-- -someAttr; -?> ---EXPECT-- -string(3) "hit" -foo -fooAttr \ No newline at end of file diff --git a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/006.phpt b/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/006.phpt deleted file mode 100644 index cfe8a119e..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/006.phpt +++ /dev/null @@ -1,51 +0,0 @@ ---TEST-- -Test complex class inheritance ---SKIPIF-- - ---FILE-- - 'bar', 88 => 'baz'); - -$p = new TestPimple($defaultValues); -$p[42] = 'foo'; -var_dump($p[42]); -var_dump($p[0]); -?> ---EXPECT-- -string(13) "hit offsetset" -string(27) "hit offsetget in TestPimple" -string(25) "hit offsetget in MyPimple" -string(3) "foo" -string(27) "hit offsetget in TestPimple" -string(25) "hit offsetget in MyPimple" -string(3) "baz" \ No newline at end of file diff --git a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/007.phpt b/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/007.phpt deleted file mode 100644 index 5aac68380..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/007.phpt +++ /dev/null @@ -1,22 +0,0 @@ ---TEST-- -Test for read_dim/write_dim handlers ---SKIPIF-- - ---FILE-- - ---EXPECTF-- -foo -42 \ No newline at end of file diff --git a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/008.phpt b/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/008.phpt deleted file mode 100644 index db7eeec4a..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/008.phpt +++ /dev/null @@ -1,29 +0,0 @@ ---TEST-- -Test frozen services ---SKIPIF-- - ---FILE-- - ---EXPECTF-- diff --git a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/009.phpt b/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/009.phpt deleted file mode 100644 index bb05ea296..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/009.phpt +++ /dev/null @@ -1,13 +0,0 @@ ---TEST-- -Test service is called as callback, and only once ---SKIPIF-- - ---FILE-- - ---EXPECTF-- -bool(true) \ No newline at end of file diff --git a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/010.phpt b/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/010.phpt deleted file mode 100644 index badce0146..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/010.phpt +++ /dev/null @@ -1,45 +0,0 @@ ---TEST-- -Test service is called as callback for every callback type ---SKIPIF-- - ---FILE-- - ---EXPECTF-- -callme -called -Foo::bar -array(2) { - [0]=> - string(3) "Foo" - [1]=> - string(3) "bar" -} \ No newline at end of file diff --git a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/011.phpt b/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/011.phpt deleted file mode 100644 index 6682ab8eb..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/011.phpt +++ /dev/null @@ -1,19 +0,0 @@ ---TEST-- -Test service callback throwing an exception ---SKIPIF-- - ---FILE-- - ---EXPECTF-- -all right! \ No newline at end of file diff --git a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/012.phpt b/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/012.phpt deleted file mode 100644 index 4c6ac486d..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/012.phpt +++ /dev/null @@ -1,28 +0,0 @@ ---TEST-- -Test service factory ---SKIPIF-- - ---FILE-- -factory($f = function() { var_dump('called-1'); return 'ret-1';}); - -$p[] = $f; - -$p[] = function () { var_dump('called-2'); return 'ret-2'; }; - -var_dump($p[0]); -var_dump($p[0]); -var_dump($p[1]); -var_dump($p[1]); -?> ---EXPECTF-- -string(8) "called-1" -string(5) "ret-1" -string(8) "called-1" -string(5) "ret-1" -string(8) "called-2" -string(5) "ret-2" -string(5) "ret-2" \ No newline at end of file diff --git a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/013.phpt b/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/013.phpt deleted file mode 100644 index f419958c5..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/013.phpt +++ /dev/null @@ -1,33 +0,0 @@ ---TEST-- -Test keys() ---SKIPIF-- - ---FILE-- -keys()); - -$p['foo'] = 'bar'; -$p[] = 'foo'; - -var_dump($p->keys()); - -unset($p['foo']); - -var_dump($p->keys()); -?> ---EXPECTF-- -array(0) { -} -array(2) { - [0]=> - string(3) "foo" - [1]=> - int(0) -} -array(1) { - [0]=> - int(0) -} \ No newline at end of file diff --git a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/014.phpt b/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/014.phpt deleted file mode 100644 index ac937213a..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/014.phpt +++ /dev/null @@ -1,30 +0,0 @@ ---TEST-- -Test raw() ---SKIPIF-- - ---FILE-- -raw('foo')); -var_dump($p[42]); - -unset($p['foo']); - -try { - $p->raw('foo'); - echo "expected exception"; -} catch (InvalidArgumentException $e) { } ---EXPECTF-- -string(8) "called-2" -string(5) "ret-2" -object(Closure)#%i (0) { -} -string(8) "called-2" -string(5) "ret-2" \ No newline at end of file diff --git a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/015.phpt b/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/015.phpt deleted file mode 100644 index 314f008ac..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/015.phpt +++ /dev/null @@ -1,17 +0,0 @@ ---TEST-- -Test protect() ---SKIPIF-- - ---FILE-- -protect($f); - -var_dump($p['foo']); ---EXPECTF-- -object(Closure)#%i (0) { -} \ No newline at end of file diff --git a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/016.phpt b/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/016.phpt deleted file mode 100644 index e55edb0a7..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/016.phpt +++ /dev/null @@ -1,24 +0,0 @@ ---TEST-- -Test extend() ---SKIPIF-- - ---FILE-- -extend(12, function ($w) { var_dump($w); return 'bar'; }); /* $callable in code above */ - -var_dump($c('param')); ---EXPECTF-- -string(5) "param" -string(3) "foo" -string(3) "bar" \ No newline at end of file diff --git a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/017.phpt b/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/017.phpt deleted file mode 100644 index bac23ce09..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/017.phpt +++ /dev/null @@ -1,17 +0,0 @@ ---TEST-- -Test extend() with exception in service extension ---SKIPIF-- - ---FILE-- -extend(12, function ($w) { throw new BadMethodCallException; }); - -try { - $p[12]; - echo "Exception expected"; -} catch (BadMethodCallException $e) { } ---EXPECTF-- diff --git a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/017_1.phpt b/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/017_1.phpt deleted file mode 100644 index 8f881d6eb..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/017_1.phpt +++ /dev/null @@ -1,17 +0,0 @@ ---TEST-- -Test extend() with exception in service factory ---SKIPIF-- - ---FILE-- -extend(12, function ($w) { return 'foobar'; }); - -try { - $p[12]; - echo "Exception expected"; -} catch (BadMethodCallException $e) { } ---EXPECTF-- diff --git a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/018.phpt b/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/018.phpt deleted file mode 100644 index 27c12a14e..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/018.phpt +++ /dev/null @@ -1,23 +0,0 @@ ---TEST-- -Test register() ---SKIPIF-- - ---FILE-- -register(new Foo, array(42 => 'bar')); - -var_dump($p[42]); ---EXPECTF-- -object(Pimple\Container)#1 (0) { -} -string(3) "bar" \ No newline at end of file diff --git a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/019.phpt b/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/019.phpt deleted file mode 100644 index 28a9aecac..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/019.phpt +++ /dev/null @@ -1,18 +0,0 @@ ---TEST-- -Test register() returns static and is a fluent interface ---SKIPIF-- - ---FILE-- -register(new Foo)); ---EXPECTF-- -bool(true) diff --git a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/bench.phpb b/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/bench.phpb deleted file mode 100644 index 8f983e656..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/bench.phpb +++ /dev/null @@ -1,51 +0,0 @@ -factory($factory); - -$p['factory'] = $factory; - -echo $p['factory']; -echo $p['factory']; -echo $p['factory']; - -} - -echo microtime(true) - $time; diff --git a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/bench_shared.phpb b/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/bench_shared.phpb deleted file mode 100644 index aec541f0b..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/ext/pimple/tests/bench_shared.phpb +++ /dev/null @@ -1,25 +0,0 @@ - diff --git a/advancedcontentfilter/vendor/pimple/pimple/phpunit.xml.dist b/advancedcontentfilter/vendor/pimple/pimple/phpunit.xml.dist deleted file mode 100644 index 5c8d487fe..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/phpunit.xml.dist +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - ./src/Pimple/Tests - - - diff --git a/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Container.php b/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Container.php deleted file mode 100644 index 707b92b82..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Container.php +++ /dev/null @@ -1,298 +0,0 @@ -factories = new \SplObjectStorage(); - $this->protected = new \SplObjectStorage(); - - foreach ($values as $key => $value) { - $this->offsetSet($key, $value); - } - } - - /** - * Sets a parameter or an object. - * - * Objects must be defined as Closures. - * - * Allowing any PHP callable leads to difficult to debug problems - * as function names (strings) are callable (creating a function with - * the same name as an existing parameter would break your container). - * - * @param string $id The unique identifier for the parameter or object - * @param mixed $value The value of the parameter or a closure to define an object - * - * @throws FrozenServiceException Prevent override of a frozen service - */ - public function offsetSet($id, $value) - { - if (isset($this->frozen[$id])) { - throw new FrozenServiceException($id); - } - - $this->values[$id] = $value; - $this->keys[$id] = true; - } - - /** - * Gets a parameter or an object. - * - * @param string $id The unique identifier for the parameter or object - * - * @return mixed The value of the parameter or an object - * - * @throws UnknownIdentifierException If the identifier is not defined - */ - public function offsetGet($id) - { - if (!isset($this->keys[$id])) { - throw new UnknownIdentifierException($id); - } - - if ( - isset($this->raw[$id]) - || !\is_object($this->values[$id]) - || isset($this->protected[$this->values[$id]]) - || !\method_exists($this->values[$id], '__invoke') - ) { - return $this->values[$id]; - } - - if (isset($this->factories[$this->values[$id]])) { - return $this->values[$id]($this); - } - - $raw = $this->values[$id]; - $val = $this->values[$id] = $raw($this); - $this->raw[$id] = $raw; - - $this->frozen[$id] = true; - - return $val; - } - - /** - * Checks if a parameter or an object is set. - * - * @param string $id The unique identifier for the parameter or object - * - * @return bool - */ - public function offsetExists($id) - { - return isset($this->keys[$id]); - } - - /** - * Unsets a parameter or an object. - * - * @param string $id The unique identifier for the parameter or object - */ - public function offsetUnset($id) - { - if (isset($this->keys[$id])) { - if (\is_object($this->values[$id])) { - unset($this->factories[$this->values[$id]], $this->protected[$this->values[$id]]); - } - - unset($this->values[$id], $this->frozen[$id], $this->raw[$id], $this->keys[$id]); - } - } - - /** - * Marks a callable as being a factory service. - * - * @param callable $callable A service definition to be used as a factory - * - * @return callable The passed callable - * - * @throws ExpectedInvokableException Service definition has to be a closure or an invokable object - */ - public function factory($callable) - { - if (!\method_exists($callable, '__invoke')) { - throw new ExpectedInvokableException('Service definition is not a Closure or invokable object.'); - } - - $this->factories->attach($callable); - - return $callable; - } - - /** - * Protects a callable from being interpreted as a service. - * - * This is useful when you want to store a callable as a parameter. - * - * @param callable $callable A callable to protect from being evaluated - * - * @return callable The passed callable - * - * @throws ExpectedInvokableException Service definition has to be a closure or an invokable object - */ - public function protect($callable) - { - if (!\method_exists($callable, '__invoke')) { - throw new ExpectedInvokableException('Callable is not a Closure or invokable object.'); - } - - $this->protected->attach($callable); - - return $callable; - } - - /** - * Gets a parameter or the closure defining an object. - * - * @param string $id The unique identifier for the parameter or object - * - * @return mixed The value of the parameter or the closure defining an object - * - * @throws UnknownIdentifierException If the identifier is not defined - */ - public function raw($id) - { - if (!isset($this->keys[$id])) { - throw new UnknownIdentifierException($id); - } - - if (isset($this->raw[$id])) { - return $this->raw[$id]; - } - - return $this->values[$id]; - } - - /** - * Extends an object definition. - * - * Useful when you want to extend an existing object definition, - * without necessarily loading that object. - * - * @param string $id The unique identifier for the object - * @param callable $callable A service definition to extend the original - * - * @return callable The wrapped callable - * - * @throws UnknownIdentifierException If the identifier is not defined - * @throws FrozenServiceException If the service is frozen - * @throws InvalidServiceIdentifierException If the identifier belongs to a parameter - * @throws ExpectedInvokableException If the extension callable is not a closure or an invokable object - */ - public function extend($id, $callable) - { - if (!isset($this->keys[$id])) { - throw new UnknownIdentifierException($id); - } - - if (isset($this->frozen[$id])) { - throw new FrozenServiceException($id); - } - - if (!\is_object($this->values[$id]) || !\method_exists($this->values[$id], '__invoke')) { - throw new InvalidServiceIdentifierException($id); - } - - if (isset($this->protected[$this->values[$id]])) { - @\trigger_error(\sprintf('How Pimple behaves when extending protected closures will be fixed in Pimple 4. Are you sure "%s" should be protected?', $id), \E_USER_DEPRECATED); - } - - if (!\is_object($callable) || !\method_exists($callable, '__invoke')) { - throw new ExpectedInvokableException('Extension service definition is not a Closure or invokable object.'); - } - - $factory = $this->values[$id]; - - $extended = function ($c) use ($callable, $factory) { - return $callable($factory($c), $c); - }; - - if (isset($this->factories[$factory])) { - $this->factories->detach($factory); - $this->factories->attach($extended); - } - - return $this[$id] = $extended; - } - - /** - * Returns all defined value names. - * - * @return array An array of value names - */ - public function keys() - { - return \array_keys($this->values); - } - - /** - * Registers a service provider. - * - * @param ServiceProviderInterface $provider A ServiceProviderInterface instance - * @param array $values An array of values that customizes the provider - * - * @return static - */ - public function register(ServiceProviderInterface $provider, array $values = array()) - { - $provider->register($this); - - foreach ($values as $key => $value) { - $this[$key] = $value; - } - - return $this; - } -} diff --git a/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Exception/ExpectedInvokableException.php b/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Exception/ExpectedInvokableException.php deleted file mode 100644 index 7228421b1..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Exception/ExpectedInvokableException.php +++ /dev/null @@ -1,38 +0,0 @@ - - */ -class ExpectedInvokableException extends \InvalidArgumentException implements ContainerExceptionInterface -{ -} diff --git a/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Exception/FrozenServiceException.php b/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Exception/FrozenServiceException.php deleted file mode 100644 index e4d2f6d36..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Exception/FrozenServiceException.php +++ /dev/null @@ -1,45 +0,0 @@ - - */ -class FrozenServiceException extends \RuntimeException implements ContainerExceptionInterface -{ - /** - * @param string $id Identifier of the frozen service - */ - public function __construct($id) - { - parent::__construct(\sprintf('Cannot override frozen service "%s".', $id)); - } -} diff --git a/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Exception/InvalidServiceIdentifierException.php b/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Exception/InvalidServiceIdentifierException.php deleted file mode 100644 index 91e82f98c..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Exception/InvalidServiceIdentifierException.php +++ /dev/null @@ -1,45 +0,0 @@ - - */ -class InvalidServiceIdentifierException extends \InvalidArgumentException implements NotFoundExceptionInterface -{ - /** - * @param string $id The invalid identifier - */ - public function __construct($id) - { - parent::__construct(\sprintf('Identifier "%s" does not contain an object definition.', $id)); - } -} diff --git a/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Exception/UnknownIdentifierException.php b/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Exception/UnknownIdentifierException.php deleted file mode 100644 index fb6b626e2..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Exception/UnknownIdentifierException.php +++ /dev/null @@ -1,45 +0,0 @@ - - */ -class UnknownIdentifierException extends \InvalidArgumentException implements NotFoundExceptionInterface -{ - /** - * @param string $id The unknown identifier - */ - public function __construct($id) - { - parent::__construct(\sprintf('Identifier "%s" is not defined.', $id)); - } -} diff --git a/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Psr11/Container.php b/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Psr11/Container.php deleted file mode 100644 index cadbfffad..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Psr11/Container.php +++ /dev/null @@ -1,55 +0,0 @@ - - */ -final class Container implements ContainerInterface -{ - private $pimple; - - public function __construct(PimpleContainer $pimple) - { - $this->pimple = $pimple; - } - - public function get($id) - { - return $this->pimple[$id]; - } - - public function has($id) - { - return isset($this->pimple[$id]); - } -} diff --git a/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Psr11/ServiceLocator.php b/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Psr11/ServiceLocator.php deleted file mode 100644 index 3361c6f19..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Psr11/ServiceLocator.php +++ /dev/null @@ -1,75 +0,0 @@ - - */ -class ServiceLocator implements ContainerInterface -{ - private $container; - private $aliases = array(); - - /** - * @param PimpleContainer $container The Container instance used to locate services - * @param array $ids Array of service ids that can be located. String keys can be used to define aliases - */ - public function __construct(PimpleContainer $container, array $ids) - { - $this->container = $container; - - foreach ($ids as $key => $id) { - $this->aliases[\is_int($key) ? $id : $key] = $id; - } - } - - /** - * {@inheritdoc} - */ - public function get($id) - { - if (!isset($this->aliases[$id])) { - throw new UnknownIdentifierException($id); - } - - return $this->container[$this->aliases[$id]]; - } - - /** - * {@inheritdoc} - */ - public function has($id) - { - return isset($this->aliases[$id]) && isset($this->container[$this->aliases[$id]]); - } -} diff --git a/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/ServiceIterator.php b/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/ServiceIterator.php deleted file mode 100644 index 5cde5188f..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/ServiceIterator.php +++ /dev/null @@ -1,69 +0,0 @@ - - */ -final class ServiceIterator implements \Iterator -{ - private $container; - private $ids; - - public function __construct(Container $container, array $ids) - { - $this->container = $container; - $this->ids = $ids; - } - - public function rewind() - { - \reset($this->ids); - } - - public function current() - { - return $this->container[\current($this->ids)]; - } - - public function key() - { - return \current($this->ids); - } - - public function next() - { - \next($this->ids); - } - - public function valid() - { - return null !== \key($this->ids); - } -} diff --git a/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/ServiceProviderInterface.php b/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/ServiceProviderInterface.php deleted file mode 100644 index c004594ba..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/ServiceProviderInterface.php +++ /dev/null @@ -1,46 +0,0 @@ -value = $value; - - return $service; - } -} diff --git a/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/NonInvokable.php b/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/NonInvokable.php deleted file mode 100644 index 33cd4e548..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/NonInvokable.php +++ /dev/null @@ -1,34 +0,0 @@ -factory(function () { - return new Service(); - }); - } -} diff --git a/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Service.php b/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Service.php deleted file mode 100644 index d71b184dd..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Service.php +++ /dev/null @@ -1,35 +0,0 @@ - - */ -class Service -{ - public $value; -} diff --git a/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php b/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php deleted file mode 100644 index 8e5c4c73d..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php +++ /dev/null @@ -1,76 +0,0 @@ - - */ -class PimpleServiceProviderInterfaceTest extends \PHPUnit_Framework_TestCase -{ - public function testProvider() - { - $pimple = new Container(); - - $pimpleServiceProvider = new Fixtures\PimpleServiceProvider(); - $pimpleServiceProvider->register($pimple); - - $this->assertEquals('value', $pimple['param']); - $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $pimple['service']); - - $serviceOne = $pimple['factory']; - $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne); - - $serviceTwo = $pimple['factory']; - $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo); - - $this->assertNotSame($serviceOne, $serviceTwo); - } - - public function testProviderWithRegisterMethod() - { - $pimple = new Container(); - - $pimple->register(new Fixtures\PimpleServiceProvider(), array( - 'anotherParameter' => 'anotherValue', - )); - - $this->assertEquals('value', $pimple['param']); - $this->assertEquals('anotherValue', $pimple['anotherParameter']); - - $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $pimple['service']); - - $serviceOne = $pimple['factory']; - $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne); - - $serviceTwo = $pimple['factory']; - $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo); - - $this->assertNotSame($serviceOne, $serviceTwo); - } -} diff --git a/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Tests/PimpleTest.php b/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Tests/PimpleTest.php deleted file mode 100644 index acb66e000..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Tests/PimpleTest.php +++ /dev/null @@ -1,589 +0,0 @@ - - */ -class PimpleTest extends \PHPUnit_Framework_TestCase -{ - public function testWithString() - { - $pimple = new Container(); - $pimple['param'] = 'value'; - - $this->assertEquals('value', $pimple['param']); - } - - public function testWithClosure() - { - $pimple = new Container(); - $pimple['service'] = function () { - return new Fixtures\Service(); - }; - - $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $pimple['service']); - } - - public function testServicesShouldBeDifferent() - { - $pimple = new Container(); - $pimple['service'] = $pimple->factory(function () { - return new Fixtures\Service(); - }); - - $serviceOne = $pimple['service']; - $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne); - - $serviceTwo = $pimple['service']; - $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo); - - $this->assertNotSame($serviceOne, $serviceTwo); - } - - public function testShouldPassContainerAsParameter() - { - $pimple = new Container(); - $pimple['service'] = function () { - return new Fixtures\Service(); - }; - $pimple['container'] = function ($container) { - return $container; - }; - - $this->assertNotSame($pimple, $pimple['service']); - $this->assertSame($pimple, $pimple['container']); - } - - public function testIsset() - { - $pimple = new Container(); - $pimple['param'] = 'value'; - $pimple['service'] = function () { - return new Fixtures\Service(); - }; - - $pimple['null'] = null; - - $this->assertTrue(isset($pimple['param'])); - $this->assertTrue(isset($pimple['service'])); - $this->assertTrue(isset($pimple['null'])); - $this->assertFalse(isset($pimple['non_existent'])); - } - - public function testConstructorInjection() - { - $params = array('param' => 'value'); - $pimple = new Container($params); - - $this->assertSame($params['param'], $pimple['param']); - } - - /** - * @expectedException \Pimple\Exception\UnknownIdentifierException - * @expectedExceptionMessage Identifier "foo" is not defined. - */ - public function testOffsetGetValidatesKeyIsPresent() - { - $pimple = new Container(); - echo $pimple['foo']; - } - - /** - * @group legacy - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Identifier "foo" is not defined. - */ - public function testLegacyOffsetGetValidatesKeyIsPresent() - { - $pimple = new Container(); - echo $pimple['foo']; - } - - public function testOffsetGetHonorsNullValues() - { - $pimple = new Container(); - $pimple['foo'] = null; - $this->assertNull($pimple['foo']); - } - - public function testUnset() - { - $pimple = new Container(); - $pimple['param'] = 'value'; - $pimple['service'] = function () { - return new Fixtures\Service(); - }; - - unset($pimple['param'], $pimple['service']); - $this->assertFalse(isset($pimple['param'])); - $this->assertFalse(isset($pimple['service'])); - } - - /** - * @dataProvider serviceDefinitionProvider - */ - public function testShare($service) - { - $pimple = new Container(); - $pimple['shared_service'] = $service; - - $serviceOne = $pimple['shared_service']; - $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne); - - $serviceTwo = $pimple['shared_service']; - $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo); - - $this->assertSame($serviceOne, $serviceTwo); - } - - /** - * @dataProvider serviceDefinitionProvider - */ - public function testProtect($service) - { - $pimple = new Container(); - $pimple['protected'] = $pimple->protect($service); - - $this->assertSame($service, $pimple['protected']); - } - - public function testGlobalFunctionNameAsParameterValue() - { - $pimple = new Container(); - $pimple['global_function'] = 'strlen'; - $this->assertSame('strlen', $pimple['global_function']); - } - - public function testRaw() - { - $pimple = new Container(); - $pimple['service'] = $definition = $pimple->factory(function () { return 'foo'; }); - $this->assertSame($definition, $pimple->raw('service')); - } - - public function testRawHonorsNullValues() - { - $pimple = new Container(); - $pimple['foo'] = null; - $this->assertNull($pimple->raw('foo')); - } - - public function testFluentRegister() - { - $pimple = new Container(); - $this->assertSame($pimple, $pimple->register($this->getMockBuilder('Pimple\ServiceProviderInterface')->getMock())); - } - - /** - * @expectedException \Pimple\Exception\UnknownIdentifierException - * @expectedExceptionMessage Identifier "foo" is not defined. - */ - public function testRawValidatesKeyIsPresent() - { - $pimple = new Container(); - $pimple->raw('foo'); - } - - /** - * @group legacy - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Identifier "foo" is not defined. - */ - public function testLegacyRawValidatesKeyIsPresent() - { - $pimple = new Container(); - $pimple->raw('foo'); - } - - /** - * @dataProvider serviceDefinitionProvider - */ - public function testExtend($service) - { - $pimple = new Container(); - $pimple['shared_service'] = function () { - return new Fixtures\Service(); - }; - $pimple['factory_service'] = $pimple->factory(function () { - return new Fixtures\Service(); - }); - - $pimple->extend('shared_service', $service); - $serviceOne = $pimple['shared_service']; - $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne); - $serviceTwo = $pimple['shared_service']; - $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo); - $this->assertSame($serviceOne, $serviceTwo); - $this->assertSame($serviceOne->value, $serviceTwo->value); - - $pimple->extend('factory_service', $service); - $serviceOne = $pimple['factory_service']; - $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne); - $serviceTwo = $pimple['factory_service']; - $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo); - $this->assertNotSame($serviceOne, $serviceTwo); - $this->assertNotSame($serviceOne->value, $serviceTwo->value); - } - - public function testExtendDoesNotLeakWithFactories() - { - if (extension_loaded('pimple')) { - $this->markTestSkipped('Pimple extension does not support this test'); - } - $pimple = new Container(); - - $pimple['foo'] = $pimple->factory(function () { return; }); - $pimple['foo'] = $pimple->extend('foo', function ($foo, $pimple) { return; }); - unset($pimple['foo']); - - $p = new \ReflectionProperty($pimple, 'values'); - $p->setAccessible(true); - $this->assertEmpty($p->getValue($pimple)); - - $p = new \ReflectionProperty($pimple, 'factories'); - $p->setAccessible(true); - $this->assertCount(0, $p->getValue($pimple)); - } - - /** - * @expectedException \Pimple\Exception\UnknownIdentifierException - * @expectedExceptionMessage Identifier "foo" is not defined. - */ - public function testExtendValidatesKeyIsPresent() - { - $pimple = new Container(); - $pimple->extend('foo', function () {}); - } - - /** - * @group legacy - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Identifier "foo" is not defined. - */ - public function testLegacyExtendValidatesKeyIsPresent() - { - $pimple = new Container(); - $pimple->extend('foo', function () {}); - } - - public function testKeys() - { - $pimple = new Container(); - $pimple['foo'] = 123; - $pimple['bar'] = 123; - - $this->assertEquals(array('foo', 'bar'), $pimple->keys()); - } - - /** @test */ - public function settingAnInvokableObjectShouldTreatItAsFactory() - { - $pimple = new Container(); - $pimple['invokable'] = new Fixtures\Invokable(); - - $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $pimple['invokable']); - } - - /** @test */ - public function settingNonInvokableObjectShouldTreatItAsParameter() - { - $pimple = new Container(); - $pimple['non_invokable'] = new Fixtures\NonInvokable(); - - $this->assertInstanceOf('Pimple\Tests\Fixtures\NonInvokable', $pimple['non_invokable']); - } - - /** - * @dataProvider badServiceDefinitionProvider - * @expectedException \Pimple\Exception\ExpectedInvokableException - * @expectedExceptionMessage Service definition is not a Closure or invokable object. - */ - public function testFactoryFailsForInvalidServiceDefinitions($service) - { - $pimple = new Container(); - $pimple->factory($service); - } - - /** - * @group legacy - * @dataProvider badServiceDefinitionProvider - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Service definition is not a Closure or invokable object. - */ - public function testLegacyFactoryFailsForInvalidServiceDefinitions($service) - { - $pimple = new Container(); - $pimple->factory($service); - } - - /** - * @dataProvider badServiceDefinitionProvider - * @expectedException \Pimple\Exception\ExpectedInvokableException - * @expectedExceptionMessage Callable is not a Closure or invokable object. - */ - public function testProtectFailsForInvalidServiceDefinitions($service) - { - $pimple = new Container(); - $pimple->protect($service); - } - - /** - * @group legacy - * @dataProvider badServiceDefinitionProvider - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Callable is not a Closure or invokable object. - */ - public function testLegacyProtectFailsForInvalidServiceDefinitions($service) - { - $pimple = new Container(); - $pimple->protect($service); - } - - /** - * @dataProvider badServiceDefinitionProvider - * @expectedException \Pimple\Exception\InvalidServiceIdentifierException - * @expectedExceptionMessage Identifier "foo" does not contain an object definition. - */ - public function testExtendFailsForKeysNotContainingServiceDefinitions($service) - { - $pimple = new Container(); - $pimple['foo'] = $service; - $pimple->extend('foo', function () {}); - } - - /** - * @group legacy - * @dataProvider badServiceDefinitionProvider - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Identifier "foo" does not contain an object definition. - */ - public function testLegacyExtendFailsForKeysNotContainingServiceDefinitions($service) - { - $pimple = new Container(); - $pimple['foo'] = $service; - $pimple->extend('foo', function () {}); - } - - /** - * @group legacy - * @expectedDeprecation How Pimple behaves when extending protected closures will be fixed in Pimple 4. Are you sure "foo" should be protected? - */ - public function testExtendingProtectedClosureDeprecation() - { - $pimple = new Container(); - $pimple['foo'] = $pimple->protect(function () { - return 'bar'; - }); - - $pimple->extend('foo', function ($value) { - return $value.'-baz'; - }); - - $this->assertSame('bar-baz', $pimple['foo']); - } - - /** - * @dataProvider badServiceDefinitionProvider - * @expectedException \Pimple\Exception\ExpectedInvokableException - * @expectedExceptionMessage Extension service definition is not a Closure or invokable object. - */ - public function testExtendFailsForInvalidServiceDefinitions($service) - { - $pimple = new Container(); - $pimple['foo'] = function () {}; - $pimple->extend('foo', $service); - } - - /** - * @group legacy - * @dataProvider badServiceDefinitionProvider - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Extension service definition is not a Closure or invokable object. - */ - public function testLegacyExtendFailsForInvalidServiceDefinitions($service) - { - $pimple = new Container(); - $pimple['foo'] = function () {}; - $pimple->extend('foo', $service); - } - - /** - * @expectedException \Pimple\Exception\FrozenServiceException - * @expectedExceptionMessage Cannot override frozen service "foo". - */ - public function testExtendFailsIfFrozenServiceIsNonInvokable() - { - $pimple = new Container(); - $pimple['foo'] = function () { - return new Fixtures\NonInvokable(); - }; - $foo = $pimple['foo']; - - $pimple->extend('foo', function () {}); - } - - /** - * @expectedException \Pimple\Exception\FrozenServiceException - * @expectedExceptionMessage Cannot override frozen service "foo". - */ - public function testExtendFailsIfFrozenServiceIsInvokable() - { - $pimple = new Container(); - $pimple['foo'] = function () { - return new Fixtures\Invokable(); - }; - $foo = $pimple['foo']; - - $pimple->extend('foo', function () {}); - } - - /** - * Provider for invalid service definitions. - */ - public function badServiceDefinitionProvider() - { - return array( - array(123), - array(new Fixtures\NonInvokable()), - ); - } - - /** - * Provider for service definitions. - */ - public function serviceDefinitionProvider() - { - return array( - array(function ($value) { - $service = new Fixtures\Service(); - $service->value = $value; - - return $service; - }), - array(new Fixtures\Invokable()), - ); - } - - public function testDefiningNewServiceAfterFreeze() - { - $pimple = new Container(); - $pimple['foo'] = function () { - return 'foo'; - }; - $foo = $pimple['foo']; - - $pimple['bar'] = function () { - return 'bar'; - }; - $this->assertSame('bar', $pimple['bar']); - } - - /** - * @expectedException \Pimple\Exception\FrozenServiceException - * @expectedExceptionMessage Cannot override frozen service "foo". - */ - public function testOverridingServiceAfterFreeze() - { - $pimple = new Container(); - $pimple['foo'] = function () { - return 'foo'; - }; - $foo = $pimple['foo']; - - $pimple['foo'] = function () { - return 'bar'; - }; - } - - /** - * @group legacy - * @expectedException \RuntimeException - * @expectedExceptionMessage Cannot override frozen service "foo". - */ - public function testLegacyOverridingServiceAfterFreeze() - { - $pimple = new Container(); - $pimple['foo'] = function () { - return 'foo'; - }; - $foo = $pimple['foo']; - - $pimple['foo'] = function () { - return 'bar'; - }; - } - - public function testRemovingServiceAfterFreeze() - { - $pimple = new Container(); - $pimple['foo'] = function () { - return 'foo'; - }; - $foo = $pimple['foo']; - - unset($pimple['foo']); - $pimple['foo'] = function () { - return 'bar'; - }; - $this->assertSame('bar', $pimple['foo']); - } - - public function testExtendingService() - { - $pimple = new Container(); - $pimple['foo'] = function () { - return 'foo'; - }; - $pimple['foo'] = $pimple->extend('foo', function ($foo, $app) { - return "$foo.bar"; - }); - $pimple['foo'] = $pimple->extend('foo', function ($foo, $app) { - return "$foo.baz"; - }); - $this->assertSame('foo.bar.baz', $pimple['foo']); - } - - public function testExtendingServiceAfterOtherServiceFreeze() - { - $pimple = new Container(); - $pimple['foo'] = function () { - return 'foo'; - }; - $pimple['bar'] = function () { - return 'bar'; - }; - $foo = $pimple['foo']; - - $pimple['bar'] = $pimple->extend('bar', function ($bar, $app) { - return "$bar.baz"; - }); - $this->assertSame('bar.baz', $pimple['bar']); - } -} diff --git a/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Tests/Psr11/ContainerTest.php b/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Tests/Psr11/ContainerTest.php deleted file mode 100644 index 7ca2d7fff..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Tests/Psr11/ContainerTest.php +++ /dev/null @@ -1,77 +0,0 @@ -assertSame($pimple['service'], $psr->get('service')); - } - - /** - * @expectedException \Psr\Container\NotFoundExceptionInterface - * @expectedExceptionMessage Identifier "service" is not defined. - */ - public function testGetThrowsExceptionIfServiceIsNotFound() - { - $pimple = new Container(); - $psr = new PsrContainer($pimple); - - $psr->get('service'); - } - - public function testHasReturnsTrueIfServiceExists() - { - $pimple = new Container(); - $pimple['service'] = function () { - return new Service(); - }; - $psr = new PsrContainer($pimple); - - $this->assertTrue($psr->has('service')); - } - - public function testHasReturnsFalseIfServiceDoesNotExist() - { - $pimple = new Container(); - $psr = new PsrContainer($pimple); - - $this->assertFalse($psr->has('service')); - } -} diff --git a/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Tests/Psr11/ServiceLocatorTest.php b/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Tests/Psr11/ServiceLocatorTest.php deleted file mode 100644 index c9a081259..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Tests/Psr11/ServiceLocatorTest.php +++ /dev/null @@ -1,134 +0,0 @@ - - */ -class ServiceLocatorTest extends TestCase -{ - public function testCanAccessServices() - { - $pimple = new Container(); - $pimple['service'] = function () { - return new Fixtures\Service(); - }; - $locator = new ServiceLocator($pimple, array('service')); - - $this->assertSame($pimple['service'], $locator->get('service')); - } - - public function testCanAccessAliasedServices() - { - $pimple = new Container(); - $pimple['service'] = function () { - return new Fixtures\Service(); - }; - $locator = new ServiceLocator($pimple, array('alias' => 'service')); - - $this->assertSame($pimple['service'], $locator->get('alias')); - } - - /** - * @expectedException \Pimple\Exception\UnknownIdentifierException - * @expectedExceptionMessage Identifier "service" is not defined. - */ - public function testCannotAccessAliasedServiceUsingRealIdentifier() - { - $pimple = new Container(); - $pimple['service'] = function () { - return new Fixtures\Service(); - }; - $locator = new ServiceLocator($pimple, array('alias' => 'service')); - - $service = $locator->get('service'); - } - - /** - * @expectedException \Pimple\Exception\UnknownIdentifierException - * @expectedExceptionMessage Identifier "foo" is not defined. - */ - public function testGetValidatesServiceCanBeLocated() - { - $pimple = new Container(); - $pimple['service'] = function () { - return new Fixtures\Service(); - }; - $locator = new ServiceLocator($pimple, array('alias' => 'service')); - - $service = $locator->get('foo'); - } - - /** - * @expectedException \Pimple\Exception\UnknownIdentifierException - * @expectedExceptionMessage Identifier "invalid" is not defined. - */ - public function testGetValidatesTargetServiceExists() - { - $pimple = new Container(); - $pimple['service'] = function () { - return new Fixtures\Service(); - }; - $locator = new ServiceLocator($pimple, array('alias' => 'invalid')); - - $service = $locator->get('alias'); - } - - public function testHasValidatesServiceCanBeLocated() - { - $pimple = new Container(); - $pimple['service1'] = function () { - return new Fixtures\Service(); - }; - $pimple['service2'] = function () { - return new Fixtures\Service(); - }; - $locator = new ServiceLocator($pimple, array('service1')); - - $this->assertTrue($locator->has('service1')); - $this->assertFalse($locator->has('service2')); - } - - public function testHasChecksIfTargetServiceExists() - { - $pimple = new Container(); - $pimple['service'] = function () { - return new Fixtures\Service(); - }; - $locator = new ServiceLocator($pimple, array('foo' => 'service', 'bar' => 'invalid')); - - $this->assertTrue($locator->has('foo')); - $this->assertFalse($locator->has('bar')); - } -} diff --git a/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Tests/ServiceIteratorTest.php b/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Tests/ServiceIteratorTest.php deleted file mode 100644 index 5dd52f0d9..000000000 --- a/advancedcontentfilter/vendor/pimple/pimple/src/Pimple/Tests/ServiceIteratorTest.php +++ /dev/null @@ -1,52 +0,0 @@ -assertSame(array('service1' => $pimple['service1'], 'service2' => $pimple['service2']), iterator_to_array($iterator)); - } -} diff --git a/advancedcontentfilter/vendor/psr/container/README.md b/advancedcontentfilter/vendor/psr/container/README.md index 084f6df51..1b9d9e570 100644 --- a/advancedcontentfilter/vendor/psr/container/README.md +++ b/advancedcontentfilter/vendor/psr/container/README.md @@ -1,5 +1,13 @@ -# PSR Container +Container interface +============== -This repository holds all interfaces/classes/traits related to [PSR-11](https://github.com/container-interop/fig-standards/blob/master/proposed/container.md). +This repository holds all interfaces related to [PSR-11 (Container Interface)][psr-url]. + +Note that this is not a Container implementation of its own. It is merely abstractions that describe the components of a Dependency Injection Container. + +The installable [package][package-url] and [implementations][implementation-url] are listed on Packagist. + +[psr-url]: https://www.php-fig.org/psr/psr-11/ +[package-url]: https://packagist.org/packages/psr/container +[implementation-url]: https://packagist.org/providers/psr/container-implementation -Note that this is not a container implementation of its own. See the specification for more details. diff --git a/advancedcontentfilter/vendor/psr/container/composer.json b/advancedcontentfilter/vendor/psr/container/composer.json index b8ee01265..baf6cd1a0 100644 --- a/advancedcontentfilter/vendor/psr/container/composer.json +++ b/advancedcontentfilter/vendor/psr/container/composer.json @@ -8,11 +8,11 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "require": { - "php": ">=5.3.0" + "php": ">=7.4.0" }, "autoload": { "psr-4": { @@ -21,7 +21,7 @@ }, "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.0.x-dev" } } } diff --git a/advancedcontentfilter/vendor/psr/container/src/ContainerExceptionInterface.php b/advancedcontentfilter/vendor/psr/container/src/ContainerExceptionInterface.php index d35c6b4d8..0f213f2fe 100644 --- a/advancedcontentfilter/vendor/psr/container/src/ContainerExceptionInterface.php +++ b/advancedcontentfilter/vendor/psr/container/src/ContainerExceptionInterface.php @@ -1,13 +1,12 @@ =7.0.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + } +} diff --git a/advancedcontentfilter/vendor/psr/http-factory/src/RequestFactoryInterface.php b/advancedcontentfilter/vendor/psr/http-factory/src/RequestFactoryInterface.php new file mode 100644 index 000000000..cb39a08bf --- /dev/null +++ b/advancedcontentfilter/vendor/psr/http-factory/src/RequestFactoryInterface.php @@ -0,0 +1,18 @@ +=5.3.0" + "php": "^7.2 || ^8.0" }, "autoload": { "psr-4": { @@ -20,7 +20,7 @@ }, "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.1.x-dev" } } } diff --git a/advancedcontentfilter/vendor/psr/http-message/docs/PSR7-Interfaces.md b/advancedcontentfilter/vendor/psr/http-message/docs/PSR7-Interfaces.md new file mode 100644 index 000000000..3a7e7dda6 --- /dev/null +++ b/advancedcontentfilter/vendor/psr/http-message/docs/PSR7-Interfaces.md @@ -0,0 +1,130 @@ +# Interfaces + +The purpose of this list is to help in finding the methods when working with PSR-7. This can be considered as a cheatsheet for PSR-7 interfaces. + +The interfaces defined in PSR-7 are the following: + +| Class Name | Description | +|---|---| +| [Psr\Http\Message\MessageInterface](http://www.php-fig.org/psr/psr-7/#psrhttpmessagemessageinterface) | Representation of a HTTP message | +| [Psr\Http\Message\RequestInterface](http://www.php-fig.org/psr/psr-7/#psrhttpmessagerequestinterface) | Representation of an outgoing, client-side request. | +| [Psr\Http\Message\ServerRequestInterface](http://www.php-fig.org/psr/psr-7/#psrhttpmessageserverrequestinterface) | Representation of an incoming, server-side HTTP request. | +| [Psr\Http\Message\ResponseInterface](http://www.php-fig.org/psr/psr-7/#psrhttpmessageresponseinterface) | Representation of an outgoing, server-side response. | +| [Psr\Http\Message\StreamInterface](http://www.php-fig.org/psr/psr-7/#psrhttpmessagestreaminterface) | Describes a data stream | +| [Psr\Http\Message\UriInterface](http://www.php-fig.org/psr/psr-7/#psrhttpmessageuriinterface) | Value object representing a URI. | +| [Psr\Http\Message\UploadedFileInterface](http://www.php-fig.org/psr/psr-7/#psrhttpmessageuploadedfileinterface) | Value object representing a file uploaded through an HTTP request. | + +## `Psr\Http\Message\MessageInterface` Methods + +| Method Name | Description | Notes | +|------------------------------------| ----------- | ----- | +| `getProtocolVersion()` | Retrieve HTTP protocol version | 1.0 or 1.1 | +| `withProtocolVersion($version)` | Returns new message instance with given HTTP protocol version | | +| `getHeaders()` | Retrieve all HTTP Headers | [Request Header List](https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Request_fields), [Response Header List](https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Response_fields) | +| `hasHeader($name)` | Checks if HTTP Header with given name exists | | +| `getHeader($name)` | Retrieves a array with the values for a single header | | +| `getHeaderLine($name)` | Retrieves a comma-separated string of the values for a single header | | +| `withHeader($name, $value)` | Returns new message instance with given HTTP Header | if the header existed in the original instance, replaces the header value from the original message with the value provided when creating the new instance. | +| `withAddedHeader($name, $value)` | Returns new message instance with appended value to given header | If header already exists value will be appended, if not a new header will be created | +| `withoutHeader($name)` | Removes HTTP Header with given name| | +| `getBody()` | Retrieves the HTTP Message Body | Returns object implementing `StreamInterface`| +| `withBody(StreamInterface $body)` | Returns new message instance with given HTTP Message Body | | + + +## `Psr\Http\Message\RequestInterface` Methods + +Same methods as `Psr\Http\Message\MessageInterface` + the following methods: + +| Method Name | Description | Notes | +|------------------------------------| ----------- | ----- | +| `getRequestTarget()` | Retrieves the message's request target | origin-form, absolute-form, authority-form, asterisk-form ([RFC7230](https://www.rfc-editor.org/rfc/rfc7230.txt)) | +| `withRequestTarget($requestTarget)` | Return a new message instance with the specific request-target | | +| `getMethod()` | Retrieves the HTTP method of the request. | GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE (defined in [RFC7231](https://tools.ietf.org/html/rfc7231)), PATCH (defined in [RFC5789](https://tools.ietf.org/html/rfc5789)) | +| `withMethod($method)` | Returns a new message instance with the provided HTTP method | | +| `getUri()` | Retrieves the URI instance | | +| `withUri(UriInterface $uri, $preserveHost = false)` | Returns a new message instance with the provided URI | | + + +## `Psr\Http\Message\ServerRequestInterface` Methods + +Same methods as `Psr\Http\Message\RequestInterface` + the following methods: + +| Method Name | Description | Notes | +|------------------------------------| ----------- | ----- | +| `getServerParams() ` | Retrieve server parameters | Typically derived from `$_SERVER` | +| `getCookieParams()` | Retrieves cookies sent by the client to the server. | Typically derived from `$_COOKIES` | +| `withCookieParams(array $cookies)` | Returns a new request instance with the specified cookies | | +| `withQueryParams(array $query)` | Returns a new request instance with the specified query string arguments | | +| `getUploadedFiles()` | Retrieve normalized file upload data | | +| `withUploadedFiles(array $uploadedFiles)` | Returns a new request instance with the specified uploaded files | | +| `getParsedBody()` | Retrieve any parameters provided in the request body | | +| `withParsedBody($data)` | Returns a new request instance with the specified body parameters | | +| `getAttributes()` | Retrieve attributes derived from the request | | +| `getAttribute($name, $default = null)` | Retrieve a single derived request attribute | | +| `withAttribute($name, $value)` | Returns a new request instance with the specified derived request attribute | | +| `withoutAttribute($name)` | Returns a new request instance that without the specified derived request attribute | | + +## `Psr\Http\Message\ResponseInterface` Methods: + +Same methods as `Psr\Http\Message\MessageInterface` + the following methods: + +| Method Name | Description | Notes | +|------------------------------------| ----------- | ----- | +| `getStatusCode()` | Gets the response status code. | | +| `withStatus($code, $reasonPhrase = '')` | Returns a new response instance with the specified status code and, optionally, reason phrase. | | +| `getReasonPhrase()` | Gets the response reason phrase associated with the status code. | | + +## `Psr\Http\Message\StreamInterface` Methods + +| Method Name | Description | Notes | +|------------------------------------| ----------- | ----- | +| `__toString()` | Reads all data from the stream into a string, from the beginning to end. | | +| `close()` | Closes the stream and any underlying resources. | | +| `detach()` | Separates any underlying resources from the stream. | | +| `getSize()` | Get the size of the stream if known. | | +| `eof()` | Returns true if the stream is at the end of the stream.| | +| `isSeekable()` | Returns whether or not the stream is seekable. | | +| `seek($offset, $whence = SEEK_SET)` | Seek to a position in the stream. | | +| `rewind()` | Seek to the beginning of the stream. | | +| `isWritable()` | Returns whether or not the stream is writable. | | +| `write($string)` | Write data to the stream. | | +| `isReadable()` | Returns whether or not the stream is readable. | | +| `read($length)` | Read data from the stream. | | +| `getContents()` | Returns the remaining contents in a string | | +| `getMetadata($key = null)()` | Get stream metadata as an associative array or retrieve a specific key. | | + +## `Psr\Http\Message\UriInterface` Methods + +| Method Name | Description | Notes | +|------------------------------------| ----------- | ----- | +| `getScheme()` | Retrieve the scheme component of the URI. | | +| `getAuthority()` | Retrieve the authority component of the URI. | | +| `getUserInfo()` | Retrieve the user information component of the URI. | | +| `getHost()` | Retrieve the host component of the URI. | | +| `getPort()` | Retrieve the port component of the URI. | | +| `getPath()` | Retrieve the path component of the URI. | | +| `getQuery()` | Retrieve the query string of the URI. | | +| `getFragment()` | Retrieve the fragment component of the URI. | | +| `withScheme($scheme)` | Return an instance with the specified scheme. | | +| `withUserInfo($user, $password = null)` | Return an instance with the specified user information. | | +| `withHost($host)` | Return an instance with the specified host. | | +| `withPort($port)` | Return an instance with the specified port. | | +| `withPath($path)` | Return an instance with the specified path. | | +| `withQuery($query)` | Return an instance with the specified query string. | | +| `withFragment($fragment)` | Return an instance with the specified URI fragment. | | +| `__toString()` | Return the string representation as a URI reference. | | + +## `Psr\Http\Message\UploadedFileInterface` Methods + +| Method Name | Description | Notes | +|------------------------------------| ----------- | ----- | +| `getStream()` | Retrieve a stream representing the uploaded file. | | +| `moveTo($targetPath)` | Move the uploaded file to a new location. | | +| `getSize()` | Retrieve the file size. | | +| `getError()` | Retrieve the error associated with the uploaded file. | | +| `getClientFilename()` | Retrieve the filename sent by the client. | | +| `getClientMediaType()` | Retrieve the media type sent by the client. | | + +> `RequestInterface`, `ServerRequestInterface`, `ResponseInterface` extend `MessageInterface` because the `Request` and the `Response` are `HTTP Messages`. +> When using `ServerRequestInterface`, both `RequestInterface` and `Psr\Http\Message\MessageInterface` methods are considered. + diff --git a/advancedcontentfilter/vendor/psr/http-message/docs/PSR7-Usage.md b/advancedcontentfilter/vendor/psr/http-message/docs/PSR7-Usage.md new file mode 100644 index 000000000..b6d048a34 --- /dev/null +++ b/advancedcontentfilter/vendor/psr/http-message/docs/PSR7-Usage.md @@ -0,0 +1,159 @@ +### PSR-7 Usage + +All PSR-7 applications comply with these interfaces +They were created to establish a standard between middleware implementations. + +> `RequestInterface`, `ServerRequestInterface`, `ResponseInterface` extend `MessageInterface` because the `Request` and the `Response` are `HTTP Messages`. +> When using `ServerRequestInterface`, both `RequestInterface` and `Psr\Http\Message\MessageInterface` methods are considered. + + +The following examples will illustrate how basic operations are done in PSR-7. + +##### Examples + + +For this examples to work (at least) a PSR-7 implementation package is required. (eg: zendframework/zend-diactoros, guzzlehttp/psr7, slim/slim, etc) +All PSR-7 implementations should have the same behaviour. + +The following will be assumed: +`$request` is an object of `Psr\Http\Message\RequestInterface` and + +`$response` is an object implementing `Psr\Http\Message\RequestInterface` + + +### Working with HTTP Headers + +#### Adding headers to response: + +```php +$response->withHeader('My-Custom-Header', 'My Custom Message'); +``` + +#### Appending values to headers + +```php +$response->withAddedHeader('My-Custom-Header', 'The second message'); +``` + +#### Checking if header exists: + +```php +$request->hasHeader('My-Custom-Header'); // will return false +$response->hasHeader('My-Custom-Header'); // will return true +``` + +> Note: My-Custom-Header was only added in the Response + +#### Getting comma-separated values from a header (also applies to request) + +```php +// getting value from request headers +$request->getHeaderLine('Content-Type'); // will return: "text/html; charset=UTF-8" +// getting value from response headers +$response->getHeaderLine('My-Custom-Header'); // will return: "My Custom Message; The second message" +``` + +#### Getting array of value from a header (also applies to request) +```php +// getting value from request headers +$request->getHeader('Content-Type'); // will return: ["text/html", "charset=UTF-8"] +// getting value from response headers +$response->getHeader('My-Custom-Header'); // will return: ["My Custom Message", "The second message"] +``` + +#### Removing headers from HTTP Messages +```php +// removing a header from Request, removing deprecated "Content-MD5" header +$request->withoutHeader('Content-MD5'); + +// removing a header from Response +// effect: the browser won't know the size of the stream +// the browser will download the stream till it ends +$response->withoutHeader('Content-Length'); +``` + +### Working with HTTP Message Body + +When working with the PSR-7 there are two methods of implementation: +#### 1. Getting the body separately + +> This method makes the body handling easier to understand and is useful when repeatedly calling body methods. (You only call `getBody()` once). Using this method mistakes like `$response->write()` are also prevented. + +```php +$body = $response->getBody(); +// operations on body, eg. read, write, seek +// ... +// replacing the old body +$response->withBody($body); +// this last statement is optional as we working with objects +// in this case the "new" body is same with the "old" one +// the $body variable has the same value as the one in $request, only the reference is passed +``` + +#### 2. Working directly on response + +> This method is useful when only performing few operations as the `$request->getBody()` statement fragment is required + +```php +$response->getBody()->write('hello'); +``` + +### Getting the body contents + +The following snippet gets the contents of a stream contents. +> Note: Streams must be rewinded, if content was written into streams, it will be ignored when calling `getContents()` because the stream pointer is set to the last character, which is `\0` - meaning end of stream. +```php +$body = $response->getBody(); +$body->rewind(); // or $body->seek(0); +$bodyText = $body->getContents(); +``` +> Note: If `$body->seek(1)` is called before `$body->getContents()`, the first character will be ommited as the starting pointer is set to `1`, not `0`. This is why using `$body->rewind()` is recommended. + +### Append to body + +```php +$response->getBody()->write('Hello'); // writing directly +$body = $request->getBody(); // which is a `StreamInterface` +$body->write('xxxxx'); +``` + +### Prepend to body +Prepending is different when it comes to streams. The content must be copied before writing the content to be prepended. +The following example will explain the behaviour of streams. + +```php +// assuming our response is initially empty +$body = $repsonse->getBody(); +// writing the string "abcd" +$body->write('abcd'); + +// seeking to start of stream +$body->seek(0); +// writing 'ef' +$body->write('ef'); // at this point the stream contains "efcd" +``` + +#### Prepending by rewriting separately + +```php +// assuming our response body stream only contains: "abcd" +$body = $response->getBody(); +$body->rewind(); +$contents = $body->getContents(); // abcd +// seeking the stream to beginning +$body->rewind(); +$body->write('ef'); // stream contains "efcd" +$body->write($contents); // stream contains "efabcd" +``` + +> Note: `getContents()` seeks the stream while reading it, therefore if the second `rewind()` method call was not present the stream would have resulted in `abcdefabcd` because the `write()` method appends to stream if not preceeded by `rewind()` or `seek(0)`. + +#### Prepending by using contents as a string +```php +$body = $response->getBody(); +$body->rewind(); +$contents = $body->getContents(); // efabcd +$contents = 'ef'.$contents; +$body->rewind(); +$body->write($contents); +``` diff --git a/advancedcontentfilter/vendor/psr/http-message/src/MessageInterface.php b/advancedcontentfilter/vendor/psr/http-message/src/MessageInterface.php index dd46e5ec8..8cdb4ed63 100644 --- a/advancedcontentfilter/vendor/psr/http-message/src/MessageInterface.php +++ b/advancedcontentfilter/vendor/psr/http-message/src/MessageInterface.php @@ -1,5 +1,7 @@ =7.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Server\\": "src/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + } +} diff --git a/advancedcontentfilter/vendor/psr/http-server-handler/src/RequestHandlerInterface.php b/advancedcontentfilter/vendor/psr/http-server-handler/src/RequestHandlerInterface.php new file mode 100644 index 000000000..83911e265 --- /dev/null +++ b/advancedcontentfilter/vendor/psr/http-server-handler/src/RequestHandlerInterface.php @@ -0,0 +1,22 @@ +=7.0", + "psr/http-message": "^1.0 || ^2.0", + "psr/http-server-handler": "^1.0" + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Server\\": "src/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + } +} diff --git a/advancedcontentfilter/vendor/psr/http-server-middleware/src/MiddlewareInterface.php b/advancedcontentfilter/vendor/psr/http-server-middleware/src/MiddlewareInterface.php new file mode 100644 index 000000000..a6c14f8c7 --- /dev/null +++ b/advancedcontentfilter/vendor/psr/http-server-middleware/src/MiddlewareInterface.php @@ -0,0 +1,25 @@ + true, 'null' => null, @@ -110,6 +114,7 @@ abstract class LoggerInterfaceTest extends \PHPUnit_Framework_TestCase 'nested' => array('with object' => new DummyTest), 'object' => new \DateTime, 'resource' => fopen('php://memory', 'r'), + 'closed' => $closed, ); $this->getLogger()->warning('Crazy context data', $context); @@ -131,10 +136,3 @@ abstract class LoggerInterfaceTest extends \PHPUnit_Framework_TestCase $this->assertEquals($expected, $this->getLogs()); } } - -class DummyTest -{ - public function __toString() - { - } -} diff --git a/advancedcontentfilter/vendor/psr/log/Psr/Log/Test/TestLogger.php b/advancedcontentfilter/vendor/psr/log/Psr/Log/Test/TestLogger.php new file mode 100644 index 000000000..1be323049 --- /dev/null +++ b/advancedcontentfilter/vendor/psr/log/Psr/Log/Test/TestLogger.php @@ -0,0 +1,147 @@ + $level, + 'message' => $message, + 'context' => $context, + ]; + + $this->recordsByLevel[$record['level']][] = $record; + $this->records[] = $record; + } + + public function hasRecords($level) + { + return isset($this->recordsByLevel[$level]); + } + + public function hasRecord($record, $level) + { + if (is_string($record)) { + $record = ['message' => $record]; + } + return $this->hasRecordThatPasses(function ($rec) use ($record) { + if ($rec['message'] !== $record['message']) { + return false; + } + if (isset($record['context']) && $rec['context'] !== $record['context']) { + return false; + } + return true; + }, $level); + } + + public function hasRecordThatContains($message, $level) + { + return $this->hasRecordThatPasses(function ($rec) use ($message) { + return strpos($rec['message'], $message) !== false; + }, $level); + } + + public function hasRecordThatMatches($regex, $level) + { + return $this->hasRecordThatPasses(function ($rec) use ($regex) { + return preg_match($regex, $rec['message']) > 0; + }, $level); + } + + public function hasRecordThatPasses(callable $predicate, $level) + { + if (!isset($this->recordsByLevel[$level])) { + return false; + } + foreach ($this->recordsByLevel[$level] as $i => $rec) { + if (call_user_func($predicate, $rec, $i)) { + return true; + } + } + return false; + } + + public function __call($method, $args) + { + if (preg_match('/(.*)(Debug|Info|Notice|Warning|Error|Critical|Alert|Emergency)(.*)/', $method, $matches) > 0) { + $genericMethod = $matches[1] . ('Records' !== $matches[3] ? 'Record' : '') . $matches[3]; + $level = strtolower($matches[2]); + if (method_exists($this, $genericMethod)) { + $args[] = $level; + return call_user_func_array([$this, $genericMethod], $args); + } + } + throw new \BadMethodCallException('Call to undefined method ' . get_class($this) . '::' . $method . '()'); + } + + public function reset() + { + $this->records = []; + $this->recordsByLevel = []; + } +} diff --git a/advancedcontentfilter/vendor/psr/log/README.md b/advancedcontentfilter/vendor/psr/log/README.md index 574bc1cb2..a9f20c437 100644 --- a/advancedcontentfilter/vendor/psr/log/README.md +++ b/advancedcontentfilter/vendor/psr/log/README.md @@ -7,6 +7,13 @@ This repository holds all interfaces/classes/traits related to Note that this is not a logger of its own. It is merely an interface that describes a logger. See the specification for more details. +Installation +------------ + +```bash +composer require psr/log +``` + Usage ----- @@ -31,6 +38,12 @@ class Foo if ($this->logger) { $this->logger->info('Doing work'); } + + try { + $this->doSomethingElse(); + } catch (Exception $exception) { + $this->logger->error('Oh no!', array('exception' => $exception)); + } // do something useful } diff --git a/advancedcontentfilter/vendor/psr/log/composer.json b/advancedcontentfilter/vendor/psr/log/composer.json index 87934d707..ca0569537 100644 --- a/advancedcontentfilter/vendor/psr/log/composer.json +++ b/advancedcontentfilter/vendor/psr/log/composer.json @@ -7,7 +7,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "require": { @@ -20,7 +20,7 @@ }, "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.1.x-dev" } } } diff --git a/advancedcontentfilter/vendor/slim/slim/CHANGELOG.md b/advancedcontentfilter/vendor/slim/slim/CHANGELOG.md new file mode 100644 index 000000000..6bcb127dd --- /dev/null +++ b/advancedcontentfilter/vendor/slim/slim/CHANGELOG.md @@ -0,0 +1,237 @@ +# Changelog + +# 4.11.0 - 2022-11-06 +- [3180: Declare types](https://github.com/slimphp/Slim/pull/3180) thanks to @nbayramberdiyev +- [3181: Update laminas/laminas-diactoros requirement from ^2.8 to ^2.9](https://github.com/slimphp/Slim/pull/3181) thanks to @dependabot[bot] +- [3182: Update guzzlehttp/psr7 requirement from ^2.1 to ^2.2](https://github.com/slimphp/Slim/pull/3182) thanks to @dependabot[bot] +- [3183: Update phpstan/phpstan requirement from ^1.4 to ^1.5](https://github.com/slimphp/Slim/pull/3183) thanks to @dependabot[bot] +- [3184: Update adriansuter/php-autoload-override requirement from ^1.2 to ^1.3](https://github.com/slimphp/Slim/pull/3184) thanks to @dependabot[bot] +- [3189: Update phpstan/phpstan requirement from ^1.5 to ^1.6](https://github.com/slimphp/Slim/pull/3189) thanks to @dependabot[bot] +- [3191: Adding property types to Middleware classes](https://github.com/slimphp/Slim/pull/3191) thanks to @ashleycoles +- [3193: Handlers types](https://github.com/slimphp/Slim/pull/3193) thanks to @ashleycoles +- [3194: Adding types to AbstractErrorRenderer](https://github.com/slimphp/Slim/pull/3194) thanks to @ashleycoles +- [3195: Adding prop types for Exception classes](https://github.com/slimphp/Slim/pull/3195) thanks to @ashleycoles +- [3196: Adding property type declarations for Factory classes](https://github.com/slimphp/Slim/pull/3196) thanks to @ashleycoles +- [3197: Remove redundant docblock types](https://github.com/slimphp/Slim/pull/3197) thanks to @theodorejb +- [3199: Update laminas/laminas-diactoros requirement from ^2.9 to ^2.11](https://github.com/slimphp/Slim/pull/3199) thanks to @dependabot[bot] +- [3200: Update phpstan/phpstan requirement from ^1.6 to ^1.7](https://github.com/slimphp/Slim/pull/3200) thanks to @dependabot[bot] +- [3205: Update guzzlehttp/psr7 requirement from ^2.2 to ^2.4](https://github.com/slimphp/Slim/pull/3205) thanks to @dependabot[bot] +- [3206: Update squizlabs/php_codesniffer requirement from ^3.6 to ^3.7](https://github.com/slimphp/Slim/pull/3206) thanks to @dependabot[bot] +- [3207: Update phpstan/phpstan requirement from ^1.7 to ^1.8](https://github.com/slimphp/Slim/pull/3207) thanks to @dependabot[bot] +- [3211: Assign null coalescing to coalesce equal](https://github.com/slimphp/Slim/pull/3211) thanks to @MathiasReker +- [3213: Void return](https://github.com/slimphp/Slim/pull/3213) thanks to @MathiasReker +- [3214: Is null](https://github.com/slimphp/Slim/pull/3214) thanks to @MathiasReker +- [3216: Refactor](https://github.com/slimphp/Slim/pull/3216) thanks to @mehdihasanpour +- [3218: Refactor some code](https://github.com/slimphp/Slim/pull/3218) thanks to @mehdihasanpour +- [3221: Cleanup](https://github.com/slimphp/Slim/pull/3221) thanks to @mehdihasanpour +- [3225: Update laminas/laminas-diactoros requirement from ^2.11 to ^2.14](https://github.com/slimphp/Slim/pull/3225) thanks to @dependabot[bot] +- [3228: Using assertSame to let assert equal be restricted](https://github.com/slimphp/Slim/pull/3228) thanks to @peter279k +- [3229: Update laminas/laminas-diactoros requirement from ^2.14 to ^2.17](https://github.com/slimphp/Slim/pull/3229) thanks to @dependabot[bot] +- [3235: Persist routes indexed by name in RouteCollector for improved performance.](https://github.com/slimphp/Slim/pull/3235) thanks to @BusterNeece + +# 4.10.0 - 2022-03-14 +- [3120: Add a new PSR-17 factory to Psr17FactoryProvider](https://github.com/slimphp/Slim/pull/3120) thanks to @solventt +- [3123: Replace deprecated setMethods() in tests](https://github.com/slimphp/Slim/pull/3123) thanks to @solventt +- [3126: Update guzzlehttp/psr7 requirement from ^2.0 to ^2.1](https://github.com/slimphp/Slim/pull/3126) thanks to @dependabot[bot] +- [3127: PHPStan v1.0](https://github.com/slimphp/Slim/pull/3127) thanks to @t0mmy742 +- [3128: Update phpstan/phpstan requirement from ^1.0 to ^1.2](https://github.com/slimphp/Slim/pull/3128) thanks to @dependabot[bot] +- [3129: Deprecate PHP 7.3](https://github.com/slimphp/Slim/pull/3129) thanks to @l0gicgate +- [3130: Removed double defined PHP 7.4](https://github.com/slimphp/Slim/pull/3130) thanks to @flangofas +- [3132: Add new `RequestResponseNamedArgs` route strategy](https://github.com/slimphp/Slim/pull/3132) thanks to @adoy +- [3133: Improve typehinting for `RouteParserInterface`](https://github.com/slimphp/Slim/pull/3133) thanks to @jerowork +- [3135: Update phpstan/phpstan requirement from ^1.2 to ^1.3](https://github.com/slimphp/Slim/pull/3135) thanks to @dependabot[bot] +- [3137: Update phpspec/prophecy requirement from ^1.14 to ^1.15](https://github.com/slimphp/Slim/pull/3137) thanks to @dependabot[bot] +- [3138: Update license year](https://github.com/slimphp/Slim/pull/3138) thanks to @Awilum +- [3139: Fixed #1730 (reintroduced in 4.x)](https://github.com/slimphp/Slim/pull/3139) thanks to @adoy +- [3145: Update phpstan/phpstan requirement from ^1.3 to ^1.4](https://github.com/slimphp/Slim/pull/3145) thanks to @dependabot[bot] +- [3146: Inherit HttpException from RuntimeException](https://github.com/slimphp/Slim/pull/3146) thanks to @nbayramberdiyev +- [3148: Upgrade to HTML5](https://github.com/slimphp/Slim/pull/3148) thanks to @nbayramberdiyev +- [3172: Update nyholm/psr7 requirement from ^1.4 to ^1.5](https://github.com/slimphp/Slim/pull/3172) thanks to @dependabot[bot] + +# 4.9.0 - 2021-10-05 +- [3058: Implement exception class for Gone Http error](https://github.com/slimphp/Slim/pull/3058) thanks to @TheKernelPanic +- [3086: Update slim/psr7 requirement from ^1.3 to ^1.4](https://github.com/slimphp/Slim/pull/3086) thanks to @dependabot[bot] +- [3087: Update nyholm/psr7-server requirement from ^1.0.1 to ^1.0.2](https://github.com/slimphp/Slim/pull/3087) thanks to @dependabot[bot] +- [3093: Update phpstan/phpstan requirement from ^0.12.85 to ^0.12.90](https://github.com/slimphp/Slim/pull/3093) thanks to @dependabot[bot] +- [3099: Allow updated psr log](https://github.com/slimphp/Slim/pull/3099) thanks to @t0mmy742 +- [3104: Drop php7.2](https://github.com/slimphp/Slim/pull/3104) thanks to @t0mmy742 +- [3106: Use PSR-17 factory from Guzzle/psr7 2.0](https://github.com/slimphp/Slim/pull/3106) thanks to @t0mmy742 +- [3108: Update README file](https://github.com/slimphp/Slim/pull/3108) thanks to @t0mmy742 +- [3112: Update laminas/laminas-diactoros requirement from ^2.6 to ^2.8](https://github.com/slimphp/Slim/pull/3112) thanks to @dependabot[bot] +- [3114: Update slim/psr7 requirement from ^1.4 to ^1.5](https://github.com/slimphp/Slim/pull/3114) thanks to @dependabot[bot] +- [3115: Update phpstan/phpstan requirement from ^0.12.96 to ^0.12.99](https://github.com/slimphp/Slim/pull/3115) thanks to @dependabot[bot] +- [3116: Remove Zend Diactoros references](https://github.com/slimphp/Slim/pull/3116) thanks to @l0gicgate + +# 4.8.0 - 2021-05-19 +- [3034: Fix phpunit dependency version](https://github.com/slimphp/Slim/pull/3034) thanks to @l0gicgate +- [3037: Replace Travis by GitHub Actions](https://github.com/slimphp/Slim/pull/3037) thanks to @t0mmy742 +- [3043: Cover App creation from AppFactory with empty Container](https://github.com/slimphp/Slim/pull/3043) thanks to @t0mmy742 +- [3045: Update phpstan/phpstan requirement from ^0.12.58 to ^0.12.64](https://github.com/slimphp/Slim/pull/3045) thanks to @dependabot-preview[bot] +- [3047: documentation: min php 7.2 required](https://github.com/slimphp/Slim/pull/3047) thanks to @Rotzbua +- [3054: Update phpstan/phpstan requirement from ^0.12.64 to ^0.12.70](https://github.com/slimphp/Slim/pull/3054) thanks to @dependabot-preview[bot] +- [3056: Fix docblock in ErrorMiddleware](https://github.com/slimphp/Slim/pull/3056) thanks to @piotr-cz +- [3060: Update phpstan/phpstan requirement from ^0.12.70 to ^0.12.80](https://github.com/slimphp/Slim/pull/3060) thanks to @dependabot-preview[bot] +- [3061: Update nyholm/psr7 requirement from ^1.3 to ^1.4](https://github.com/slimphp/Slim/pull/3061) thanks to @dependabot-preview[bot] +- [3063: Allow ^1.0 || ^2.0 in psr/container](https://github.com/slimphp/Slim/pull/3063) thanks to @Ayesh +- [3069: Classname/Method Callable Arrays](https://github.com/slimphp/Slim/pull/3069) thanks to @ddrv +- [3078: Update squizlabs/php_codesniffer requirement from ^3.5 to ^3.6](https://github.com/slimphp/Slim/pull/3078) thanks to @dependabot[bot] +- [3079: Update phpspec/prophecy requirement from ^1.12 to ^1.13](https://github.com/slimphp/Slim/pull/3079) thanks to @dependabot[bot] +- [3080: Update guzzlehttp/psr7 requirement from ^1.7 to ^1.8](https://github.com/slimphp/Slim/pull/3080) thanks to @dependabot[bot] +- [3082: Update phpstan/phpstan requirement from ^0.12.80 to ^0.12.85](https://github.com/slimphp/Slim/pull/3082) thanks to @dependabot[bot] + +# 4.7.0 - 2020-11-30 + +### Fixed +- [3027: Fix: FastRoute dispatcher and data generator should match](https://github.com/slimphp/Slim/pull/3027) thanks to @edudobay + +### Added +- [3015: PHP 8 support](https://github.com/slimphp/Slim/pull/3015) thanks to @edudobay + +### Optimizations +- [3024: Randomize tests](https://github.com/slimphp/Slim/pull/3024) thanks to @pawel-slowik + +## 4.6.0 - 2020-11-15 + +### Fixed +- [2942: Fix PHPdoc for error handlers in ErrorMiddleware ](https://github.com/slimphp/Slim/pull/2942) thanks to @TiMESPLiNTER +- [2944: Remove unused function in ErrorHandler](https://github.com/slimphp/Slim/pull/2944) thanks to @l0gicgate +- [2960: Fix phpstan 0.12 errors](https://github.com/slimphp/Slim/pull/2960) thanks to @adriansuter +- [2982: Removing cloning statements in tests](https://github.com/slimphp/Slim/pull/2982) thanks to @l0gicgate +- [3017: Fix request creator factory test](https://github.com/slimphp/Slim/pull/3017) thanks to @pawel-slowik +- [3022: Ensure RouteParser Always Present After Routing](https://github.com/slimphp/Slim/pull/3022) thanks to @l0gicgate + +### Added +- [2949: Add the support in composer.json](https://github.com/slimphp/Slim/pull/2949) thanks to @ddrv +- [2958: Strict empty string content type checking in BodyParsingMiddleware::getMediaType](https://github.com/slimphp/Slim/pull/2958) thanks to @Ayesh +- [2997: Add hints to methods](https://github.com/slimphp/Slim/pull/2997) thanks to @evgsavosin - [3000: Fix route controller test](https://github.com/slimphp/Slim/pull/3000) thanks to @pawel-slowik +- [3001: Add missing `$strategy` parameter in a Route test](https://github.com/slimphp/Slim/pull/3001) thanks to @pawel-slowik + +### Optimizations +- [2951: Minor optimizations in if() blocks](https://github.com/slimphp/Slim/pull/2951) thanks to @Ayesh +- [2959: Micro optimization: Declare closures in BodyParsingMiddleware as static](https://github.com/slimphp/Slim/pull/2959) thanks to @Ayesh +- [2978: Split the routing results to its own function.](https://github.com/slimphp/Slim/pull/2978) thanks to @dlundgren + +### Dependencies Updated +- [2953: Update nyholm/psr7-server requirement from ^0.4.1](https://github.com/slimphp/Slim/pull/2953) thanks to @dependabot-preview[bot] +- [2954: Update laminas/laminas-diactoros requirement from ^2.1 to ^2.3](https://github.com/slimphp/Slim/pull/2954) thanks to @dependabot-preview[bot] +- [2955: Update guzzlehttp/psr7 requirement from ^1.5 to ^1.6](https://github.com/slimphp/Slim/pull/2955) thanks to @dependabot-preview[bot] +- [2956: Update slim/psr7 requirement from ^1.0 to ^1.1](https://github.com/slimphp/Slim/pull/2956) thanks to @dependabot-preview[bot] +- [2957: Update nyholm/psr7 requirement from ^1.1 to ^1.2](https://github.com/slimphp/Slim/pull/2957) thanks to @dependabot-preview[bot] +- [2963: Update phpstan/phpstan requirement from ^0.12.23 to ^0.12.25](https://github.com/slimphp/Slim/pull/2963) thanks to @dependabot-preview[bot] +- [2965: Update adriansuter/php-autoload-override requirement from ^1.0 to ^1.1](https://github.com/slimphp/Slim/pull/2965) thanks to @dependabot-preview[bot] +- [2967: Update nyholm/psr7 requirement from ^1.2 to ^1.3](https://github.com/slimphp/Slim/pull/2967) thanks to @dependabot-preview[bot] +- [2969: Update nyholm/psr7-server requirement from ^0.4.1 to ^1.0.0](https://github.com/slimphp/Slim/pull/2969) thanks to @dependabot-preview[bot] +- [2970: Update phpstan/phpstan requirement from ^0.12.25 to ^0.12.26](https://github.com/slimphp/Slim/pull/2970) thanks to @dependabot-preview[bot] +- [2971: Update phpstan/phpstan requirement from ^0.12.26 to ^0.12.27](https://github.com/slimphp/Slim/pull/2971) thanks to @dependabot-preview[bot] +- [2972: Update phpstan/phpstan requirement from ^0.12.27 to ^0.12.28](https://github.com/slimphp/Slim/pull/2972) thanks to @dependabot-preview[bot] +- [2973: Update phpstan/phpstan requirement from ^0.12.28 to ^0.12.29](https://github.com/slimphp/Slim/pull/2973) thanks to @dependabot-preview[bot] +- [2975: Update phpstan/phpstan requirement from ^0.12.29 to ^0.12.30](https://github.com/slimphp/Slim/pull/2975) thanks to @dependabot-preview[bot] +- [2976: Update phpstan/phpstan requirement from ^0.12.30 to ^0.12.31](https://github.com/slimphp/Slim/pull/2976) thanks to @dependabot-preview[bot] +- [2980: Update phpstan/phpstan requirement from ^0.12.31 to ^0.12.32](https://github.com/slimphp/Slim/pull/2980) thanks to @dependabot-preview[bot] +- [2981: Update phpspec/prophecy requirement from ^1.10 to ^1.11](https://github.com/slimphp/Slim/pull/2981) thanks to @dependabot-preview[bot] +- [2986: Update phpstan/phpstan requirement from ^0.12.32 to ^0.12.33](https://github.com/slimphp/Slim/pull/2986) thanks to @dependabot-preview[bot] +- [2990: Update phpstan/phpstan requirement from ^0.12.33 to ^0.12.34](https://github.com/slimphp/Slim/pull/2990) thanks to @dependabot-preview[bot] +- [2991: Update phpstan/phpstan requirement from ^0.12.34 to ^0.12.35](https://github.com/slimphp/Slim/pull/2991) thanks to @dependabot-preview[bot] +- [2993: Update phpstan/phpstan requirement from ^0.12.35 to ^0.12.36](https://github.com/slimphp/Slim/pull/2993) thanks to @dependabot-preview[bot] +- [2995: Update phpstan/phpstan requirement from ^0.12.36 to ^0.12.37](https://github.com/slimphp/Slim/pull/2995) thanks to @dependabot-preview[bot] +- [3010: Update guzzlehttp/psr7 requirement from ^1.6 to ^1.7](https://github.com/slimphp/Slim/pull/3010) thanks to @dependabot-preview[bot] +- [3011: Update phpspec/prophecy requirement from ^1.11 to ^1.12](https://github.com/slimphp/Slim/pull/3011) thanks to @dependabot-preview[bot] +- [3012: Update slim/http requirement from ^1.0 to ^1.1](https://github.com/slimphp/Slim/pull/3012) thanks to @dependabot-preview[bot] +- [3013: Update slim/psr7 requirement from ^1.1 to ^1.2](https://github.com/slimphp/Slim/pull/3013) thanks to @dependabot-preview[bot] +- [3014: Update laminas/laminas-diactoros requirement from ^2.3 to ^2.4](https://github.com/slimphp/Slim/pull/3014) thanks to @dependabot-preview[bot] +- [3018: Update phpstan/phpstan requirement from ^0.12.37 to ^0.12.54](https://github.com/slimphp/Slim/pull/3018) thanks to @dependabot-preview[bot] + +## 4.5.0 - 2020-04-14 + +### Added +- [2928](https://github.com/slimphp/Slim/pull/2928) Test against PHP 7.4 +- [2937](https://github.com/slimphp/Slim/pull/2937) Add support for PSR-3 + +### Fixed +- [2916](https://github.com/slimphp/Slim/pull/2916) Rename phpcs.xml to phpcs.xml.dist +- [2917](https://github.com/slimphp/Slim/pull/2917) Update .editorconfig +- [2925](https://github.com/slimphp/Slim/pull/2925) ResponseEmitter: Don't remove Content-Type and Content-Length when body is empt +- [2932](https://github.com/slimphp/Slim/pull/2932) Update the Tidelift enterprise language +- [2938](https://github.com/slimphp/Slim/pull/2938) Modify usage of deprecated expectExceptionMessageRegExp() method + +## 4.4.0 - 2020-01-04 + +### Added +- [2862](https://github.com/slimphp/Slim/pull/2862) Optionally handle subclasses of exceptions in custom error handler +- [2869](https://github.com/slimphp/Slim/pull/2869) php-di/php-di added in composer suggestion +- [2874](https://github.com/slimphp/Slim/pull/2874) Add `null` to param type-hints +- [2889](https://github.com/slimphp/Slim/pull/2889) Make `RouteContext` attributes customizable and change default to use private names +- [2907](https://github.com/slimphp/Slim/pull/2907) Migrate to PSR-12 convention +- [2910](https://github.com/slimphp/Slim/pull/2910) Migrate Zend to Laminas +- [2912](https://github.com/slimphp/Slim/pull/2912) Add Laminas PSR17 Factory +- [2913](https://github.com/slimphp/Slim/pull/2913) Update php-autoload-override version +- [2914](https://github.com/slimphp/Slim/pull/2914) Added ability to add handled exceptions as an array + +### Fixed +- [2864](https://github.com/slimphp/Slim/pull/2864) Optimize error message in error handling if displayErrorDetails was not set +- [2876](https://github.com/slimphp/Slim/pull/2876) Update links from http to https +- [2877](https://github.com/slimphp/Slim/pull/2877) Fix docblock for `Slim\Routing\RouteCollector::cacheFile` +- [2878](https://github.com/slimphp/Slim/pull/2878) check body is writable only on ouput buffering append +- [2896](https://github.com/slimphp/Slim/pull/2896) Render errors uniformly +- [2902](https://github.com/slimphp/Slim/pull/2902) Fix prophecies +- [2908](https://github.com/slimphp/Slim/pull/2908) Use autoload-dev for `Slim\Tests` namespace + +### Removed +- [2871](https://github.com/slimphp/Slim/pull/2871) Remove explicit type-hint +- [2872](https://github.com/slimphp/Slim/pull/2872) Remove type-hint + +## 4.3.0 - 2019-10-05 + +### Added +- [2819](https://github.com/slimphp/Slim/pull/2819) Added description to addRoutingMiddleware() +- [2820](https://github.com/slimphp/Slim/pull/2820) Update link to homepage in composer.json +- [2828](https://github.com/slimphp/Slim/pull/2828) Allow URIs with leading multi-slashes +- [2832](https://github.com/slimphp/Slim/pull/2832) Refactor `FastRouteDispatcher` +- [2835](https://github.com/slimphp/Slim/pull/2835) Rename `pathFor` to `urlFor` in docblock +- [2846](https://github.com/slimphp/Slim/pull/2846) Correcting the branch name as per issue-2843 +- [2849](https://github.com/slimphp/Slim/pull/2849) Create class alias for FastRoute\RouteCollector +- [2855](https://github.com/slimphp/Slim/pull/2855) Add list of allowed methods to HttpMethodNotAllowedException +- [2860](https://github.com/slimphp/Slim/pull/2860) Add base path to `$request` and use `RouteContext` to read + +### Fixed +- [2839](https://github.com/slimphp/Slim/pull/2839) Fix description for handler signature in phpdocs +- [2844](https://github.com/slimphp/Slim/pull/2844) Handle base path by routeCollector instead of RouteCollectorProxy +- [2845](https://github.com/slimphp/Slim/pull/2845) Fix composer scripts +- [2851](https://github.com/slimphp/Slim/pull/2851) Fix example of 'Hello World' app +- [2854](https://github.com/slimphp/Slim/pull/2854) Fix undefined property in tests + +### Removed +- [2853](https://github.com/slimphp/Slim/pull/2853) Remove unused classes + +## 4.2.0 - 2019-08-20 + +### Added +- [2787](https://github.com/slimphp/Slim/pull/2787) Add an advanced callable resolver +- [2791](https://github.com/slimphp/Slim/pull/2791) Add `inferPrivatePropertyTypeFromConstructor` to phpstan +- [2793](https://github.com/slimphp/Slim/pull/2793) Add ability to configure application via a container in `AppFactory` +- [2798](https://github.com/slimphp/Slim/pull/2798) Add PSR-7 Agnostic Body Parsing Middleware +- [2801](https://github.com/slimphp/Slim/pull/2801) Add `setLogErrorRenderer()` method to `ErrorHandler` +- [2807](https://github.com/slimphp/Slim/pull/2807) Add check for Slim callable notation if no resolver given +- [2803](https://github.com/slimphp/Slim/pull/2803) Add ability to emit non seekable streams in `ResponseEmitter` +- [2817](https://github.com/slimphp/Slim/pull/2817) Add the ability to pass in a custom `MiddlewareDispatcherInterface` to the `App` + +### Fixed +- [2789](https://github.com/slimphp/Slim/pull/2789) Fix Cookie header detection in `ResponseEmitter` +- [2796](https://github.com/slimphp/Slim/pull/2796) Fix http message format +- [2800](https://github.com/slimphp/Slim/pull/2800) Fix null comparisons more clear in `ErrorHandler` +- [2802](https://github.com/slimphp/Slim/pull/2802) Fix incorrect search of a header in stack +- [2806](https://github.com/slimphp/Slim/pull/2806) Simplify `Route::prepare()` method argument preparation +- [2809](https://github.com/slimphp/Slim/pull/2809) Eliminate a duplicate code via HOF in `MiddlewareDispatcher` +- [2816](https://github.com/slimphp/Slim/pull/2816) Fix RouteCollectorProxy::redirect() bug + +### Removed +- [2811](https://github.com/slimphp/Slim/pull/2811) Remove `DeferredCallable` + +## 4.1.0 - 2019-08-06 + +### Added +- [#2779](https://github.com/slimphp/Slim/pull/2774) Add support for Slim callables `Class:method` resolution & Container Closure auto-binding in `MiddlewareDispatcher` +- [#2774](https://github.com/slimphp/Slim/pull/2774) Add possibility for custom `RequestHandler` invocation strategies + +### Fixed +- [#2776](https://github.com/slimphp/Slim/pull/2774) Fix group middleware on multiple nested groups diff --git a/advancedcontentfilter/vendor/slim/slim/LICENSE.md b/advancedcontentfilter/vendor/slim/slim/LICENSE.md index 682c21dc7..d6fd559c7 100644 --- a/advancedcontentfilter/vendor/slim/slim/LICENSE.md +++ b/advancedcontentfilter/vendor/slim/slim/LICENSE.md @@ -1,4 +1,4 @@ -Copyright (c) 2011-2017 Josh Lockhart +Copyright (c) 2011-2022 Josh Lockhart Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/advancedcontentfilter/vendor/slim/slim/MAINTAINERS.md b/advancedcontentfilter/vendor/slim/slim/MAINTAINERS.md new file mode 100644 index 000000000..2b8ad0496 --- /dev/null +++ b/advancedcontentfilter/vendor/slim/slim/MAINTAINERS.md @@ -0,0 +1,17 @@ +# Maintainers + +There aren't many rules for maintainers of Slim to remember; what we have is listed here. + +## We don't merge our own PRs + +Our code is better if more than one set of eyes looks at it. Therefore we do not merge our own pull requests unless there is an exceptional circumstance. This helps to spot errors in the patch and also enables us to share information about the project around the maintainer team. + +## PRs tagged `WIP` are not ready to be merged + +Sometimes it's helpful to collaborate on a patch before it's ready to be merged. We use the text `WIP` (for _Work in Progress_) in the title to mark these PRs. + +If a PR has `WIP` in its title, then it is not to be merged. The person who raised the PR will remove the `WIP` text when they are ready for a full review and merge. + +## Assign a merged PR to a milestone + +By ensuring that all merged PRs are assigned to a milestone, we can easily find which PRs were in which release. diff --git a/advancedcontentfilter/vendor/slim/slim/SECURITY.md b/advancedcontentfilter/vendor/slim/slim/SECURITY.md new file mode 100644 index 000000000..a5b6df0b4 --- /dev/null +++ b/advancedcontentfilter/vendor/slim/slim/SECURITY.md @@ -0,0 +1,14 @@ +# Security Policy + +### Supported Versions + + +| Version | Supported | +| ------- | ------------------ | +| 3.x.x | :white_check_mark: | +| 4.x.x | :white_check_mark: | + + +### Reporting a Vulnerability + +To report a vulnerability please send an email to security@slimframework.com diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/App.php b/advancedcontentfilter/vendor/slim/slim/Slim/App.php index c5a0f2d3a..ebcc751f6 100644 --- a/advancedcontentfilter/vendor/slim/slim/Slim/App.php +++ b/advancedcontentfilter/vendor/slim/slim/Slim/App.php @@ -1,696 +1,216 @@ container = $container; - } + public function __construct( + ResponseFactoryInterface $responseFactory, + ?ContainerInterface $container = null, + ?CallableResolverInterface $callableResolver = null, + ?RouteCollectorInterface $routeCollector = null, + ?RouteResolverInterface $routeResolver = null, + ?MiddlewareDispatcherInterface $middlewareDispatcher = null + ) { + parent::__construct( + $responseFactory, + $callableResolver ?? new CallableResolver($container), + $container, + $routeCollector + ); - /** - * Enable access to the DI container by consumers of $app - * - * @return ContainerInterface - */ - public function getContainer() - { - return $this->container; - } + $this->routeResolver = $routeResolver ?? new RouteResolver($this->routeCollector); + $routeRunner = new RouteRunner($this->routeResolver, $this->routeCollector->getRouteParser(), $this); - /** - * Add middleware - * - * This method prepends new middleware to the app's middleware stack. - * - * @param callable|string $callable The callback routine - * - * @return static - */ - public function add($callable) - { - return $this->addMiddleware(new DeferredCallable($callable, $this->container)); - } - - /** - * Calling a non-existant method on App checks to see if there's an item - * in the container that is callable and if so, calls it. - * - * @param string $method - * @param array $args - * @return mixed - */ - public function __call($method, $args) - { - if ($this->container->has($method)) { - $obj = $this->container->get($method); - if (is_callable($obj)) { - return call_user_func_array($obj, $args); - } + if (!$middlewareDispatcher) { + $middlewareDispatcher = new MiddlewareDispatcher($routeRunner, $this->callableResolver, $container); + } else { + $middlewareDispatcher->seedMiddlewareStack($routeRunner); } - throw new \BadMethodCallException("Method $method is not a valid method"); - } - - /******************************************************************************** - * Router proxy methods - *******************************************************************************/ - - /** - * Add GET route - * - * @param string $pattern The route URI pattern - * @param callable|string $callable The route callback routine - * - * @return \Slim\Interfaces\RouteInterface - */ - public function get($pattern, $callable) - { - return $this->map(['GET'], $pattern, $callable); + $this->middlewareDispatcher = $middlewareDispatcher; } /** - * Add POST route - * - * @param string $pattern The route URI pattern - * @param callable|string $callable The route callback routine - * - * @return \Slim\Interfaces\RouteInterface + * @return RouteResolverInterface */ - public function post($pattern, $callable) + public function getRouteResolver(): RouteResolverInterface { - return $this->map(['POST'], $pattern, $callable); + return $this->routeResolver; } /** - * Add PUT route - * - * @param string $pattern The route URI pattern - * @param callable|string $callable The route callback routine - * - * @return \Slim\Interfaces\RouteInterface + * @return MiddlewareDispatcherInterface */ - public function put($pattern, $callable) + public function getMiddlewareDispatcher(): MiddlewareDispatcherInterface { - return $this->map(['PUT'], $pattern, $callable); + return $this->middlewareDispatcher; } /** - * Add PATCH route - * - * @param string $pattern The route URI pattern - * @param callable|string $callable The route callback routine - * - * @return \Slim\Interfaces\RouteInterface + * @param MiddlewareInterface|string|callable $middleware */ - public function patch($pattern, $callable) + public function add($middleware): self { - return $this->map(['PATCH'], $pattern, $callable); + $this->middlewareDispatcher->add($middleware); + return $this; } /** - * Add DELETE route - * - * @param string $pattern The route URI pattern - * @param callable|string $callable The route callback routine - * - * @return \Slim\Interfaces\RouteInterface + * @param MiddlewareInterface $middleware */ - public function delete($pattern, $callable) + public function addMiddleware(MiddlewareInterface $middleware): self { - return $this->map(['DELETE'], $pattern, $callable); + $this->middlewareDispatcher->addMiddleware($middleware); + return $this; } /** - * Add OPTIONS route + * Add the Slim built-in routing middleware to the app middleware stack * - * @param string $pattern The route URI pattern - * @param callable|string $callable The route callback routine + * This method can be used to control middleware order and is not required for default routing operation. * - * @return \Slim\Interfaces\RouteInterface + * @return RoutingMiddleware */ - public function options($pattern, $callable) + public function addRoutingMiddleware(): RoutingMiddleware { - return $this->map(['OPTIONS'], $pattern, $callable); + $routingMiddleware = new RoutingMiddleware( + $this->getRouteResolver(), + $this->getRouteCollector()->getRouteParser() + ); + $this->add($routingMiddleware); + return $routingMiddleware; } /** - * Add route for any HTTP method + * Add the Slim built-in error middleware to the app middleware stack * - * @param string $pattern The route URI pattern - * @param callable|string $callable The route callback routine + * @param bool $displayErrorDetails + * @param bool $logErrors + * @param bool $logErrorDetails + * @param LoggerInterface|null $logger * - * @return \Slim\Interfaces\RouteInterface + * @return ErrorMiddleware */ - public function any($pattern, $callable) - { - return $this->map(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'], $pattern, $callable); + public function addErrorMiddleware( + bool $displayErrorDetails, + bool $logErrors, + bool $logErrorDetails, + ?LoggerInterface $logger = null + ): ErrorMiddleware { + $errorMiddleware = new ErrorMiddleware( + $this->getCallableResolver(), + $this->getResponseFactory(), + $displayErrorDetails, + $logErrors, + $logErrorDetails, + $logger + ); + $this->add($errorMiddleware); + return $errorMiddleware; } /** - * Add route with multiple methods + * Add the Slim body parsing middleware to the app middleware stack * - * @param string[] $methods Numeric array of HTTP method names - * @param string $pattern The route URI pattern - * @param callable|string $callable The route callback routine + * @param callable[] $bodyParsers * - * @return RouteInterface + * @return BodyParsingMiddleware */ - public function map(array $methods, $pattern, $callable) + public function addBodyParsingMiddleware(array $bodyParsers = []): BodyParsingMiddleware { - if ($callable instanceof Closure) { - $callable = $callable->bindTo($this->container); - } - - $route = $this->container->get('router')->map($methods, $pattern, $callable); - if (is_callable([$route, 'setContainer'])) { - $route->setContainer($this->container); - } - - if (is_callable([$route, 'setOutputBuffering'])) { - $route->setOutputBuffering($this->container->get('settings')['outputBuffering']); - } - - return $route; + $bodyParsingMiddleware = new BodyParsingMiddleware($bodyParsers); + $this->add($bodyParsingMiddleware); + return $bodyParsingMiddleware; } - /** - * Route Groups - * - * This method accepts a route pattern and a callback. All route - * declarations in the callback will be prepended by the group(s) - * that it is in. - * - * @param string $pattern - * @param callable $callable - * - * @return RouteGroupInterface - */ - public function group($pattern, $callable) - { - /** @var RouteGroup $group */ - $group = $this->container->get('router')->pushGroup($pattern, $callable); - $group->setContainer($this->container); - $group($this); - $this->container->get('router')->popGroup(); - return $group; - } - - /******************************************************************************** - * Runner - *******************************************************************************/ - /** * Run application * * This method traverses the application middleware stack and then sends the * resultant Response object to the HTTP client. * - * @param bool|false $silent - * @return ResponseInterface - * - * @throws Exception - * @throws MethodNotAllowedException - * @throws NotFoundException + * @param ServerRequestInterface|null $request + * @return void */ - public function run($silent = false) + public function run(?ServerRequestInterface $request = null): void { - $response = $this->container->get('response'); - - try { - ob_start(); - $response = $this->process($this->container->get('request'), $response); - } catch (InvalidMethodException $e) { - $response = $this->processInvalidMethod($e->getRequest(), $response); - } finally { - $output = ob_get_clean(); + if (!$request) { + $serverRequestCreator = ServerRequestCreatorFactory::create(); + $request = $serverRequestCreator->createServerRequestFromGlobals(); } - if (!empty($output) && $response->getBody()->isWritable()) { - $outputBuffering = $this->container->get('settings')['outputBuffering']; - if ($outputBuffering === 'prepend') { - // prepend output buffer content - $body = new Http\Body(fopen('php://temp', 'r+')); - $body->write($output . $response->getBody()); - $response = $response->withBody($body); - } elseif ($outputBuffering === 'append') { - // append output buffer content - $response->getBody()->write($output); - } - } - - $response = $this->finalize($response); - - if (!$silent) { - $this->respond($response); - } - - return $response; + $response = $this->handle($request); + $responseEmitter = new ResponseEmitter(); + $responseEmitter->emit($response); } /** - * Pull route info for a request with a bad method to decide whether to - * return a not-found error (default) or a bad-method error, then run - * the handler for that error, returning the resulting response. - * - * Used for cases where an incoming request has an unrecognized method, - * rather than throwing an exception and not catching it all the way up. - * - * @param ServerRequestInterface $request - * @param ResponseInterface $response - * @return ResponseInterface - */ - protected function processInvalidMethod(ServerRequestInterface $request, ResponseInterface $response) - { - $router = $this->container->get('router'); - if (is_callable([$request->getUri(), 'getBasePath']) && is_callable([$router, 'setBasePath'])) { - $router->setBasePath($request->getUri()->getBasePath()); - } - - $request = $this->dispatchRouterAndPrepareRoute($request, $router); - $routeInfo = $request->getAttribute('routeInfo', [RouterInterface::DISPATCH_STATUS => Dispatcher::NOT_FOUND]); - - if ($routeInfo[RouterInterface::DISPATCH_STATUS] === Dispatcher::METHOD_NOT_ALLOWED) { - return $this->handleException( - new MethodNotAllowedException($request, $response, $routeInfo[RouterInterface::ALLOWED_METHODS]), - $request, - $response - ); - } - - return $this->handleException(new NotFoundException($request, $response), $request, $response); - } - - /** - * Process a request + * Handle a request * * This method traverses the application middleware stack and then returns the * resultant Response object. * * @param ServerRequestInterface $request - * @param ResponseInterface $response * @return ResponseInterface - * - * @throws Exception - * @throws MethodNotAllowedException - * @throws NotFoundException */ - public function process(ServerRequestInterface $request, ResponseInterface $response) + public function handle(ServerRequestInterface $request): ResponseInterface { - // Ensure basePath is set - $router = $this->container->get('router'); - if (is_callable([$request->getUri(), 'getBasePath']) && is_callable([$router, 'setBasePath'])) { - $router->setBasePath($request->getUri()->getBasePath()); - } + $response = $this->middlewareDispatcher->handle($request); - // Dispatch the Router first if the setting for this is on - if ($this->container->get('settings')['determineRouteBeforeAppMiddleware'] === true) { - // Dispatch router (note: you won't be able to alter routes after this) - $request = $this->dispatchRouterAndPrepareRoute($request, $router); - } - - // Traverse middleware stack - try { - $response = $this->callMiddlewareStack($request, $response); - } catch (Exception $e) { - $response = $this->handleException($e, $request, $response); - } catch (Throwable $e) { - $response = $this->handlePhpError($e, $request, $response); + /** + * This is to be in compliance with RFC 2616, Section 9. + * If the incoming request method is HEAD, we need to ensure that the response body + * is empty as the request may fall back on a GET route handler due to FastRoute's + * routing logic which could potentially append content to the response body + * https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.4 + */ + $method = strtoupper($request->getMethod()); + if ($method === 'HEAD') { + $emptyBody = $this->responseFactory->createResponse()->getBody(); + return $response->withBody($emptyBody); } return $response; } - - /** - * Send the response to the client - * - * @param ResponseInterface $response - */ - public function respond(ResponseInterface $response) - { - // Send response - if (!headers_sent()) { - // Headers - foreach ($response->getHeaders() as $name => $values) { - foreach ($values as $value) { - header(sprintf('%s: %s', $name, $value), false); - } - } - - // Set the status _after_ the headers, because of PHP's "helpful" behavior with location headers. - // See https://github.com/slimphp/Slim/issues/1730 - - // Status - header(sprintf( - 'HTTP/%s %s %s', - $response->getProtocolVersion(), - $response->getStatusCode(), - $response->getReasonPhrase() - )); - } - - // Body - if (!$this->isEmptyResponse($response)) { - $body = $response->getBody(); - if ($body->isSeekable()) { - $body->rewind(); - } - $settings = $this->container->get('settings'); - $chunkSize = $settings['responseChunkSize']; - - $contentLength = $response->getHeaderLine('Content-Length'); - if (!$contentLength) { - $contentLength = $body->getSize(); - } - - - if (isset($contentLength)) { - $amountToRead = $contentLength; - while ($amountToRead > 0 && !$body->eof()) { - $data = $body->read(min($chunkSize, $amountToRead)); - echo $data; - - $amountToRead -= strlen($data); - - if (connection_status() != CONNECTION_NORMAL) { - break; - } - } - } else { - while (!$body->eof()) { - echo $body->read($chunkSize); - if (connection_status() != CONNECTION_NORMAL) { - break; - } - } - } - } - } - - /** - * Invoke application - * - * This method implements the middleware interface. It receives - * Request and Response objects, and it returns a Response object - * after compiling the routes registered in the Router and dispatching - * the Request object to the appropriate Route callback routine. - * - * @param ServerRequestInterface $request The most recent Request object - * @param ResponseInterface $response The most recent Response object - * - * @return ResponseInterface - * @throws MethodNotAllowedException - * @throws NotFoundException - */ - public function __invoke(ServerRequestInterface $request, ResponseInterface $response) - { - // Get the route info - $routeInfo = $request->getAttribute('routeInfo'); - - /** @var \Slim\Interfaces\RouterInterface $router */ - $router = $this->container->get('router'); - - // If router hasn't been dispatched or the URI changed then dispatch - if (null === $routeInfo || ($routeInfo['request'] !== [$request->getMethod(), (string) $request->getUri()])) { - $request = $this->dispatchRouterAndPrepareRoute($request, $router); - $routeInfo = $request->getAttribute('routeInfo'); - } - - if ($routeInfo[0] === Dispatcher::FOUND) { - $route = $router->lookupRoute($routeInfo[1]); - return $route->run($request, $response); - } elseif ($routeInfo[0] === Dispatcher::METHOD_NOT_ALLOWED) { - if (!$this->container->has('notAllowedHandler')) { - throw new MethodNotAllowedException($request, $response, $routeInfo[1]); - } - /** @var callable $notAllowedHandler */ - $notAllowedHandler = $this->container->get('notAllowedHandler'); - return $notAllowedHandler($request, $response, $routeInfo[1]); - } - - if (!$this->container->has('notFoundHandler')) { - throw new NotFoundException($request, $response); - } - /** @var callable $notFoundHandler */ - $notFoundHandler = $this->container->get('notFoundHandler'); - return $notFoundHandler($request, $response); - } - - /** - * Perform a sub-request from within an application route - * - * This method allows you to prepare and initiate a sub-request, run within - * the context of the current request. This WILL NOT issue a remote HTTP - * request. Instead, it will route the provided URL, method, headers, - * cookies, body, and server variables against the set of registered - * application routes. The result response object is returned. - * - * @param string $method The request method (e.g., GET, POST, PUT, etc.) - * @param string $path The request URI path - * @param string $query The request URI query string - * @param array $headers The request headers (key-value array) - * @param array $cookies The request cookies (key-value array) - * @param string $bodyContent The request body - * @param ResponseInterface $response The response object (optional) - * @return ResponseInterface - */ - public function subRequest( - $method, - $path, - $query = '', - array $headers = [], - array $cookies = [], - $bodyContent = '', - ResponseInterface $response = null - ) { - $env = $this->container->get('environment'); - $uri = Uri::createFromEnvironment($env)->withPath($path)->withQuery($query); - $headers = new Headers($headers); - $serverParams = $env->all(); - $body = new Body(fopen('php://temp', 'r+')); - $body->write($bodyContent); - $body->rewind(); - $request = new Request($method, $uri, $headers, $cookies, $serverParams, $body); - - if (!$response) { - $response = $this->container->get('response'); - } - - return $this($request, $response); - } - - /** - * Dispatch the router to find the route. Prepare the route for use. - * - * @param ServerRequestInterface $request - * @param RouterInterface $router - * @return ServerRequestInterface - */ - protected function dispatchRouterAndPrepareRoute(ServerRequestInterface $request, RouterInterface $router) - { - $routeInfo = $router->dispatch($request); - - if ($routeInfo[0] === Dispatcher::FOUND) { - $routeArguments = []; - foreach ($routeInfo[2] as $k => $v) { - $routeArguments[$k] = urldecode($v); - } - - $route = $router->lookupRoute($routeInfo[1]); - $route->prepare($request, $routeArguments); - - // add route to the request's attributes in case a middleware or handler needs access to the route - $request = $request->withAttribute('route', $route); - } - - $routeInfo['request'] = [$request->getMethod(), (string) $request->getUri()]; - - return $request->withAttribute('routeInfo', $routeInfo); - } - - /** - * Finalize response - * - * @param ResponseInterface $response - * @return ResponseInterface - */ - protected function finalize(ResponseInterface $response) - { - // stop PHP sending a Content-Type automatically - ini_set('default_mimetype', ''); - - if ($this->isEmptyResponse($response)) { - return $response->withoutHeader('Content-Type')->withoutHeader('Content-Length'); - } - - // Add Content-Length header if `addContentLengthHeader` setting is set - if (isset($this->container->get('settings')['addContentLengthHeader']) && - $this->container->get('settings')['addContentLengthHeader'] == true) { - if (ob_get_length() > 0) { - throw new \RuntimeException("Unexpected data in output buffer. " . - "Maybe you have characters before an opening getBody()->getSize(); - if ($size !== null && !$response->hasHeader('Content-Length')) { - $response = $response->withHeader('Content-Length', (string) $size); - } - } - - return $response; - } - - /** - * Helper method, which returns true if the provided response must not output a body and false - * if the response could have a body. - * - * @see https://tools.ietf.org/html/rfc7231 - * - * @param ResponseInterface $response - * @return bool - */ - protected function isEmptyResponse(ResponseInterface $response) - { - if (method_exists($response, 'isEmpty')) { - return $response->isEmpty(); - } - - return in_array($response->getStatusCode(), [204, 205, 304]); - } - - /** - * Call relevant handler from the Container if needed. If it doesn't exist, - * then just re-throw. - * - * @param Exception $e - * @param ServerRequestInterface $request - * @param ResponseInterface $response - * - * @return ResponseInterface - * @throws Exception if a handler is needed and not found - */ - protected function handleException(Exception $e, ServerRequestInterface $request, ResponseInterface $response) - { - if ($e instanceof MethodNotAllowedException) { - $handler = 'notAllowedHandler'; - $params = [$e->getRequest(), $e->getResponse(), $e->getAllowedMethods()]; - } elseif ($e instanceof NotFoundException) { - $handler = 'notFoundHandler'; - $params = [$e->getRequest(), $e->getResponse(), $e]; - } elseif ($e instanceof SlimException) { - // This is a Stop exception and contains the response - return $e->getResponse(); - } else { - // Other exception, use $request and $response params - $handler = 'errorHandler'; - $params = [$request, $response, $e]; - } - - if ($this->container->has($handler)) { - $callable = $this->container->get($handler); - // Call the registered handler - return call_user_func_array($callable, $params); - } - - // No handlers found, so just throw the exception - throw $e; - } - - /** - * Call relevant handler from the Container if needed. If it doesn't exist, - * then just re-throw. - * - * @param Throwable $e - * @param ServerRequestInterface $request - * @param ResponseInterface $response - * @return ResponseInterface - * @throws Throwable - */ - protected function handlePhpError(Throwable $e, ServerRequestInterface $request, ResponseInterface $response) - { - $handler = 'phpErrorHandler'; - $params = [$request, $response, $e]; - - if ($this->container->has($handler)) { - $callable = $this->container->get($handler); - // Call the registered handler - return call_user_func_array($callable, $params); - } - - // No handlers found, so just throw the exception - throw $e; - } } diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/CallableResolver.php b/advancedcontentfilter/vendor/slim/slim/Slim/CallableResolver.php index 2211a3291..66f225de8 100644 --- a/advancedcontentfilter/vendor/slim/slim/Slim/CallableResolver.php +++ b/advancedcontentfilter/vendor/slim/slim/Slim/CallableResolver.php @@ -1,110 +1,193 @@ container = $container; } /** - * Resolve toResolve into a closure so that the router can dispatch. + * {@inheritdoc} + */ + public function resolve($toResolve): callable + { + $toResolve = $this->prepareToResolve($toResolve); + if (is_callable($toResolve)) { + return $this->bindToContainer($toResolve); + } + $resolved = $toResolve; + if (is_string($toResolve)) { + $resolved = $this->resolveSlimNotation($toResolve); + $resolved[1] ??= '__invoke'; + } + $callable = $this->assertCallable($resolved, $toResolve); + return $this->bindToContainer($callable); + } + + /** + * {@inheritdoc} + */ + public function resolveRoute($toResolve): callable + { + return $this->resolveByPredicate($toResolve, [$this, 'isRoute'], 'handle'); + } + + /** + * {@inheritdoc} + */ + public function resolveMiddleware($toResolve): callable + { + return $this->resolveByPredicate($toResolve, [$this, 'isMiddleware'], 'process'); + } + + /** + * @param string|callable $toResolve * - * If toResolve is of the format 'class:method', then try to extract 'class' - * from the container otherwise instantiate it and then dispatch 'method'. + * @throws RuntimeException + */ + private function resolveByPredicate($toResolve, callable $predicate, string $defaultMethod): callable + { + $toResolve = $this->prepareToResolve($toResolve); + if (is_callable($toResolve)) { + return $this->bindToContainer($toResolve); + } + $resolved = $toResolve; + if ($predicate($toResolve)) { + $resolved = [$toResolve, $defaultMethod]; + } + if (is_string($toResolve)) { + [$instance, $method] = $this->resolveSlimNotation($toResolve); + if ($method === null && $predicate($instance)) { + $method = $defaultMethod; + } + $resolved = [$instance, $method ?? '__invoke']; + } + $callable = $this->assertCallable($resolved, $toResolve); + return $this->bindToContainer($callable); + } + + /** + * @param mixed $toResolve + */ + private function isRoute($toResolve): bool + { + return $toResolve instanceof RequestHandlerInterface; + } + + /** + * @param mixed $toResolve + */ + private function isMiddleware($toResolve): bool + { + return $toResolve instanceof MiddlewareInterface; + } + + /** + * @throws RuntimeException * + * @return array{object, string|null} [Instance, Method Name] + */ + private function resolveSlimNotation(string $toResolve): array + { + preg_match(CallableResolver::$callablePattern, $toResolve, $matches); + [$class, $method] = $matches ? [$matches[1], $matches[2]] : [$toResolve, null]; + + /** @var string $class */ + /** @var string|null $method */ + if ($this->container && $this->container->has($class)) { + $instance = $this->container->get($class); + if (!is_object($instance)) { + throw new RuntimeException(sprintf('%s container entry is not an object', $class)); + } + } else { + if (!class_exists($class)) { + if ($method) { + $class .= '::' . $method . '()'; + } + throw new RuntimeException(sprintf('Callable %s does not exist', $class)); + } + $instance = new $class($this->container); + } + return [$instance, $method]; + } + + /** + * @param mixed $resolved * @param mixed $toResolve * - * @return callable - * - * @throws RuntimeException if the callable does not exist - * @throws RuntimeException if the callable is not resolvable + * @throws RuntimeException */ - public function resolve($toResolve) + private function assertCallable($resolved, $toResolve): callable { - if (is_callable($toResolve)) { - return $toResolve; + if (!is_callable($resolved)) { + if (is_callable($toResolve) || is_object($toResolve) || is_array($toResolve)) { + $formatedToResolve = ($toResolveJson = json_encode($toResolve)) !== false ? $toResolveJson : ''; + } else { + $formatedToResolve = is_string($toResolve) ? $toResolve : ''; + } + throw new RuntimeException(sprintf('%s is not resolvable', $formatedToResolve)); } - - if (!is_string($toResolve)) { - $this->assertCallable($toResolve); - } - - // check for slim callable as "class:method" - if (preg_match(self::CALLABLE_PATTERN, $toResolve, $matches)) { - $resolved = $this->resolveCallable($matches[1], $matches[2]); - $this->assertCallable($resolved); - - return $resolved; - } - - $resolved = $this->resolveCallable($toResolve); - $this->assertCallable($resolved); - return $resolved; } - /** - * Check if string is something in the DIC - * that's callable or is a class name which has an __invoke() method. - * - * @param string $class - * @param string $method - * @return callable - * - * @throws \RuntimeException if the callable does not exist - */ - protected function resolveCallable($class, $method = '__invoke') + private function bindToContainer(callable $callable): callable { - if ($this->container->has($class)) { - return [$this->container->get($class), $method]; + if (is_array($callable) && $callable[0] instanceof Closure) { + $callable = $callable[0]; } - - if (!class_exists($class)) { - throw new RuntimeException(sprintf('Callable %s does not exist', $class)); + if ($this->container && $callable instanceof Closure) { + /** @var Closure $callable */ + $callable = $callable->bindTo($this->container); } - - return [new $class($this->container), $method]; + return $callable; } /** - * @param Callable $callable - * - * @throws \RuntimeException if the callable is not resolvable + * @param string|callable $toResolve + * @return string|callable */ - protected function assertCallable($callable) + private function prepareToResolve($toResolve) { - if (!is_callable($callable)) { - throw new RuntimeException(sprintf( - '%s is not resolvable', - is_array($callable) || is_object($callable) ? json_encode($callable) : $callable - )); + if (!is_array($toResolve)) { + return $toResolve; } + $candidate = $toResolve; + $class = array_shift($candidate); + $method = array_shift($candidate); + if (is_string($class) && is_string($method)) { + return $class . ':' . $method; + } + return $toResolve; } } diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/CallableResolverAwareTrait.php b/advancedcontentfilter/vendor/slim/slim/Slim/CallableResolverAwareTrait.php deleted file mode 100644 index ffb4eb28a..000000000 --- a/advancedcontentfilter/vendor/slim/slim/Slim/CallableResolverAwareTrait.php +++ /dev/null @@ -1,47 +0,0 @@ -container instanceof ContainerInterface) { - return $callable; - } - - /** @var CallableResolverInterface $resolver */ - $resolver = $this->container->get('callableResolver'); - - return $resolver->resolve($callable); - } -} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Collection.php b/advancedcontentfilter/vendor/slim/slim/Slim/Collection.php deleted file mode 100644 index 728bb73e0..000000000 --- a/advancedcontentfilter/vendor/slim/slim/Slim/Collection.php +++ /dev/null @@ -1,202 +0,0 @@ -replace($items); - } - - /******************************************************************************** - * Collection interface - *******************************************************************************/ - - /** - * Set collection item - * - * @param string $key The data key - * @param mixed $value The data value - */ - public function set($key, $value) - { - $this->data[$key] = $value; - } - - /** - * Get collection item for key - * - * @param string $key The data key - * @param mixed $default The default value to return if data key does not exist - * - * @return mixed The key's value, or the default value - */ - public function get($key, $default = null) - { - return $this->has($key) ? $this->data[$key] : $default; - } - - /** - * Add item to collection, replacing existing items with the same data key - * - * @param array $items Key-value array of data to append to this collection - */ - public function replace(array $items) - { - foreach ($items as $key => $value) { - $this->set($key, $value); - } - } - - /** - * Get all items in collection - * - * @return array The collection's source data - */ - public function all() - { - return $this->data; - } - - /** - * Get collection keys - * - * @return array The collection's source data keys - */ - public function keys() - { - return array_keys($this->data); - } - - /** - * Does this collection have a given key? - * - * @param string $key The data key - * - * @return bool - */ - public function has($key) - { - return array_key_exists($key, $this->data); - } - - /** - * Remove item from collection - * - * @param string $key The data key - */ - public function remove($key) - { - unset($this->data[$key]); - } - - /** - * Remove all items from collection - */ - public function clear() - { - $this->data = []; - } - - /******************************************************************************** - * ArrayAccess interface - *******************************************************************************/ - - /** - * Does this collection have a given key? - * - * @param string $key The data key - * - * @return bool - */ - public function offsetExists($key) - { - return $this->has($key); - } - - /** - * Get collection item for key - * - * @param string $key The data key - * - * @return mixed The key's value, or the default value - */ - public function offsetGet($key) - { - return $this->get($key); - } - - /** - * Set collection item - * - * @param string $key The data key - * @param mixed $value The data value - */ - public function offsetSet($key, $value) - { - $this->set($key, $value); - } - - /** - * Remove item from collection - * - * @param string $key The data key - */ - public function offsetUnset($key) - { - $this->remove($key); - } - - /** - * Get number of items in collection - * - * @return int - */ - public function count() - { - return count($this->data); - } - - /******************************************************************************** - * IteratorAggregate interface - *******************************************************************************/ - - /** - * Get collection iterator - * - * @return \ArrayIterator - */ - public function getIterator() - { - return new ArrayIterator($this->data); - } -} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Container.php b/advancedcontentfilter/vendor/slim/slim/Slim/Container.php deleted file mode 100644 index 1f713ac4e..000000000 --- a/advancedcontentfilter/vendor/slim/slim/Slim/Container.php +++ /dev/null @@ -1,179 +0,0 @@ - '1.1', - 'responseChunkSize' => 4096, - 'outputBuffering' => 'append', - 'determineRouteBeforeAppMiddleware' => false, - 'displayErrorDetails' => false, - 'addContentLengthHeader' => true, - 'routerCacheFile' => false, - ]; - - /** - * Create new container - * - * @param array $values The parameters or objects. - */ - public function __construct(array $values = []) - { - parent::__construct($values); - - $userSettings = isset($values['settings']) ? $values['settings'] : []; - $this->registerDefaultServices($userSettings); - } - - /** - * This function registers the default services that Slim needs to work. - * - * All services are shared - that is, they are registered such that the - * same instance is returned on subsequent calls. - * - * @param array $userSettings Associative array of application settings - * - * @return void - */ - private function registerDefaultServices($userSettings) - { - $defaultSettings = $this->defaultSettings; - - /** - * This service MUST return an array or an - * instance of \ArrayAccess. - * - * @return array|\ArrayAccess - */ - $this['settings'] = function () use ($userSettings, $defaultSettings) { - return new Collection(array_merge($defaultSettings, $userSettings)); - }; - - $defaultProvider = new DefaultServicesProvider(); - $defaultProvider->register($this); - } - - /******************************************************************************** - * Methods to satisfy Psr\Container\ContainerInterface - *******************************************************************************/ - - /** - * Finds an entry of the container by its identifier and returns it. - * - * @param string $id Identifier of the entry to look for. - * - * @throws ContainerValueNotFoundException No entry was found for this identifier. - * @throws ContainerException Error while retrieving the entry. - * - * @return mixed Entry. - */ - public function get($id) - { - if (!$this->offsetExists($id)) { - throw new ContainerValueNotFoundException(sprintf('Identifier "%s" is not defined.', $id)); - } - try { - return $this->offsetGet($id); - } catch (\InvalidArgumentException $exception) { - if ($this->exceptionThrownByContainer($exception)) { - throw new SlimContainerException( - sprintf('Container error while retrieving "%s"', $id), - null, - $exception - ); - } else { - throw $exception; - } - } - } - - /** - * Tests whether an exception needs to be recast for compliance with Container-Interop. This will be if the - * exception was thrown by Pimple. - * - * @param \InvalidArgumentException $exception - * - * @return bool - */ - private function exceptionThrownByContainer(\InvalidArgumentException $exception) - { - $trace = $exception->getTrace()[0]; - - return $trace['class'] === PimpleContainer::class && $trace['function'] === 'offsetGet'; - } - - /** - * Returns true if the container can return an entry for the given identifier. - * Returns false otherwise. - * - * @param string $id Identifier of the entry to look for. - * - * @return boolean - */ - public function has($id) - { - return $this->offsetExists($id); - } - - - /******************************************************************************** - * Magic methods for convenience - *******************************************************************************/ - - public function __get($name) - { - return $this->get($name); - } - - public function __isset($name) - { - return $this->has($name); - } -} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/DefaultServicesProvider.php b/advancedcontentfilter/vendor/slim/slim/Slim/DefaultServicesProvider.php deleted file mode 100644 index 13fe1fb31..000000000 --- a/advancedcontentfilter/vendor/slim/slim/Slim/DefaultServicesProvider.php +++ /dev/null @@ -1,211 +0,0 @@ -get('environment')); - }; - } - - if (!isset($container['response'])) { - /** - * PSR-7 Response object - * - * @param Container $container - * - * @return ResponseInterface - */ - $container['response'] = function ($container) { - $headers = new Headers(['Content-Type' => 'text/html; charset=UTF-8']); - $response = new Response(200, $headers); - - return $response->withProtocolVersion($container->get('settings')['httpVersion']); - }; - } - - if (!isset($container['router'])) { - /** - * This service MUST return a SHARED instance - * of \Slim\Interfaces\RouterInterface. - * - * @param Container $container - * - * @return RouterInterface - */ - $container['router'] = function ($container) { - $routerCacheFile = false; - if (isset($container->get('settings')['routerCacheFile'])) { - $routerCacheFile = $container->get('settings')['routerCacheFile']; - } - - - $router = (new Router)->setCacheFile($routerCacheFile); - if (method_exists($router, 'setContainer')) { - $router->setContainer($container); - } - - return $router; - }; - } - - if (!isset($container['foundHandler'])) { - /** - * This service MUST return a SHARED instance - * of \Slim\Interfaces\InvocationStrategyInterface. - * - * @return InvocationStrategyInterface - */ - $container['foundHandler'] = function () { - return new RequestResponse; - }; - } - - if (!isset($container['phpErrorHandler'])) { - /** - * This service MUST return a callable - * that accepts three arguments: - * - * 1. Instance of \Psr\Http\Message\ServerRequestInterface - * 2. Instance of \Psr\Http\Message\ResponseInterface - * 3. Instance of \Error - * - * The callable MUST return an instance of - * \Psr\Http\Message\ResponseInterface. - * - * @param Container $container - * - * @return callable - */ - $container['phpErrorHandler'] = function ($container) { - return new PhpError($container->get('settings')['displayErrorDetails']); - }; - } - - if (!isset($container['errorHandler'])) { - /** - * This service MUST return a callable - * that accepts three arguments: - * - * 1. Instance of \Psr\Http\Message\ServerRequestInterface - * 2. Instance of \Psr\Http\Message\ResponseInterface - * 3. Instance of \Exception - * - * The callable MUST return an instance of - * \Psr\Http\Message\ResponseInterface. - * - * @param Container $container - * - * @return callable - */ - $container['errorHandler'] = function ($container) { - return new Error( - $container->get('settings')['displayErrorDetails'] - ); - }; - } - - if (!isset($container['notFoundHandler'])) { - /** - * This service MUST return a callable - * that accepts two arguments: - * - * 1. Instance of \Psr\Http\Message\ServerRequestInterface - * 2. Instance of \Psr\Http\Message\ResponseInterface - * - * The callable MUST return an instance of - * \Psr\Http\Message\ResponseInterface. - * - * @return callable - */ - $container['notFoundHandler'] = function () { - return new NotFound; - }; - } - - if (!isset($container['notAllowedHandler'])) { - /** - * This service MUST return a callable - * that accepts three arguments: - * - * 1. Instance of \Psr\Http\Message\ServerRequestInterface - * 2. Instance of \Psr\Http\Message\ResponseInterface - * 3. Array of allowed HTTP methods - * - * The callable MUST return an instance of - * \Psr\Http\Message\ResponseInterface. - * - * @return callable - */ - $container['notAllowedHandler'] = function () { - return new NotAllowed; - }; - } - - if (!isset($container['callableResolver'])) { - /** - * Instance of \Slim\Interfaces\CallableResolverInterface - * - * @param Container $container - * - * @return CallableResolverInterface - */ - $container['callableResolver'] = function ($container) { - return new CallableResolver($container); - }; - } - } -} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/DeferredCallable.php b/advancedcontentfilter/vendor/slim/slim/Slim/DeferredCallable.php deleted file mode 100644 index 22887c0fc..000000000 --- a/advancedcontentfilter/vendor/slim/slim/Slim/DeferredCallable.php +++ /dev/null @@ -1,45 +0,0 @@ -callable = $callable; - $this->container = $container; - } - - public function __invoke() - { - $callable = $this->resolveCallable($this->callable); - if ($callable instanceof Closure) { - $callable = $callable->bindTo($this->container); - } - - $args = func_get_args(); - - return call_user_func_array($callable, $args); - } -} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Error/AbstractErrorRenderer.php b/advancedcontentfilter/vendor/slim/slim/Slim/Error/AbstractErrorRenderer.php new file mode 100644 index 000000000..90b290d41 --- /dev/null +++ b/advancedcontentfilter/vendor/slim/slim/Slim/Error/AbstractErrorRenderer.php @@ -0,0 +1,46 @@ +getTitle(); + } + + return $this->defaultErrorTitle; + } + + protected function getErrorDescription(Throwable $exception): string + { + if ($exception instanceof HttpException) { + return $exception->getDescription(); + } + + return $this->defaultErrorDescription; + } +} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Error/Renderers/HtmlErrorRenderer.php b/advancedcontentfilter/vendor/slim/slim/Slim/Error/Renderers/HtmlErrorRenderer.php new file mode 100644 index 000000000..e030522aa --- /dev/null +++ b/advancedcontentfilter/vendor/slim/slim/Slim/Error/Renderers/HtmlErrorRenderer.php @@ -0,0 +1,84 @@ +The application could not run because of the following error:

'; + $html .= '

Details

'; + $html .= $this->renderExceptionFragment($exception); + } else { + $html = "

{$this->getErrorDescription($exception)}

"; + } + + return $this->renderHtmlBody($this->getErrorTitle($exception), $html); + } + + private function renderExceptionFragment(Throwable $exception): string + { + $html = sprintf('
Type: %s
', get_class($exception)); + + /** @var int|string $code */ + $code = $exception->getCode(); + $html .= sprintf('
Code: %s
', $code); + + $html .= sprintf('
Message: %s
', htmlentities($exception->getMessage())); + + $html .= sprintf('
File: %s
', $exception->getFile()); + + $html .= sprintf('
Line: %s
', $exception->getLine()); + + $html .= '

Trace

'; + $html .= sprintf('
%s
', htmlentities($exception->getTraceAsString())); + + return $html; + } + + public function renderHtmlBody(string $title = '', string $html = ''): string + { + return sprintf( + '' . + '' . + ' ' . + ' ' . + ' ' . + ' %s' . + ' ' . + ' ' . + ' ' . + '

%s

' . + '
%s
' . + ' Go Back' . + ' ' . + '', + $title, + $title, + $html + ); + } +} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Error/Renderers/JsonErrorRenderer.php b/advancedcontentfilter/vendor/slim/slim/Slim/Error/Renderers/JsonErrorRenderer.php new file mode 100644 index 000000000..63d905b3c --- /dev/null +++ b/advancedcontentfilter/vendor/slim/slim/Slim/Error/Renderers/JsonErrorRenderer.php @@ -0,0 +1,56 @@ + $this->getErrorTitle($exception)]; + + if ($displayErrorDetails) { + $error['exception'] = []; + do { + $error['exception'][] = $this->formatExceptionFragment($exception); + } while ($exception = $exception->getPrevious()); + } + + return (string) json_encode($error, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); + } + + /** + * @return array + */ + private function formatExceptionFragment(Throwable $exception): array + { + /** @var int|string $code */ + $code = $exception->getCode(); + return [ + 'type' => get_class($exception), + 'code' => $code, + 'message' => $exception->getMessage(), + 'file' => $exception->getFile(), + 'line' => $exception->getLine(), + ]; + } +} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Error/Renderers/PlainTextErrorRenderer.php b/advancedcontentfilter/vendor/slim/slim/Slim/Error/Renderers/PlainTextErrorRenderer.php new file mode 100644 index 000000000..3d80c74be --- /dev/null +++ b/advancedcontentfilter/vendor/slim/slim/Slim/Error/Renderers/PlainTextErrorRenderer.php @@ -0,0 +1,59 @@ +getErrorTitle($exception)}\n"; + + if ($displayErrorDetails) { + $text .= $this->formatExceptionFragment($exception); + + while ($exception = $exception->getPrevious()) { + $text .= "\nPrevious Error:\n"; + $text .= $this->formatExceptionFragment($exception); + } + } + + return $text; + } + + private function formatExceptionFragment(Throwable $exception): string + { + $text = sprintf("Type: %s\n", get_class($exception)); + + $code = $exception->getCode(); + /** @var int|string $code */ + $text .= sprintf("Code: %s\n", $code); + + $text .= sprintf("Message: %s\n", htmlentities($exception->getMessage())); + + $text .= sprintf("File: %s\n", $exception->getFile()); + + $text .= sprintf("Line: %s\n", $exception->getLine()); + + $text .= sprintf('Trace: %s', $exception->getTraceAsString()); + + return $text; + } +} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Error/Renderers/XmlErrorRenderer.php b/advancedcontentfilter/vendor/slim/slim/Slim/Error/Renderers/XmlErrorRenderer.php new file mode 100644 index 000000000..1171b79b2 --- /dev/null +++ b/advancedcontentfilter/vendor/slim/slim/Slim/Error/Renderers/XmlErrorRenderer.php @@ -0,0 +1,54 @@ +\n"; + $xml .= "\n " . $this->createCdataSection($this->getErrorTitle($exception)) . "\n"; + + if ($displayErrorDetails) { + do { + $xml .= " \n"; + $xml .= ' ' . get_class($exception) . "\n"; + $xml .= ' ' . $exception->getCode() . "\n"; + $xml .= ' ' . $this->createCdataSection($exception->getMessage()) . "\n"; + $xml .= ' ' . $exception->getFile() . "\n"; + $xml .= ' ' . $exception->getLine() . "\n"; + $xml .= " \n"; + } while ($exception = $exception->getPrevious()); + } + + $xml .= ''; + + return $xml; + } + + /** + * Returns a CDATA section with the given content. + */ + private function createCdataSection(string $content): string + { + return sprintf('', str_replace(']]>', ']]]]>', $content)); + } +} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Exception/ContainerException.php b/advancedcontentfilter/vendor/slim/slim/Slim/Exception/ContainerException.php deleted file mode 100644 index 06163f1da..000000000 --- a/advancedcontentfilter/vendor/slim/slim/Slim/Exception/ContainerException.php +++ /dev/null @@ -1,20 +0,0 @@ -request = $request; + } + + public function getRequest(): ServerRequestInterface + { + return $this->request; + } + + public function getTitle(): string + { + return $this->title; + } + + public function setTitle(string $title): self + { + $this->title = $title; + return $this; + } + + public function getDescription(): string + { + return $this->description; + } + + public function setDescription(string $description): self + { + $this->description = $description; + return $this; + } +} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Exception/HttpForbiddenException.php b/advancedcontentfilter/vendor/slim/slim/Slim/Exception/HttpForbiddenException.php new file mode 100644 index 000000000..dd3bb230a --- /dev/null +++ b/advancedcontentfilter/vendor/slim/slim/Slim/Exception/HttpForbiddenException.php @@ -0,0 +1,27 @@ +allowedMethods; + } + + /** + * @param string[] $methods + */ + public function setAllowedMethods(array $methods): self + { + $this->allowedMethods = $methods; + $this->message = 'Method not allowed. Must be one of: ' . implode(', ', $methods); + return $this; + } +} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Exception/HttpNotFoundException.php b/advancedcontentfilter/vendor/slim/slim/Slim/Exception/HttpNotFoundException.php new file mode 100644 index 000000000..865146d68 --- /dev/null +++ b/advancedcontentfilter/vendor/slim/slim/Slim/Exception/HttpNotFoundException.php @@ -0,0 +1,27 @@ +message = $message; + } + + parent::__construct($request, $this->message, $this->code, $previous); + } +} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Exception/HttpUnauthorizedException.php b/advancedcontentfilter/vendor/slim/slim/Slim/Exception/HttpUnauthorizedException.php new file mode 100644 index 000000000..07bd70d01 --- /dev/null +++ b/advancedcontentfilter/vendor/slim/slim/Slim/Exception/HttpUnauthorizedException.php @@ -0,0 +1,27 @@ +request = $request; - parent::__construct(sprintf('Unsupported HTTP method "%s" provided', $method)); - } - - public function getRequest() - { - return $this->request; - } -} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Exception/MethodNotAllowedException.php b/advancedcontentfilter/vendor/slim/slim/Slim/Exception/MethodNotAllowedException.php deleted file mode 100644 index 951f5dfbe..000000000 --- a/advancedcontentfilter/vendor/slim/slim/Slim/Exception/MethodNotAllowedException.php +++ /dev/null @@ -1,45 +0,0 @@ -allowedMethods = $allowedMethods; - } - - /** - * Get allowed methods - * - * @return string[] - */ - public function getAllowedMethods() - { - return $this->allowedMethods; - } -} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Exception/NotFoundException.php b/advancedcontentfilter/vendor/slim/slim/Slim/Exception/NotFoundException.php deleted file mode 100644 index 9e72e14e6..000000000 --- a/advancedcontentfilter/vendor/slim/slim/Slim/Exception/NotFoundException.php +++ /dev/null @@ -1,14 +0,0 @@ -request = $request; - $this->response = $response; - } - - /** - * Get request - * - * @return ServerRequestInterface - */ - public function getRequest() - { - return $this->request; - } - - /** - * Get response - * - * @return ResponseInterface - */ - public function getResponse() - { - return $this->response; - } -} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Factory/AppFactory.php b/advancedcontentfilter/vendor/slim/slim/Slim/Factory/AppFactory.php new file mode 100644 index 000000000..6fc5f86ea --- /dev/null +++ b/advancedcontentfilter/vendor/slim/slim/Slim/Factory/AppFactory.php @@ -0,0 +1,206 @@ +has(ResponseFactoryInterface::class) + && ( + $responseFactoryFromContainer = $container->get(ResponseFactoryInterface::class) + ) instanceof ResponseFactoryInterface + ? $responseFactoryFromContainer + : self::determineResponseFactory(); + + $callableResolver = $container->has(CallableResolverInterface::class) + && ( + $callableResolverFromContainer = $container->get(CallableResolverInterface::class) + ) instanceof CallableResolverInterface + ? $callableResolverFromContainer + : null; + + $routeCollector = $container->has(RouteCollectorInterface::class) + && ( + $routeCollectorFromContainer = $container->get(RouteCollectorInterface::class) + ) instanceof RouteCollectorInterface + ? $routeCollectorFromContainer + : null; + + $routeResolver = $container->has(RouteResolverInterface::class) + && ( + $routeResolverFromContainer = $container->get(RouteResolverInterface::class) + ) instanceof RouteResolverInterface + ? $routeResolverFromContainer + : null; + + $middlewareDispatcher = $container->has(MiddlewareDispatcherInterface::class) + && ( + $middlewareDispatcherFromContainer = $container->get(MiddlewareDispatcherInterface::class) + ) instanceof MiddlewareDispatcherInterface + ? $middlewareDispatcherFromContainer + : null; + + return new App( + $responseFactory, + $container, + $callableResolver, + $routeCollector, + $routeResolver, + $middlewareDispatcher + ); + } + + /** + * @throws RuntimeException + */ + public static function determineResponseFactory(): ResponseFactoryInterface + { + if (static::$responseFactory) { + if (static::$streamFactory) { + return static::attemptResponseFactoryDecoration(static::$responseFactory, static::$streamFactory); + } + return static::$responseFactory; + } + + $psr17FactoryProvider = static::$psr17FactoryProvider ?? new Psr17FactoryProvider(); + + /** @var Psr17Factory $psr17factory */ + foreach ($psr17FactoryProvider->getFactories() as $psr17factory) { + if ($psr17factory::isResponseFactoryAvailable()) { + $responseFactory = $psr17factory::getResponseFactory(); + + if (static::$streamFactory || $psr17factory::isStreamFactoryAvailable()) { + $streamFactory = static::$streamFactory ?? $psr17factory::getStreamFactory(); + return static::attemptResponseFactoryDecoration($responseFactory, $streamFactory); + } + + return $responseFactory; + } + } + + throw new RuntimeException( + "Could not detect any PSR-17 ResponseFactory implementations. " . + "Please install a supported implementation in order to use `AppFactory::create()`. " . + "See https://github.com/slimphp/Slim/blob/4.x/README.md for a list of supported implementations." + ); + } + + protected static function attemptResponseFactoryDecoration( + ResponseFactoryInterface $responseFactory, + StreamFactoryInterface $streamFactory + ): ResponseFactoryInterface { + if ( + static::$slimHttpDecoratorsAutomaticDetectionEnabled + && SlimHttpPsr17Factory::isResponseFactoryAvailable() + ) { + return SlimHttpPsr17Factory::createDecoratedResponseFactory($responseFactory, $streamFactory); + } + + return $responseFactory; + } + + public static function setPsr17FactoryProvider(Psr17FactoryProviderInterface $psr17FactoryProvider): void + { + static::$psr17FactoryProvider = $psr17FactoryProvider; + } + + public static function setResponseFactory(ResponseFactoryInterface $responseFactory): void + { + static::$responseFactory = $responseFactory; + } + + public static function setStreamFactory(StreamFactoryInterface $streamFactory): void + { + static::$streamFactory = $streamFactory; + } + + public static function setContainer(ContainerInterface $container): void + { + static::$container = $container; + } + + public static function setCallableResolver(CallableResolverInterface $callableResolver): void + { + static::$callableResolver = $callableResolver; + } + + public static function setRouteCollector(RouteCollectorInterface $routeCollector): void + { + static::$routeCollector = $routeCollector; + } + + public static function setRouteResolver(RouteResolverInterface $routeResolver): void + { + static::$routeResolver = $routeResolver; + } + + public static function setMiddlewareDispatcher(MiddlewareDispatcherInterface $middlewareDispatcher): void + { + static::$middlewareDispatcher = $middlewareDispatcher; + } + + public static function setSlimHttpDecoratorsAutomaticDetection(bool $enabled): void + { + static::$slimHttpDecoratorsAutomaticDetectionEnabled = $enabled; + } +} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Factory/Psr17/GuzzlePsr17Factory.php b/advancedcontentfilter/vendor/slim/slim/Slim/Factory/Psr17/GuzzlePsr17Factory.php new file mode 100644 index 000000000..32a548a67 --- /dev/null +++ b/advancedcontentfilter/vendor/slim/slim/Slim/Factory/Psr17/GuzzlePsr17Factory.php @@ -0,0 +1,19 @@ +serverRequestCreator = $serverRequestCreator; + $this->serverRequestCreatorMethod = $serverRequestCreatorMethod; + } + + /** + * {@inheritdoc} + */ + public function createServerRequestFromGlobals(): ServerRequestInterface + { + /** @var callable $callable */ + $callable = [$this->serverRequestCreator, $this->serverRequestCreatorMethod]; + return (Closure::fromCallable($callable))(); + } +} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Factory/Psr17/SlimHttpPsr17Factory.php b/advancedcontentfilter/vendor/slim/slim/Slim/Factory/Psr17/SlimHttpPsr17Factory.php new file mode 100644 index 000000000..5d636318b --- /dev/null +++ b/advancedcontentfilter/vendor/slim/slim/Slim/Factory/Psr17/SlimHttpPsr17Factory.php @@ -0,0 +1,39 @@ +serverRequestCreator = $serverRequestCreator; + } + + /** + * {@inheritdoc} + */ + public function createServerRequestFromGlobals(): ServerRequestInterface + { + if (!static::isServerRequestDecoratorAvailable()) { + throw new RuntimeException('The Slim-Http ServerRequest decorator is not available.'); + } + + $request = $this->serverRequestCreator->createServerRequestFromGlobals(); + + if ( + !(( + $decoratedServerRequest = new static::$serverRequestDecoratorClass($request) + ) instanceof ServerRequestInterface) + ) { + throw new RuntimeException(get_called_class() . ' could not instantiate a decorated server request.'); + } + + return $decoratedServerRequest; + } + + public static function isServerRequestDecoratorAvailable(): bool + { + return class_exists(static::$serverRequestDecoratorClass); + } +} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Factory/Psr17/SlimPsr17Factory.php b/advancedcontentfilter/vendor/slim/slim/Slim/Factory/Psr17/SlimPsr17Factory.php new file mode 100644 index 000000000..46c46f9ce --- /dev/null +++ b/advancedcontentfilter/vendor/slim/slim/Slim/Factory/Psr17/SlimPsr17Factory.php @@ -0,0 +1,19 @@ +getFactories() as $psr17Factory) { + if ($psr17Factory::isServerRequestCreatorAvailable()) { + $serverRequestCreator = $psr17Factory::getServerRequestCreator(); + return static::attemptServerRequestCreatorDecoration($serverRequestCreator); + } + } + + throw new RuntimeException( + "Could not detect any ServerRequest creator implementations. " . + "Please install a supported implementation in order to use `App::run()` " . + "without having to pass in a `ServerRequest` object. " . + "See https://github.com/slimphp/Slim/blob/4.x/README.md for a list of supported implementations." + ); + } + + protected static function attemptServerRequestCreatorDecoration( + ServerRequestCreatorInterface $serverRequestCreator + ): ServerRequestCreatorInterface { + if ( + static::$slimHttpDecoratorsAutomaticDetectionEnabled + && SlimHttpServerRequestCreator::isServerRequestDecoratorAvailable() + ) { + return new SlimHttpServerRequestCreator($serverRequestCreator); + } + + return $serverRequestCreator; + } + + public static function setPsr17FactoryProvider(Psr17FactoryProviderInterface $psr17FactoryProvider): void + { + static::$psr17FactoryProvider = $psr17FactoryProvider; + } + + public static function setServerRequestCreator(ServerRequestCreatorInterface $serverRequestCreator): void + { + self::$serverRequestCreator = $serverRequestCreator; + } + + public static function setSlimHttpDecoratorsAutomaticDetection(bool $enabled): void + { + static::$slimHttpDecoratorsAutomaticDetectionEnabled = $enabled; + } +} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Handlers/AbstractError.php b/advancedcontentfilter/vendor/slim/slim/Slim/Handlers/AbstractError.php deleted file mode 100644 index 42f8dde3d..000000000 --- a/advancedcontentfilter/vendor/slim/slim/Slim/Handlers/AbstractError.php +++ /dev/null @@ -1,99 +0,0 @@ -displayErrorDetails = (bool) $displayErrorDetails; - } - - /** - * Write to the error log if displayErrorDetails is false - * - * @param \Exception|\Throwable $throwable - * - * @return void - */ - protected function writeToErrorLog($throwable) - { - if ($this->displayErrorDetails) { - return; - } - - $message = 'Slim Application Error:' . PHP_EOL; - $message .= $this->renderThrowableAsText($throwable); - while ($throwable = $throwable->getPrevious()) { - $message .= PHP_EOL . 'Previous error:' . PHP_EOL; - $message .= $this->renderThrowableAsText($throwable); - } - - $message .= PHP_EOL . 'View in rendered output by enabling the "displayErrorDetails" setting.' . PHP_EOL; - - $this->logError($message); - } - - /** - * Render error as Text. - * - * @param \Exception|\Throwable $throwable - * - * @return string - */ - protected function renderThrowableAsText($throwable) - { - $text = sprintf('Type: %s' . PHP_EOL, get_class($throwable)); - - if ($code = $throwable->getCode()) { - $text .= sprintf('Code: %s' . PHP_EOL, $code); - } - - if ($message = $throwable->getMessage()) { - $text .= sprintf('Message: %s' . PHP_EOL, htmlentities($message)); - } - - if ($file = $throwable->getFile()) { - $text .= sprintf('File: %s' . PHP_EOL, $file); - } - - if ($line = $throwable->getLine()) { - $text .= sprintf('Line: %s' . PHP_EOL, $line); - } - - if ($trace = $throwable->getTraceAsString()) { - $text .= sprintf('Trace: %s', $trace); - } - - return $text; - } - - /** - * Wraps the error_log function so that this can be easily tested - * - * @param $message - */ - protected function logError($message) - { - error_log($message); - } -} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Handlers/AbstractHandler.php b/advancedcontentfilter/vendor/slim/slim/Slim/Handlers/AbstractHandler.php deleted file mode 100644 index b166a1564..000000000 --- a/advancedcontentfilter/vendor/slim/slim/Slim/Handlers/AbstractHandler.php +++ /dev/null @@ -1,59 +0,0 @@ -getHeaderLine('Accept'); - $selectedContentTypes = array_intersect(explode(',', $acceptHeader), $this->knownContentTypes); - - if (count($selectedContentTypes)) { - return current($selectedContentTypes); - } - - // handle +json and +xml specially - if (preg_match('/\+(json|xml)/', $acceptHeader, $matches)) { - $mediaType = 'application/' . $matches[1]; - if (in_array($mediaType, $this->knownContentTypes)) { - return $mediaType; - } - } - - return 'text/html'; - } -} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Handlers/Error.php b/advancedcontentfilter/vendor/slim/slim/Slim/Handlers/Error.php deleted file mode 100644 index dd0bc8d4e..000000000 --- a/advancedcontentfilter/vendor/slim/slim/Slim/Handlers/Error.php +++ /dev/null @@ -1,224 +0,0 @@ -determineContentType($request); - switch ($contentType) { - case 'application/json': - $output = $this->renderJsonErrorMessage($exception); - break; - - case 'text/xml': - case 'application/xml': - $output = $this->renderXmlErrorMessage($exception); - break; - - case 'text/html': - $output = $this->renderHtmlErrorMessage($exception); - break; - - default: - throw new UnexpectedValueException('Cannot render unknown content type ' . $contentType); - } - - $this->writeToErrorLog($exception); - - $body = new Body(fopen('php://temp', 'r+')); - $body->write($output); - - return $response - ->withStatus(500) - ->withHeader('Content-type', $contentType) - ->withBody($body); - } - - /** - * Render HTML error page - * - * @param \Exception $exception - * - * @return string - */ - protected function renderHtmlErrorMessage(\Exception $exception) - { - $title = 'Slim Application Error'; - - if ($this->displayErrorDetails) { - $html = '

The application could not run because of the following error:

'; - $html .= '

Details

'; - $html .= $this->renderHtmlException($exception); - - while ($exception = $exception->getPrevious()) { - $html .= '

Previous exception

'; - $html .= $this->renderHtmlExceptionOrError($exception); - } - } else { - $html = '

A website error has occurred. Sorry for the temporary inconvenience.

'; - } - - $output = sprintf( - "" . - "%s

%s

%s", - $title, - $title, - $html - ); - - return $output; - } - - /** - * Render exception as HTML. - * - * Provided for backwards compatibility; use renderHtmlExceptionOrError(). - * - * @param \Exception $exception - * - * @return string - */ - protected function renderHtmlException(\Exception $exception) - { - return $this->renderHtmlExceptionOrError($exception); - } - - /** - * Render exception or error as HTML. - * - * @param \Exception|\Error $exception - * - * @return string - */ - protected function renderHtmlExceptionOrError($exception) - { - if (!$exception instanceof \Exception && !$exception instanceof \Error) { - throw new \RuntimeException("Unexpected type. Expected Exception or Error."); - } - - $html = sprintf('
Type: %s
', get_class($exception)); - - if (($code = $exception->getCode())) { - $html .= sprintf('
Code: %s
', $code); - } - - if (($message = $exception->getMessage())) { - $html .= sprintf('
Message: %s
', htmlentities($message)); - } - - if (($file = $exception->getFile())) { - $html .= sprintf('
File: %s
', $file); - } - - if (($line = $exception->getLine())) { - $html .= sprintf('
Line: %s
', $line); - } - - if (($trace = $exception->getTraceAsString())) { - $html .= '

Trace

'; - $html .= sprintf('
%s
', htmlentities($trace)); - } - - return $html; - } - - /** - * Render JSON error - * - * @param \Exception $exception - * - * @return string - */ - protected function renderJsonErrorMessage(\Exception $exception) - { - $error = [ - 'message' => 'Slim Application Error', - ]; - - if ($this->displayErrorDetails) { - $error['exception'] = []; - - do { - $error['exception'][] = [ - 'type' => get_class($exception), - 'code' => $exception->getCode(), - 'message' => $exception->getMessage(), - 'file' => $exception->getFile(), - 'line' => $exception->getLine(), - 'trace' => explode("\n", $exception->getTraceAsString()), - ]; - } while ($exception = $exception->getPrevious()); - } - - return json_encode($error, JSON_PRETTY_PRINT); - } - - /** - * Render XML error - * - * @param \Exception $exception - * - * @return string - */ - protected function renderXmlErrorMessage(\Exception $exception) - { - $xml = "\n Slim Application Error\n"; - if ($this->displayErrorDetails) { - do { - $xml .= " \n"; - $xml .= " " . get_class($exception) . "\n"; - $xml .= " " . $exception->getCode() . "\n"; - $xml .= " " . $this->createCdataSection($exception->getMessage()) . "\n"; - $xml .= " " . $exception->getFile() . "\n"; - $xml .= " " . $exception->getLine() . "\n"; - $xml .= " " . $this->createCdataSection($exception->getTraceAsString()) . "\n"; - $xml .= " \n"; - } while ($exception = $exception->getPrevious()); - } - $xml .= ""; - - return $xml; - } - - /** - * Returns a CDATA section with the given content. - * - * @param string $content - * @return string - */ - private function createCdataSection($content) - { - return sprintf('', str_replace(']]>', ']]]]>', $content)); - } -} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Handlers/ErrorHandler.php b/advancedcontentfilter/vendor/slim/slim/Slim/Handlers/ErrorHandler.php new file mode 100644 index 000000000..f9606e364 --- /dev/null +++ b/advancedcontentfilter/vendor/slim/slim/Slim/Handlers/ErrorHandler.php @@ -0,0 +1,308 @@ + + */ + protected array $errorRenderers = [ + 'application/json' => JsonErrorRenderer::class, + 'application/xml' => XmlErrorRenderer::class, + 'text/xml' => XmlErrorRenderer::class, + 'text/html' => HtmlErrorRenderer::class, + 'text/plain' => PlainTextErrorRenderer::class, + ]; + + protected bool $displayErrorDetails = false; + + protected bool $logErrors; + + protected bool $logErrorDetails = false; + + protected ?string $contentType = null; + + protected ?string $method = null; + + protected ServerRequestInterface $request; + + protected Throwable $exception; + + protected int $statusCode; + + protected CallableResolverInterface $callableResolver; + + protected ResponseFactoryInterface $responseFactory; + + protected LoggerInterface $logger; + + public function __construct( + CallableResolverInterface $callableResolver, + ResponseFactoryInterface $responseFactory, + ?LoggerInterface $logger = null + ) { + $this->callableResolver = $callableResolver; + $this->responseFactory = $responseFactory; + $this->logger = $logger ?: $this->getDefaultLogger(); + } + + /** + * Invoke error handler + * + * @param ServerRequestInterface $request The most recent Request object + * @param Throwable $exception The caught Exception object + * @param bool $displayErrorDetails Whether or not to display the error details + * @param bool $logErrors Whether or not to log errors + * @param bool $logErrorDetails Whether or not to log error details + */ + public function __invoke( + ServerRequestInterface $request, + Throwable $exception, + bool $displayErrorDetails, + bool $logErrors, + bool $logErrorDetails + ): ResponseInterface { + $this->displayErrorDetails = $displayErrorDetails; + $this->logErrors = $logErrors; + $this->logErrorDetails = $logErrorDetails; + $this->request = $request; + $this->exception = $exception; + $this->method = $request->getMethod(); + $this->statusCode = $this->determineStatusCode(); + if ($this->contentType === null) { + $this->contentType = $this->determineContentType($request); + } + + if ($logErrors) { + $this->writeToErrorLog(); + } + + return $this->respond(); + } + + /** + * Force the content type for all error handler responses. + * + * @param string|null $contentType The content type + */ + public function forceContentType(?string $contentType): void + { + $this->contentType = $contentType; + } + + protected function determineStatusCode(): int + { + if ($this->method === 'OPTIONS') { + return 200; + } + + if ($this->exception instanceof HttpException) { + return $this->exception->getCode(); + } + + return 500; + } + + /** + * Determine which content type we know about is wanted using Accept header + * + * Note: This method is a bare-bones implementation designed specifically for + * Slim's error handling requirements. Consider a fully-feature solution such + * as willdurand/negotiation for any other situation. + */ + protected function determineContentType(ServerRequestInterface $request): ?string + { + $acceptHeader = $request->getHeaderLine('Accept'); + $selectedContentTypes = array_intersect( + explode(',', $acceptHeader), + array_keys($this->errorRenderers) + ); + $count = count($selectedContentTypes); + + if ($count) { + $current = current($selectedContentTypes); + + /** + * Ensure other supported content types take precedence over text/plain + * when multiple content types are provided via Accept header. + */ + if ($current === 'text/plain' && $count > 1) { + $next = next($selectedContentTypes); + if (is_string($next)) { + return $next; + } + } + + if (is_string($current)) { + return $current; + } + } + + if (preg_match('/\+(json|xml)/', $acceptHeader, $matches)) { + $mediaType = 'application/' . $matches[1]; + if (array_key_exists($mediaType, $this->errorRenderers)) { + return $mediaType; + } + } + + return null; + } + + /** + * Determine which renderer to use based on content type + * + * @throws RuntimeException + */ + protected function determineRenderer(): callable + { + if ($this->contentType !== null && array_key_exists($this->contentType, $this->errorRenderers)) { + $renderer = $this->errorRenderers[$this->contentType]; + } else { + $renderer = $this->defaultErrorRenderer; + } + + return $this->callableResolver->resolve($renderer); + } + + /** + * Register an error renderer for a specific content-type + * + * @param string $contentType The content-type this renderer should be registered to + * @param ErrorRendererInterface|string|callable $errorRenderer The error renderer + */ + public function registerErrorRenderer(string $contentType, $errorRenderer): void + { + $this->errorRenderers[$contentType] = $errorRenderer; + } + + /** + * Set the default error renderer + * + * @param string $contentType The content type of the default error renderer + * @param ErrorRendererInterface|string|callable $errorRenderer The default error renderer + */ + public function setDefaultErrorRenderer(string $contentType, $errorRenderer): void + { + $this->defaultErrorRendererContentType = $contentType; + $this->defaultErrorRenderer = $errorRenderer; + } + + /** + * Set the renderer for the error logger + * + * @param ErrorRendererInterface|string|callable $logErrorRenderer + */ + public function setLogErrorRenderer($logErrorRenderer): void + { + $this->logErrorRenderer = $logErrorRenderer; + } + + /** + * Write to the error log if $logErrors has been set to true + */ + protected function writeToErrorLog(): void + { + $renderer = $this->callableResolver->resolve($this->logErrorRenderer); + $error = $renderer($this->exception, $this->logErrorDetails); + if (!$this->displayErrorDetails) { + $error .= "\nTips: To display error details in HTTP response "; + $error .= 'set "displayErrorDetails" to true in the ErrorHandler constructor.'; + } + $this->logError($error); + } + + /** + * Wraps the error_log function so that this can be easily tested + */ + protected function logError(string $error): void + { + $this->logger->error($error); + } + + /** + * Returns a default logger implementation. + */ + protected function getDefaultLogger(): LoggerInterface + { + return new Logger(); + } + + protected function respond(): ResponseInterface + { + $response = $this->responseFactory->createResponse($this->statusCode); + if ($this->contentType !== null && array_key_exists($this->contentType, $this->errorRenderers)) { + $response = $response->withHeader('Content-type', $this->contentType); + } else { + $response = $response->withHeader('Content-type', $this->defaultErrorRendererContentType); + } + + if ($this->exception instanceof HttpMethodNotAllowedException) { + $allowedMethods = implode(', ', $this->exception->getAllowedMethods()); + $response = $response->withHeader('Allow', $allowedMethods); + } + + $renderer = $this->determineRenderer(); + $body = call_user_func($renderer, $this->exception, $this->displayErrorDetails); + if ($body !== false) { + /** @var string $body */ + $response->getBody()->write($body); + } + + return $response; + } +} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Handlers/NotAllowed.php b/advancedcontentfilter/vendor/slim/slim/Slim/Handlers/NotAllowed.php deleted file mode 100644 index 345f0ff8c..000000000 --- a/advancedcontentfilter/vendor/slim/slim/Slim/Handlers/NotAllowed.php +++ /dev/null @@ -1,147 +0,0 @@ -getMethod() === 'OPTIONS') { - $status = 200; - $contentType = 'text/plain'; - $output = $this->renderPlainOptionsMessage($methods); - } else { - $status = 405; - $contentType = $this->determineContentType($request); - switch ($contentType) { - case 'application/json': - $output = $this->renderJsonNotAllowedMessage($methods); - break; - - case 'text/xml': - case 'application/xml': - $output = $this->renderXmlNotAllowedMessage($methods); - break; - - case 'text/html': - $output = $this->renderHtmlNotAllowedMessage($methods); - break; - default: - throw new UnexpectedValueException('Cannot render unknown content type ' . $contentType); - } - } - - $body = new Body(fopen('php://temp', 'r+')); - $body->write($output); - $allow = implode(', ', $methods); - - return $response - ->withStatus($status) - ->withHeader('Content-type', $contentType) - ->withHeader('Allow', $allow) - ->withBody($body); - } - - /** - * Render PLAIN message for OPTIONS response - * - * @param array $methods - * @return string - */ - protected function renderPlainOptionsMessage($methods) - { - $allow = implode(', ', $methods); - - return 'Allowed methods: ' . $allow; - } - - /** - * Render JSON not allowed message - * - * @param array $methods - * @return string - */ - protected function renderJsonNotAllowedMessage($methods) - { - $allow = implode(', ', $methods); - - return '{"message":"Method not allowed. Must be one of: ' . $allow . '"}'; - } - - /** - * Render XML not allowed message - * - * @param array $methods - * @return string - */ - protected function renderXmlNotAllowedMessage($methods) - { - $allow = implode(', ', $methods); - - return "Method not allowed. Must be one of: $allow"; - } - - /** - * Render HTML not allowed message - * - * @param array $methods - * @return string - */ - protected function renderHtmlNotAllowedMessage($methods) - { - $allow = implode(', ', $methods); - $output = << - - Method not allowed - - - -

Method not allowed

-

Method not allowed. Must be one of: $allow

- - -END; - - return $output; - } -} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Handlers/NotFound.php b/advancedcontentfilter/vendor/slim/slim/Slim/Handlers/NotFound.php deleted file mode 100644 index b3330321f..000000000 --- a/advancedcontentfilter/vendor/slim/slim/Slim/Handlers/NotFound.php +++ /dev/null @@ -1,141 +0,0 @@ -getMethod() === 'OPTIONS') { - $contentType = 'text/plain'; - $output = $this->renderPlainNotFoundOutput(); - } else { - $contentType = $this->determineContentType($request); - switch ($contentType) { - case 'application/json': - $output = $this->renderJsonNotFoundOutput(); - break; - - case 'text/xml': - case 'application/xml': - $output = $this->renderXmlNotFoundOutput(); - break; - - case 'text/html': - $output = $this->renderHtmlNotFoundOutput($request); - break; - - default: - throw new UnexpectedValueException('Cannot render unknown content type ' . $contentType); - } - } - - $body = new Body(fopen('php://temp', 'r+')); - $body->write($output); - - return $response->withStatus(404) - ->withHeader('Content-Type', $contentType) - ->withBody($body); - } - - /** - * Render plain not found message - * - * @return ResponseInterface - */ - protected function renderPlainNotFoundOutput() - { - return 'Not found'; - } - - /** - * Return a response for application/json content not found - * - * @return ResponseInterface - */ - protected function renderJsonNotFoundOutput() - { - return '{"message":"Not found"}'; - } - - /** - * Return a response for xml content not found - * - * @return ResponseInterface - */ - protected function renderXmlNotFoundOutput() - { - return 'Not found'; - } - - /** - * Return a response for text/html content not found - * - * @param ServerRequestInterface $request The most recent Request object - * - * @return ResponseInterface - */ - protected function renderHtmlNotFoundOutput(ServerRequestInterface $request) - { - $homeUrl = (string)($request->getUri()->withPath('')->withQuery('')->withFragment('')); - return << - - Page Not Found - - - -

Page Not Found

-

- The page you are looking for could not be found. Check the address bar - to ensure your URL is spelled correctly. If all else fails, you can - visit our home page at the link below. -

- Visit the Home Page - - -END; - } -} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Handlers/PhpError.php b/advancedcontentfilter/vendor/slim/slim/Slim/Handlers/PhpError.php deleted file mode 100644 index 3ecce30cf..000000000 --- a/advancedcontentfilter/vendor/slim/slim/Slim/Handlers/PhpError.php +++ /dev/null @@ -1,205 +0,0 @@ -determineContentType($request); - switch ($contentType) { - case 'application/json': - $output = $this->renderJsonErrorMessage($error); - break; - - case 'text/xml': - case 'application/xml': - $output = $this->renderXmlErrorMessage($error); - break; - - case 'text/html': - $output = $this->renderHtmlErrorMessage($error); - break; - default: - throw new UnexpectedValueException('Cannot render unknown content type ' . $contentType); - } - - $this->writeToErrorLog($error); - - $body = new Body(fopen('php://temp', 'r+')); - $body->write($output); - - return $response - ->withStatus(500) - ->withHeader('Content-type', $contentType) - ->withBody($body); - } - - /** - * Render HTML error page - * - * @param \Throwable $error - * - * @return string - */ - protected function renderHtmlErrorMessage(\Throwable $error) - { - $title = 'Slim Application Error'; - - if ($this->displayErrorDetails) { - $html = '

The application could not run because of the following error:

'; - $html .= '

Details

'; - $html .= $this->renderHtmlError($error); - - while ($error = $error->getPrevious()) { - $html .= '

Previous error

'; - $html .= $this->renderHtmlError($error); - } - } else { - $html = '

A website error has occurred. Sorry for the temporary inconvenience.

'; - } - - $output = sprintf( - "" . - "%s

%s

%s", - $title, - $title, - $html - ); - - return $output; - } - - /** - * Render error as HTML. - * - * @param \Throwable $error - * - * @return string - */ - protected function renderHtmlError(\Throwable $error) - { - $html = sprintf('
Type: %s
', get_class($error)); - - if (($code = $error->getCode())) { - $html .= sprintf('
Code: %s
', $code); - } - - if (($message = $error->getMessage())) { - $html .= sprintf('
Message: %s
', htmlentities($message)); - } - - if (($file = $error->getFile())) { - $html .= sprintf('
File: %s
', $file); - } - - if (($line = $error->getLine())) { - $html .= sprintf('
Line: %s
', $line); - } - - if (($trace = $error->getTraceAsString())) { - $html .= '

Trace

'; - $html .= sprintf('
%s
', htmlentities($trace)); - } - - return $html; - } - - /** - * Render JSON error - * - * @param \Throwable $error - * - * @return string - */ - protected function renderJsonErrorMessage(\Throwable $error) - { - $json = [ - 'message' => 'Slim Application Error', - ]; - - if ($this->displayErrorDetails) { - $json['error'] = []; - - do { - $json['error'][] = [ - 'type' => get_class($error), - 'code' => $error->getCode(), - 'message' => $error->getMessage(), - 'file' => $error->getFile(), - 'line' => $error->getLine(), - 'trace' => explode("\n", $error->getTraceAsString()), - ]; - } while ($error = $error->getPrevious()); - } - - return json_encode($json, JSON_PRETTY_PRINT); - } - - /** - * Render XML error - * - * @param \Throwable $error - * - * @return string - */ - protected function renderXmlErrorMessage(\Throwable $error) - { - $xml = "\n Slim Application Error\n"; - if ($this->displayErrorDetails) { - do { - $xml .= " \n"; - $xml .= " " . get_class($error) . "\n"; - $xml .= " " . $error->getCode() . "\n"; - $xml .= " " . $this->createCdataSection($error->getMessage()) . "\n"; - $xml .= " " . $error->getFile() . "\n"; - $xml .= " " . $error->getLine() . "\n"; - $xml .= " " . $this->createCdataSection($error->getTraceAsString()) . "\n"; - $xml .= " \n"; - } while ($error = $error->getPrevious()); - } - $xml .= ""; - - return $xml; - } - - /** - * Returns a CDATA section with the given content. - * - * @param string $content - * @return string - */ - private function createCdataSection($content) - { - return sprintf('', str_replace(']]>', ']]]]>', $content)); - } -} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Handlers/Strategies/RequestHandler.php b/advancedcontentfilter/vendor/slim/slim/Slim/Handlers/Strategies/RequestHandler.php new file mode 100644 index 000000000..ea88a5f12 --- /dev/null +++ b/advancedcontentfilter/vendor/slim/slim/Slim/Handlers/Strategies/RequestHandler.php @@ -0,0 +1,48 @@ +appendRouteArgumentsToRequestAttributes = $appendRouteArgumentsToRequestAttributes; + } + + /** + * Invoke a route callable that implements RequestHandlerInterface + * + * @param array $routeArguments + */ + public function __invoke( + callable $callable, + ServerRequestInterface $request, + ResponseInterface $response, + array $routeArguments + ): ResponseInterface { + if ($this->appendRouteArgumentsToRequestAttributes) { + foreach ($routeArguments as $k => $v) { + $request = $request->withAttribute($k, $v); + } + } + + return $callable($request); + } +} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponse.php b/advancedcontentfilter/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponse.php index ad99b56e8..45b2c05a4 100644 --- a/advancedcontentfilter/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponse.php +++ b/advancedcontentfilter/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponse.php @@ -1,11 +1,13 @@ $routeArguments */ public function __invoke( callable $callable, ServerRequestInterface $request, ResponseInterface $response, array $routeArguments - ) { + ): ResponseInterface { foreach ($routeArguments as $k => $v) { $request = $request->withAttribute($k, $v); } - return call_user_func($callable, $request, $response, $routeArguments); + return $callable($request, $response, $routeArguments); } } diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponseArgs.php b/advancedcontentfilter/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponseArgs.php index 739cc7ee8..c4ab16df5 100644 --- a/advancedcontentfilter/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponseArgs.php +++ b/advancedcontentfilter/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponseArgs.php @@ -1,42 +1,38 @@ $routeArguments */ public function __invoke( callable $callable, ServerRequestInterface $request, ResponseInterface $response, array $routeArguments - ) { - array_unshift($routeArguments, $request, $response); - - return call_user_func_array($callable, $routeArguments); + ): ResponseInterface { + return $callable($request, $response, ...array_values($routeArguments)); } } diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponseNamedArgs.php b/advancedcontentfilter/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponseNamedArgs.php new file mode 100644 index 000000000..651111dde --- /dev/null +++ b/advancedcontentfilter/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponseNamedArgs.php @@ -0,0 +1,44 @@ += 8.0.0'); + } + } + + /** + * Invoke a route callable with request, response and all route parameters + * as individual arguments. + * + * @param array $routeArguments + */ + public function __invoke( + callable $callable, + ServerRequestInterface $request, + ResponseInterface $response, + array $routeArguments + ): ResponseInterface { + return $callable($request, $response, ...$routeArguments); + } +} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Http/Body.php b/advancedcontentfilter/vendor/slim/slim/Slim/Http/Body.php deleted file mode 100644 index 7a7b4df81..000000000 --- a/advancedcontentfilter/vendor/slim/slim/Slim/Http/Body.php +++ /dev/null @@ -1,22 +0,0 @@ - '', - 'domain' => null, - 'hostonly' => null, - 'path' => null, - 'expires' => null, - 'secure' => false, - 'httponly' => false - ]; - - /** - * Create new cookies helper - * - * @param array $cookies - */ - public function __construct(array $cookies = []) - { - $this->requestCookies = $cookies; - } - - /** - * Set default cookie properties - * - * @param array $settings - */ - public function setDefaults(array $settings) - { - $this->defaults = array_replace($this->defaults, $settings); - } - - /** - * Get request cookie - * - * @param string $name Cookie name - * @param mixed $default Cookie default value - * - * @return mixed Cookie value if present, else default - */ - public function get($name, $default = null) - { - return isset($this->requestCookies[$name]) ? $this->requestCookies[$name] : $default; - } - - /** - * Set response cookie - * - * @param string $name Cookie name - * @param string|array $value Cookie value, or cookie properties - */ - public function set($name, $value) - { - if (!is_array($value)) { - $value = ['value' => (string)$value]; - } - $this->responseCookies[$name] = array_replace($this->defaults, $value); - } - - /** - * Convert to `Set-Cookie` headers - * - * @return string[] - */ - public function toHeaders() - { - $headers = []; - foreach ($this->responseCookies as $name => $properties) { - $headers[] = $this->toHeader($name, $properties); - } - - return $headers; - } - - /** - * Convert to `Set-Cookie` header - * - * @param string $name Cookie name - * @param array $properties Cookie properties - * - * @return string - */ - protected function toHeader($name, array $properties) - { - $result = urlencode($name) . '=' . urlencode($properties['value']); - - if (isset($properties['domain'])) { - $result .= '; domain=' . $properties['domain']; - } - - if (isset($properties['path'])) { - $result .= '; path=' . $properties['path']; - } - - if (isset($properties['expires'])) { - if (is_string($properties['expires'])) { - $timestamp = strtotime($properties['expires']); - } else { - $timestamp = (int)$properties['expires']; - } - if ($timestamp !== 0) { - $result .= '; expires=' . gmdate('D, d-M-Y H:i:s e', $timestamp); - } - } - - if (isset($properties['secure']) && $properties['secure']) { - $result .= '; secure'; - } - - if (isset($properties['hostonly']) && $properties['hostonly']) { - $result .= '; HostOnly'; - } - - if (isset($properties['httponly']) && $properties['httponly']) { - $result .= '; HttpOnly'; - } - - return $result; - } - - /** - * Parse HTTP request `Cookie:` header and extract - * into a PHP associative array. - * - * @param string $header The raw HTTP request `Cookie:` header - * - * @return array Associative array of cookie names and values - * - * @throws InvalidArgumentException if the cookie data cannot be parsed - */ - public static function parseHeader($header) - { - if (is_array($header) === true) { - $header = isset($header[0]) ? $header[0] : ''; - } - - if (is_string($header) === false) { - throw new InvalidArgumentException('Cannot parse Cookie data. Header value must be a string.'); - } - - $header = rtrim($header, "\r\n"); - $pieces = preg_split('@[;]\s*@', $header); - $cookies = []; - - foreach ($pieces as $cookie) { - $cookie = explode('=', $cookie, 2); - - if (count($cookie) === 2) { - $key = urldecode($cookie[0]); - $value = urldecode($cookie[1]); - - if (!isset($cookies[$key])) { - $cookies[$key] = $value; - } - } - } - - return $cookies; - } -} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Http/Environment.php b/advancedcontentfilter/vendor/slim/slim/Slim/Http/Environment.php deleted file mode 100644 index cd452fcff..000000000 --- a/advancedcontentfilter/vendor/slim/slim/Slim/Http/Environment.php +++ /dev/null @@ -1,63 +0,0 @@ - 'HTTP/1.1', - 'REQUEST_METHOD' => 'GET', - 'REQUEST_SCHEME' => $defscheme, - 'SCRIPT_NAME' => '', - 'REQUEST_URI' => '', - 'QUERY_STRING' => '', - 'SERVER_NAME' => 'localhost', - 'SERVER_PORT' => $defport, - 'HTTP_HOST' => 'localhost', - 'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', - 'HTTP_ACCEPT_LANGUAGE' => 'en-US,en;q=0.8', - 'HTTP_ACCEPT_CHARSET' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.3', - 'HTTP_USER_AGENT' => 'Slim Framework', - 'REMOTE_ADDR' => '127.0.0.1', - 'REQUEST_TIME' => time(), - 'REQUEST_TIME_FLOAT' => microtime(true), - ], $userData); - - return new static($data); - } -} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Http/Headers.php b/advancedcontentfilter/vendor/slim/slim/Slim/Http/Headers.php deleted file mode 100644 index ef50f84b6..000000000 --- a/advancedcontentfilter/vendor/slim/slim/Slim/Http/Headers.php +++ /dev/null @@ -1,222 +0,0 @@ - 1, - 'CONTENT_LENGTH' => 1, - 'PHP_AUTH_USER' => 1, - 'PHP_AUTH_PW' => 1, - 'PHP_AUTH_DIGEST' => 1, - 'AUTH_TYPE' => 1, - ]; - - /** - * Create new headers collection with data extracted from - * the application Environment object - * - * @param Environment $environment The Slim application Environment - * - * @return self - */ - public static function createFromEnvironment(Environment $environment) - { - $data = []; - $environment = self::determineAuthorization($environment); - foreach ($environment as $key => $value) { - $key = strtoupper($key); - if (isset(static::$special[$key]) || strpos($key, 'HTTP_') === 0) { - if ($key !== 'HTTP_CONTENT_LENGTH') { - $data[$key] = $value; - } - } - } - - return new static($data); - } - - /** - * If HTTP_AUTHORIZATION does not exist tries to get it from - * getallheaders() when available. - * - * @param Environment $environment The Slim application Environment - * - * @return Environment - */ - - public static function determineAuthorization(Environment $environment) - { - $authorization = $environment->get('HTTP_AUTHORIZATION'); - - if (empty($authorization) && is_callable('getallheaders')) { - $headers = getallheaders(); - $headers = array_change_key_case($headers, CASE_LOWER); - if (isset($headers['authorization'])) { - $environment->set('HTTP_AUTHORIZATION', $headers['authorization']); - } - } - - return $environment; - } - - /** - * Return array of HTTP header names and values. - * This method returns the _original_ header name - * as specified by the end user. - * - * @return array - */ - public function all() - { - $all = parent::all(); - $out = []; - foreach ($all as $key => $props) { - $out[$props['originalKey']] = $props['value']; - } - - return $out; - } - - /** - * Set HTTP header value - * - * This method sets a header value. It replaces - * any values that may already exist for the header name. - * - * @param string $key The case-insensitive header name - * @param string $value The header value - */ - public function set($key, $value) - { - if (!is_array($value)) { - $value = [$value]; - } - parent::set($this->normalizeKey($key), [ - 'value' => $value, - 'originalKey' => $key - ]); - } - - /** - * Get HTTP header value - * - * @param string $key The case-insensitive header name - * @param mixed $default The default value if key does not exist - * - * @return string[] - */ - public function get($key, $default = null) - { - if ($this->has($key)) { - return parent::get($this->normalizeKey($key))['value']; - } - - return $default; - } - - /** - * Get HTTP header key as originally specified - * - * @param string $key The case-insensitive header name - * @param mixed $default The default value if key does not exist - * - * @return string - */ - public function getOriginalKey($key, $default = null) - { - if ($this->has($key)) { - return parent::get($this->normalizeKey($key))['originalKey']; - } - - return $default; - } - - /** - * Add HTTP header value - * - * This method appends a header value. Unlike the set() method, - * this method _appends_ this new value to any values - * that already exist for this header name. - * - * @param string $key The case-insensitive header name - * @param array|string $value The new header value(s) - */ - public function add($key, $value) - { - $oldValues = $this->get($key, []); - $newValues = is_array($value) ? $value : [$value]; - $this->set($key, array_merge($oldValues, array_values($newValues))); - } - - /** - * Does this collection have a given header? - * - * @param string $key The case-insensitive header name - * - * @return bool - */ - public function has($key) - { - return parent::has($this->normalizeKey($key)); - } - - /** - * Remove header from collection - * - * @param string $key The case-insensitive header name - */ - public function remove($key) - { - parent::remove($this->normalizeKey($key)); - } - - /** - * Normalize header name - * - * This method transforms header names into a - * normalized form. This is how we enable case-insensitive - * header names in the other methods in this class. - * - * @param string $key The case-insensitive header name - * - * @return string Normalized header name - */ - public function normalizeKey($key) - { - $key = strtr(strtolower($key), '_', '-'); - if (strpos($key, 'http-') === 0) { - $key = substr($key, 5); - } - - return $key; - } -} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Http/Message.php b/advancedcontentfilter/vendor/slim/slim/Slim/Http/Message.php deleted file mode 100644 index 9195fb5b7..000000000 --- a/advancedcontentfilter/vendor/slim/slim/Slim/Http/Message.php +++ /dev/null @@ -1,305 +0,0 @@ - true, - '1.1' => true, - '2.0' => true, - '2' => true, - ]; - - /** - * Headers - * - * @var \Slim\Interfaces\Http\HeadersInterface - */ - protected $headers; - - /** - * Body object - * - * @var \Psr\Http\Message\StreamInterface - */ - protected $body; - - - /** - * Disable magic setter to ensure immutability - */ - public function __set($name, $value) - { - // Do nothing - } - - /******************************************************************************* - * Protocol - ******************************************************************************/ - - /** - * Retrieves the HTTP protocol version as a string. - * - * The string MUST contain only the HTTP version number (e.g., "1.1", "1.0"). - * - * @return string HTTP protocol version. - */ - public function getProtocolVersion() - { - return $this->protocolVersion; - } - - /** - * Return an instance with the specified HTTP protocol version. - * - * The version string MUST contain only the HTTP version number (e.g., - * "1.1", "1.0"). - * - * This method MUST be implemented in such a way as to retain the - * immutability of the message, and MUST return an instance that has the - * new protocol version. - * - * @param string $version HTTP protocol version - * @return static - * @throws InvalidArgumentException if the http version is an invalid number - */ - public function withProtocolVersion($version) - { - if (!isset(self::$validProtocolVersions[$version])) { - throw new InvalidArgumentException( - 'Invalid HTTP version. Must be one of: ' - . implode(', ', array_keys(self::$validProtocolVersions)) - ); - } - $clone = clone $this; - $clone->protocolVersion = $version; - - return $clone; - } - - /******************************************************************************* - * Headers - ******************************************************************************/ - - /** - * Retrieves all message header values. - * - * The keys represent the header name as it will be sent over the wire, and - * each value is an array of strings associated with the header. - * - * // Represent the headers as a string - * foreach ($message->getHeaders() as $name => $values) { - * echo $name . ": " . implode(", ", $values); - * } - * - * // Emit headers iteratively: - * foreach ($message->getHeaders() as $name => $values) { - * foreach ($values as $value) { - * header(sprintf('%s: %s', $name, $value), false); - * } - * } - * - * While header names are not case-sensitive, getHeaders() will preserve the - * exact case in which headers were originally specified. - * - * @return array Returns an associative array of the message's headers. Each - * key MUST be a header name, and each value MUST be an array of strings - * for that header. - */ - public function getHeaders() - { - return $this->headers->all(); - } - - /** - * Checks if a header exists by the given case-insensitive name. - * - * @param string $name Case-insensitive header field name. - * @return bool Returns true if any header names match the given header - * name using a case-insensitive string comparison. Returns false if - * no matching header name is found in the message. - */ - public function hasHeader($name) - { - return $this->headers->has($name); - } - - /** - * Retrieves a message header value by the given case-insensitive name. - * - * This method returns an array of all the header values of the given - * case-insensitive header name. - * - * If the header does not appear in the message, this method MUST return an - * empty array. - * - * @param string $name Case-insensitive header field name. - * @return string[] An array of string values as provided for the given - * header. If the header does not appear in the message, this method MUST - * return an empty array. - */ - public function getHeader($name) - { - return $this->headers->get($name, []); - } - - /** - * Retrieves a comma-separated string of the values for a single header. - * - * This method returns all of the header values of the given - * case-insensitive header name as a string concatenated together using - * a comma. - * - * NOTE: Not all header values may be appropriately represented using - * comma concatenation. For such headers, use getHeader() instead - * and supply your own delimiter when concatenating. - * - * If the header does not appear in the message, this method MUST return - * an empty string. - * - * @param string $name Case-insensitive header field name. - * @return string A string of values as provided for the given header - * concatenated together using a comma. If the header does not appear in - * the message, this method MUST return an empty string. - */ - public function getHeaderLine($name) - { - return implode(',', $this->headers->get($name, [])); - } - - /** - * Return an instance with the provided value replacing the specified header. - * - * While header names are case-insensitive, the casing of the header will - * be preserved by this function, and returned from getHeaders(). - * - * This method MUST be implemented in such a way as to retain the - * immutability of the message, and MUST return an instance that has the - * new and/or updated header and value. - * - * @param string $name Case-insensitive header field name. - * @param string|string[] $value Header value(s). - * @return static - * @throws \InvalidArgumentException for invalid header names or values. - */ - public function withHeader($name, $value) - { - $clone = clone $this; - $clone->headers->set($name, $value); - - return $clone; - } - - /** - * Return an instance with the specified header appended with the given value. - * - * Existing values for the specified header will be maintained. The new - * value(s) will be appended to the existing list. If the header did not - * exist previously, it will be added. - * - * This method MUST be implemented in such a way as to retain the - * immutability of the message, and MUST return an instance that has the - * new header and/or value. - * - * @param string $name Case-insensitive header field name to add. - * @param string|string[] $value Header value(s). - * @return static - * @throws \InvalidArgumentException for invalid header names or values. - */ - public function withAddedHeader($name, $value) - { - $clone = clone $this; - $clone->headers->add($name, $value); - - return $clone; - } - - /** - * Return an instance without the specified header. - * - * Header resolution MUST be done without case-sensitivity. - * - * This method MUST be implemented in such a way as to retain the - * immutability of the message, and MUST return an instance that removes - * the named header. - * - * @param string $name Case-insensitive header field name to remove. - * @return static - */ - public function withoutHeader($name) - { - $clone = clone $this; - $clone->headers->remove($name); - - return $clone; - } - - /******************************************************************************* - * Body - ******************************************************************************/ - - /** - * Gets the body of the message. - * - * @return StreamInterface Returns the body as a stream. - */ - public function getBody() - { - return $this->body; - } - - /** - * Return an instance with the specified message body. - * - * The body MUST be a StreamInterface object. - * - * This method MUST be implemented in such a way as to retain the - * immutability of the message, and MUST return a new instance that has the - * new body stream. - * - * @param StreamInterface $body Body. - * @return static - * @throws \InvalidArgumentException When the body is not valid. - */ - public function withBody(StreamInterface $body) - { - // TODO: Test for invalid body? - $clone = clone $this; - $clone->body = $body; - - return $clone; - } -} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Http/Request.php b/advancedcontentfilter/vendor/slim/slim/Slim/Http/Request.php deleted file mode 100644 index 4bea07e9e..000000000 --- a/advancedcontentfilter/vendor/slim/slim/Slim/Http/Request.php +++ /dev/null @@ -1,1227 +0,0 @@ - 1, - 'DELETE' => 1, - 'GET' => 1, - 'HEAD' => 1, - 'OPTIONS' => 1, - 'PATCH' => 1, - 'POST' => 1, - 'PUT' => 1, - 'TRACE' => 1, - ]; - - /** - * Create new HTTP request with data extracted from the application - * Environment object - * - * @param Environment $environment The Slim application Environment - * - * @return static - */ - public static function createFromEnvironment(Environment $environment) - { - $method = $environment['REQUEST_METHOD']; - $uri = Uri::createFromEnvironment($environment); - $headers = Headers::createFromEnvironment($environment); - $cookies = Cookies::parseHeader($headers->get('Cookie', [])); - $serverParams = $environment->all(); - $body = new RequestBody(); - $uploadedFiles = UploadedFile::createFromEnvironment($environment); - - $request = new static($method, $uri, $headers, $cookies, $serverParams, $body, $uploadedFiles); - - if ($method === 'POST' && - in_array($request->getMediaType(), ['application/x-www-form-urlencoded', 'multipart/form-data']) - ) { - // parsed body must be $_POST - $request = $request->withParsedBody($_POST); - } - return $request; - } - - /** - * Create new HTTP request. - * - * Adds a host header when none was provided and a host is defined in uri. - * - * @param string $method The request method - * @param UriInterface $uri The request URI object - * @param HeadersInterface $headers The request headers collection - * @param array $cookies The request cookies collection - * @param array $serverParams The server environment variables - * @param StreamInterface $body The request body object - * @param array $uploadedFiles The request uploadedFiles collection - * @throws InvalidMethodException on invalid HTTP method - */ - public function __construct( - $method, - UriInterface $uri, - HeadersInterface $headers, - array $cookies, - array $serverParams, - StreamInterface $body, - array $uploadedFiles = [] - ) { - try { - $this->originalMethod = $this->filterMethod($method); - } catch (InvalidMethodException $e) { - $this->originalMethod = $method; - } - - $this->uri = $uri; - $this->headers = $headers; - $this->cookies = $cookies; - $this->serverParams = $serverParams; - $this->attributes = new Collection(); - $this->body = $body; - $this->uploadedFiles = $uploadedFiles; - - if (isset($serverParams['SERVER_PROTOCOL'])) { - $this->protocolVersion = str_replace('HTTP/', '', $serverParams['SERVER_PROTOCOL']); - } - - if (!$this->headers->has('Host') || $this->uri->getHost() !== '') { - $this->headers->set('Host', $this->uri->getHost()); - } - - $this->registerMediaTypeParser('application/json', function ($input) { - $result = json_decode($input, true); - if (!is_array($result)) { - return null; - } - return $result; - }); - - $this->registerMediaTypeParser('application/xml', function ($input) { - $backup = libxml_disable_entity_loader(true); - $backup_errors = libxml_use_internal_errors(true); - $result = simplexml_load_string($input); - libxml_disable_entity_loader($backup); - libxml_clear_errors(); - libxml_use_internal_errors($backup_errors); - if ($result === false) { - return null; - } - return $result; - }); - - $this->registerMediaTypeParser('text/xml', function ($input) { - $backup = libxml_disable_entity_loader(true); - $backup_errors = libxml_use_internal_errors(true); - $result = simplexml_load_string($input); - libxml_disable_entity_loader($backup); - libxml_clear_errors(); - libxml_use_internal_errors($backup_errors); - if ($result === false) { - return null; - } - return $result; - }); - - $this->registerMediaTypeParser('application/x-www-form-urlencoded', function ($input) { - parse_str($input, $data); - return $data; - }); - - // if the request had an invalid method, we can throw it now - if (isset($e) && $e instanceof InvalidMethodException) { - throw $e; - } - } - - /** - * This method is applied to the cloned object - * after PHP performs an initial shallow-copy. This - * method completes a deep-copy by creating new objects - * for the cloned object's internal reference pointers. - */ - public function __clone() - { - $this->headers = clone $this->headers; - $this->attributes = clone $this->attributes; - $this->body = clone $this->body; - } - - /******************************************************************************* - * Method - ******************************************************************************/ - - /** - * Retrieves the HTTP method of the request. - * - * @return string Returns the request method. - */ - public function getMethod() - { - if ($this->method === null) { - $this->method = $this->originalMethod; - $customMethod = $this->getHeaderLine('X-Http-Method-Override'); - - if ($customMethod) { - $this->method = $this->filterMethod($customMethod); - } elseif ($this->originalMethod === 'POST') { - $overrideMethod = $this->filterMethod($this->getParsedBodyParam('_METHOD')); - if ($overrideMethod !== null) { - $this->method = $overrideMethod; - } - - if ($this->getBody()->eof()) { - $this->getBody()->rewind(); - } - } - } - - return $this->method; - } - - /** - * Get the original HTTP method (ignore override). - * - * Note: This method is not part of the PSR-7 standard. - * - * @return string - */ - public function getOriginalMethod() - { - return $this->originalMethod; - } - - /** - * Return an instance with the provided HTTP method. - * - * While HTTP method names are typically all uppercase characters, HTTP - * method names are case-sensitive and thus implementations SHOULD NOT - * modify the given string. - * - * This method MUST be implemented in such a way as to retain the - * immutability of the message, and MUST return an instance that has the - * changed request method. - * - * @param string $method Case-sensitive method. - * @return static - * @throws \InvalidArgumentException for invalid HTTP methods. - */ - public function withMethod($method) - { - $method = $this->filterMethod($method); - $clone = clone $this; - $clone->originalMethod = $method; - $clone->method = $method; - - return $clone; - } - - /** - * Validate the HTTP method - * - * @param null|string $method - * @return null|string - * @throws \InvalidArgumentException on invalid HTTP method. - */ - protected function filterMethod($method) - { - if ($method === null) { - return $method; - } - - if (!is_string($method)) { - throw new InvalidArgumentException(sprintf( - 'Unsupported HTTP method; must be a string, received %s', - (is_object($method) ? get_class($method) : gettype($method)) - )); - } - - $method = strtoupper($method); - if (preg_match("/^[!#$%&'*+.^_`|~0-9a-z-]+$/i", $method) !== 1) { - throw new InvalidMethodException($this, $method); - } - - return $method; - } - - /** - * Does this request use a given method? - * - * Note: This method is not part of the PSR-7 standard. - * - * @param string $method HTTP method - * @return bool - */ - public function isMethod($method) - { - return $this->getMethod() === $method; - } - - /** - * Is this a GET request? - * - * Note: This method is not part of the PSR-7 standard. - * - * @return bool - */ - public function isGet() - { - return $this->isMethod('GET'); - } - - /** - * Is this a POST request? - * - * Note: This method is not part of the PSR-7 standard. - * - * @return bool - */ - public function isPost() - { - return $this->isMethod('POST'); - } - - /** - * Is this a PUT request? - * - * Note: This method is not part of the PSR-7 standard. - * - * @return bool - */ - public function isPut() - { - return $this->isMethod('PUT'); - } - - /** - * Is this a PATCH request? - * - * Note: This method is not part of the PSR-7 standard. - * - * @return bool - */ - public function isPatch() - { - return $this->isMethod('PATCH'); - } - - /** - * Is this a DELETE request? - * - * Note: This method is not part of the PSR-7 standard. - * - * @return bool - */ - public function isDelete() - { - return $this->isMethod('DELETE'); - } - - /** - * Is this a HEAD request? - * - * Note: This method is not part of the PSR-7 standard. - * - * @return bool - */ - public function isHead() - { - return $this->isMethod('HEAD'); - } - - /** - * Is this a OPTIONS request? - * - * Note: This method is not part of the PSR-7 standard. - * - * @return bool - */ - public function isOptions() - { - return $this->isMethod('OPTIONS'); - } - - /** - * Is this an XHR request? - * - * Note: This method is not part of the PSR-7 standard. - * - * @return bool - */ - public function isXhr() - { - return $this->getHeaderLine('X-Requested-With') === 'XMLHttpRequest'; - } - - /******************************************************************************* - * URI - ******************************************************************************/ - - /** - * Retrieves the message's request target. - * - * Retrieves the message's request-target either as it will appear (for - * clients), as it appeared at request (for servers), or as it was - * specified for the instance (see withRequestTarget()). - * - * In most cases, this will be the origin-form of the composed URI, - * unless a value was provided to the concrete implementation (see - * withRequestTarget() below). - * - * If no URI is available, and no request-target has been specifically - * provided, this method MUST return the string "/". - * - * @return string - */ - public function getRequestTarget() - { - if ($this->requestTarget) { - return $this->requestTarget; - } - - if ($this->uri === null) { - return '/'; - } - - $basePath = $this->uri->getBasePath(); - $path = $this->uri->getPath(); - $path = $basePath . '/' . ltrim($path, '/'); - - $query = $this->uri->getQuery(); - if ($query) { - $path .= '?' . $query; - } - $this->requestTarget = $path; - - return $this->requestTarget; - } - - /** - * Return an instance with the specific request-target. - * - * If the request needs a non-origin-form request-target — e.g., for - * specifying an absolute-form, authority-form, or asterisk-form — - * this method may be used to create an instance with the specified - * request-target, verbatim. - * - * This method MUST be implemented in such a way as to retain the - * immutability of the message, and MUST return an instance that has the - * changed request target. - * - * @link http://tools.ietf.org/html/rfc7230#section-2.7 (for the various - * request-target forms allowed in request messages) - * @param mixed $requestTarget - * @return static - * @throws InvalidArgumentException if the request target is invalid - */ - public function withRequestTarget($requestTarget) - { - if (preg_match('#\s#', $requestTarget)) { - throw new InvalidArgumentException( - 'Invalid request target provided; must be a string and cannot contain whitespace' - ); - } - $clone = clone $this; - $clone->requestTarget = $requestTarget; - - return $clone; - } - - /** - * Retrieves the URI instance. - * - * This method MUST return a UriInterface instance. - * - * @link http://tools.ietf.org/html/rfc3986#section-4.3 - * @return UriInterface Returns a UriInterface instance - * representing the URI of the request. - */ - public function getUri() - { - return $this->uri; - } - - /** - * Returns an instance with the provided URI. - * - * This method MUST update the Host header of the returned request by - * default if the URI contains a host component. If the URI does not - * contain a host component, any pre-existing Host header MUST be carried - * over to the returned request. - * - * You can opt-in to preserving the original state of the Host header by - * setting `$preserveHost` to `true`. When `$preserveHost` is set to - * `true`, this method interacts with the Host header in the following ways: - * - * - If the the Host header is missing or empty, and the new URI contains - * a host component, this method MUST update the Host header in the returned - * request. - * - If the Host header is missing or empty, and the new URI does not contain a - * host component, this method MUST NOT update the Host header in the returned - * request. - * - If a Host header is present and non-empty, this method MUST NOT update - * the Host header in the returned request. - * - * This method MUST be implemented in such a way as to retain the - * immutability of the message, and MUST return an instance that has the - * new UriInterface instance. - * - * @link http://tools.ietf.org/html/rfc3986#section-4.3 - * @param UriInterface $uri New request URI to use. - * @param bool $preserveHost Preserve the original state of the Host header. - * @return static - */ - public function withUri(UriInterface $uri, $preserveHost = false) - { - $clone = clone $this; - $clone->uri = $uri; - - if (!$preserveHost) { - if ($uri->getHost() !== '') { - $clone->headers->set('Host', $uri->getHost()); - } - } else { - if ($uri->getHost() !== '' && (!$this->hasHeader('Host') || $this->getHeaderLine('Host') === '')) { - $clone->headers->set('Host', $uri->getHost()); - } - } - - return $clone; - } - - /** - * Get request content type. - * - * Note: This method is not part of the PSR-7 standard. - * - * @return string|null The request content type, if known - */ - public function getContentType() - { - $result = $this->getHeader('Content-Type'); - - return $result ? $result[0] : null; - } - - /** - * Get request media type, if known. - * - * Note: This method is not part of the PSR-7 standard. - * - * @return string|null The request media type, minus content-type params - */ - public function getMediaType() - { - $contentType = $this->getContentType(); - if ($contentType) { - $contentTypeParts = preg_split('/\s*[;,]\s*/', $contentType); - - return strtolower($contentTypeParts[0]); - } - - return null; - } - - /** - * Get request media type params, if known. - * - * Note: This method is not part of the PSR-7 standard. - * - * @return array - */ - public function getMediaTypeParams() - { - $contentType = $this->getContentType(); - $contentTypeParams = []; - if ($contentType) { - $contentTypeParts = preg_split('/\s*[;,]\s*/', $contentType); - $contentTypePartsLength = count($contentTypeParts); - for ($i = 1; $i < $contentTypePartsLength; $i++) { - $paramParts = explode('=', $contentTypeParts[$i]); - $contentTypeParams[strtolower($paramParts[0])] = $paramParts[1]; - } - } - - return $contentTypeParams; - } - - /** - * Get request content character set, if known. - * - * Note: This method is not part of the PSR-7 standard. - * - * @return string|null - */ - public function getContentCharset() - { - $mediaTypeParams = $this->getMediaTypeParams(); - if (isset($mediaTypeParams['charset'])) { - return $mediaTypeParams['charset']; - } - - return null; - } - - /** - * Get request content length, if known. - * - * Note: This method is not part of the PSR-7 standard. - * - * @return int|null - */ - public function getContentLength() - { - $result = $this->headers->get('Content-Length'); - - return $result ? (int)$result[0] : null; - } - - /******************************************************************************* - * Cookies - ******************************************************************************/ - - /** - * Retrieve cookies. - * - * Retrieves cookies sent by the client to the server. - * - * The data MUST be compatible with the structure of the $_COOKIE - * superglobal. - * - * @return array - */ - public function getCookieParams() - { - return $this->cookies; - } - - /** - * Fetch cookie value from cookies sent by the client to the server. - * - * Note: This method is not part of the PSR-7 standard. - * - * @param string $key The attribute name. - * @param mixed $default Default value to return if the attribute does not exist. - * - * @return mixed - */ - public function getCookieParam($key, $default = null) - { - $cookies = $this->getCookieParams(); - $result = $default; - if (isset($cookies[$key])) { - $result = $cookies[$key]; - } - - return $result; - } - - /** - * Return an instance with the specified cookies. - * - * The data IS NOT REQUIRED to come from the $_COOKIE superglobal, but MUST - * be compatible with the structure of $_COOKIE. Typically, this data will - * be injected at instantiation. - * - * This method MUST NOT update the related Cookie header of the request - * instance, nor related values in the server params. - * - * This method MUST be implemented in such a way as to retain the - * immutability of the message, and MUST return an instance that has the - * updated cookie values. - * - * @param array $cookies Array of key/value pairs representing cookies. - * @return static - */ - public function withCookieParams(array $cookies) - { - $clone = clone $this; - $clone->cookies = $cookies; - - return $clone; - } - - /******************************************************************************* - * Query Params - ******************************************************************************/ - - /** - * Retrieve query string arguments. - * - * Retrieves the deserialized query string arguments, if any. - * - * Note: the query params might not be in sync with the URI or server - * params. If you need to ensure you are only getting the original - * values, you may need to parse the query string from `getUri()->getQuery()` - * or from the `QUERY_STRING` server param. - * - * @return array - */ - public function getQueryParams() - { - if (is_array($this->queryParams)) { - return $this->queryParams; - } - - if ($this->uri === null) { - return []; - } - - parse_str($this->uri->getQuery(), $this->queryParams); // <-- URL decodes data - - return $this->queryParams; - } - - /** - * Return an instance with the specified query string arguments. - * - * These values SHOULD remain immutable over the course of the incoming - * request. They MAY be injected during instantiation, such as from PHP's - * $_GET superglobal, or MAY be derived from some other value such as the - * URI. In cases where the arguments are parsed from the URI, the data - * MUST be compatible with what PHP's parse_str() would return for - * purposes of how duplicate query parameters are handled, and how nested - * sets are handled. - * - * Setting query string arguments MUST NOT change the URI stored by the - * request, nor the values in the server params. - * - * This method MUST be implemented in such a way as to retain the - * immutability of the message, and MUST return an instance that has the - * updated query string arguments. - * - * @param array $query Array of query string arguments, typically from - * $_GET. - * @return static - */ - public function withQueryParams(array $query) - { - $clone = clone $this; - $clone->queryParams = $query; - - return $clone; - } - - /******************************************************************************* - * File Params - ******************************************************************************/ - - /** - * Retrieve normalized file upload data. - * - * This method returns upload metadata in a normalized tree, with each leaf - * an instance of Psr\Http\Message\UploadedFileInterface. - * - * These values MAY be prepared from $_FILES or the message body during - * instantiation, or MAY be injected via withUploadedFiles(). - * - * @return array An array tree of UploadedFileInterface instances; an empty - * array MUST be returned if no data is present. - */ - public function getUploadedFiles() - { - return $this->uploadedFiles; - } - - /** - * Create a new instance with the specified uploaded files. - * - * This method MUST be implemented in such a way as to retain the - * immutability of the message, and MUST return an instance that has the - * updated body parameters. - * - * @param array $uploadedFiles An array tree of UploadedFileInterface instances. - * @return static - * @throws \InvalidArgumentException if an invalid structure is provided. - */ - public function withUploadedFiles(array $uploadedFiles) - { - $clone = clone $this; - $clone->uploadedFiles = $uploadedFiles; - - return $clone; - } - - /******************************************************************************* - * Server Params - ******************************************************************************/ - - /** - * Retrieve server parameters. - * - * Retrieves data related to the incoming request environment, - * typically derived from PHP's $_SERVER superglobal. The data IS NOT - * REQUIRED to originate from $_SERVER. - * - * @return array - */ - public function getServerParams() - { - return $this->serverParams; - } - - /** - * Retrieve a server parameter. - * - * Note: This method is not part of the PSR-7 standard. - * - * @param string $key - * @param mixed $default - * @return mixed - */ - public function getServerParam($key, $default = null) - { - $serverParams = $this->getServerParams(); - - return isset($serverParams[$key]) ? $serverParams[$key] : $default; - } - - /******************************************************************************* - * Attributes - ******************************************************************************/ - - /** - * Retrieve attributes derived from the request. - * - * The request "attributes" may be used to allow injection of any - * parameters derived from the request: e.g., the results of path - * match operations; the results of decrypting cookies; the results of - * deserializing non-form-encoded message bodies; etc. Attributes - * will be application and request specific, and CAN be mutable. - * - * @return array Attributes derived from the request. - */ - public function getAttributes() - { - return $this->attributes->all(); - } - - /** - * Retrieve a single derived request attribute. - * - * Retrieves a single derived request attribute as described in - * getAttributes(). If the attribute has not been previously set, returns - * the default value as provided. - * - * This method obviates the need for a hasAttribute() method, as it allows - * specifying a default value to return if the attribute is not found. - * - * @see getAttributes() - * @param string $name The attribute name. - * @param mixed $default Default value to return if the attribute does not exist. - * @return mixed - */ - public function getAttribute($name, $default = null) - { - return $this->attributes->get($name, $default); - } - - /** - * Return an instance with the specified derived request attribute. - * - * This method allows setting a single derived request attribute as - * described in getAttributes(). - * - * This method MUST be implemented in such a way as to retain the - * immutability of the message, and MUST return an instance that has the - * updated attribute. - * - * @see getAttributes() - * @param string $name The attribute name. - * @param mixed $value The value of the attribute. - * @return static - */ - public function withAttribute($name, $value) - { - $clone = clone $this; - $clone->attributes->set($name, $value); - - return $clone; - } - - /** - * Create a new instance with the specified derived request attributes. - * - * Note: This method is not part of the PSR-7 standard. - * - * This method allows setting all new derived request attributes as - * described in getAttributes(). - * - * This method MUST be implemented in such a way as to retain the - * immutability of the message, and MUST return a new instance that has the - * updated attributes. - * - * @param array $attributes New attributes - * @return static - */ - public function withAttributes(array $attributes) - { - $clone = clone $this; - $clone->attributes = new Collection($attributes); - - return $clone; - } - - /** - * Return an instance that removes the specified derived request attribute. - * - * This method allows removing a single derived request attribute as - * described in getAttributes(). - * - * This method MUST be implemented in such a way as to retain the - * immutability of the message, and MUST return an instance that removes - * the attribute. - * - * @see getAttributes() - * @param string $name The attribute name. - * @return static - */ - public function withoutAttribute($name) - { - $clone = clone $this; - $clone->attributes->remove($name); - - return $clone; - } - - /******************************************************************************* - * Body - ******************************************************************************/ - - /** - * Retrieve any parameters provided in the request body. - * - * If the request Content-Type is either application/x-www-form-urlencoded - * or multipart/form-data, and the request method is POST, this method MUST - * return the contents of $_POST. - * - * Otherwise, this method may return any results of deserializing - * the request body content; as parsing returns structured content, the - * potential types MUST be arrays or objects only. A null value indicates - * the absence of body content. - * - * @return null|array|object The deserialized body parameters, if any. - * These will typically be an array or object. - * @throws RuntimeException if the request body media type parser returns an invalid value - */ - public function getParsedBody() - { - if ($this->bodyParsed !== false) { - return $this->bodyParsed; - } - - if (!$this->body) { - return null; - } - - $mediaType = $this->getMediaType(); - - // look for a media type with a structured syntax suffix (RFC 6839) - $parts = explode('+', $mediaType); - if (count($parts) >= 2) { - $mediaType = 'application/' . $parts[count($parts)-1]; - } - - if (isset($this->bodyParsers[$mediaType]) === true) { - $body = (string)$this->getBody(); - $parsed = $this->bodyParsers[$mediaType]($body); - - if (!is_null($parsed) && !is_object($parsed) && !is_array($parsed)) { - throw new RuntimeException( - 'Request body media type parser return value must be an array, an object, or null' - ); - } - $this->bodyParsed = $parsed; - return $this->bodyParsed; - } - - return null; - } - - /** - * Return an instance with the specified body parameters. - * - * These MAY be injected during instantiation. - * - * If the request Content-Type is either application/x-www-form-urlencoded - * or multipart/form-data, and the request method is POST, use this method - * ONLY to inject the contents of $_POST. - * - * The data IS NOT REQUIRED to come from $_POST, but MUST be the results of - * deserializing the request body content. Deserialization/parsing returns - * structured data, and, as such, this method ONLY accepts arrays or objects, - * or a null value if nothing was available to parse. - * - * As an example, if content negotiation determines that the request data - * is a JSON payload, this method could be used to create a request - * instance with the deserialized parameters. - * - * This method MUST be implemented in such a way as to retain the - * immutability of the message, and MUST return an instance that has the - * updated body parameters. - * - * @param null|array|object $data The deserialized body data. This will - * typically be in an array or object. - * @return static - * @throws \InvalidArgumentException if an unsupported argument type is - * provided. - */ - public function withParsedBody($data) - { - if (!is_null($data) && !is_object($data) && !is_array($data)) { - throw new InvalidArgumentException('Parsed body value must be an array, an object, or null'); - } - - $clone = clone $this; - $clone->bodyParsed = $data; - - return $clone; - } - - /** - * Force Body to be parsed again. - * - * Note: This method is not part of the PSR-7 standard. - * - * @return $this - */ - public function reparseBody() - { - $this->bodyParsed = false; - - return $this; - } - - /** - * Register media type parser. - * - * Note: This method is not part of the PSR-7 standard. - * - * @param string $mediaType A HTTP media type (excluding content-type - * params). - * @param callable $callable A callable that returns parsed contents for - * media type. - */ - public function registerMediaTypeParser($mediaType, callable $callable) - { - if ($callable instanceof Closure) { - $callable = $callable->bindTo($this); - } - $this->bodyParsers[(string)$mediaType] = $callable; - } - - /******************************************************************************* - * Parameters (e.g., POST and GET data) - ******************************************************************************/ - - /** - * Fetch request parameter value from body or query string (in that order). - * - * Note: This method is not part of the PSR-7 standard. - * - * @param string $key The parameter key. - * @param string $default The default value. - * - * @return mixed The parameter value. - */ - public function getParam($key, $default = null) - { - $postParams = $this->getParsedBody(); - $getParams = $this->getQueryParams(); - $result = $default; - if (is_array($postParams) && isset($postParams[$key])) { - $result = $postParams[$key]; - } elseif (is_object($postParams) && property_exists($postParams, $key)) { - $result = $postParams->$key; - } elseif (isset($getParams[$key])) { - $result = $getParams[$key]; - } - - return $result; - } - - /** - * Fetch parameter value from request body. - * - * Note: This method is not part of the PSR-7 standard. - * - * @param string $key - * @param mixed $default - * - * @return mixed - */ - public function getParsedBodyParam($key, $default = null) - { - $postParams = $this->getParsedBody(); - $result = $default; - if (is_array($postParams) && isset($postParams[$key])) { - $result = $postParams[$key]; - } elseif (is_object($postParams) && property_exists($postParams, $key)) { - $result = $postParams->$key; - } - - return $result; - } - - /** - * Fetch parameter value from query string. - * - * Note: This method is not part of the PSR-7 standard. - * - * @param string $key - * @param mixed $default - * - * @return mixed - */ - public function getQueryParam($key, $default = null) - { - $getParams = $this->getQueryParams(); - $result = $default; - if (isset($getParams[$key])) { - $result = $getParams[$key]; - } - - return $result; - } - - /** - * Fetch associative array of body and query string parameters. - * - * Note: This method is not part of the PSR-7 standard. - * - * @param array|null $only list the keys to retrieve. - * @return array|null - */ - public function getParams(array $only = null) - { - $params = $this->getQueryParams(); - $postParams = $this->getParsedBody(); - if ($postParams) { - $params = array_merge($params, (array)$postParams); - } - - if ($only) { - $onlyParams = []; - foreach ($only as $key) { - if (array_key_exists($key, $params)) { - $onlyParams[$key] = $params[$key]; - } - } - return $onlyParams; - } - - return $params; - } -} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Http/RequestBody.php b/advancedcontentfilter/vendor/slim/slim/Slim/Http/RequestBody.php deleted file mode 100644 index 50887fddc..000000000 --- a/advancedcontentfilter/vendor/slim/slim/Slim/Http/RequestBody.php +++ /dev/null @@ -1,27 +0,0 @@ - 'Continue', - 101 => 'Switching Protocols', - 102 => 'Processing', - //Successful 2xx - 200 => 'OK', - 201 => 'Created', - 202 => 'Accepted', - 203 => 'Non-Authoritative Information', - 204 => 'No Content', - 205 => 'Reset Content', - 206 => 'Partial Content', - 207 => 'Multi-Status', - 208 => 'Already Reported', - 226 => 'IM Used', - //Redirection 3xx - 300 => 'Multiple Choices', - 301 => 'Moved Permanently', - 302 => 'Found', - 303 => 'See Other', - 304 => 'Not Modified', - 305 => 'Use Proxy', - 306 => '(Unused)', - 307 => 'Temporary Redirect', - 308 => 'Permanent Redirect', - //Client Error 4xx - 400 => 'Bad Request', - 401 => 'Unauthorized', - 402 => 'Payment Required', - 403 => 'Forbidden', - 404 => 'Not Found', - 405 => 'Method Not Allowed', - 406 => 'Not Acceptable', - 407 => 'Proxy Authentication Required', - 408 => 'Request Timeout', - 409 => 'Conflict', - 410 => 'Gone', - 411 => 'Length Required', - 412 => 'Precondition Failed', - 413 => 'Request Entity Too Large', - 414 => 'Request-URI Too Long', - 415 => 'Unsupported Media Type', - 416 => 'Requested Range Not Satisfiable', - 417 => 'Expectation Failed', - 418 => 'I\'m a teapot', - 421 => 'Misdirected Request', - 422 => 'Unprocessable Entity', - 423 => 'Locked', - 424 => 'Failed Dependency', - 426 => 'Upgrade Required', - 428 => 'Precondition Required', - 429 => 'Too Many Requests', - 431 => 'Request Header Fields Too Large', - 444 => 'Connection Closed Without Response', - 451 => 'Unavailable For Legal Reasons', - 499 => 'Client Closed Request', - //Server Error 5xx - 500 => 'Internal Server Error', - 501 => 'Not Implemented', - 502 => 'Bad Gateway', - 503 => 'Service Unavailable', - 504 => 'Gateway Timeout', - 505 => 'HTTP Version Not Supported', - 506 => 'Variant Also Negotiates', - 507 => 'Insufficient Storage', - 508 => 'Loop Detected', - 510 => 'Not Extended', - 511 => 'Network Authentication Required', - 599 => 'Network Connect Timeout Error', - ]; - - /** - * EOL characters used for HTTP response. - * - * @var string - */ - const EOL = "\r\n"; - - /** - * Create new HTTP response. - * - * @param int $status The response status code. - * @param HeadersInterface|null $headers The response headers. - * @param StreamInterface|null $body The response body. - */ - public function __construct($status = 200, HeadersInterface $headers = null, StreamInterface $body = null) - { - $this->status = $this->filterStatus($status); - $this->headers = $headers ? $headers : new Headers(); - $this->body = $body ? $body : new Body(fopen('php://temp', 'r+')); - } - - /** - * This method is applied to the cloned object - * after PHP performs an initial shallow-copy. This - * method completes a deep-copy by creating new objects - * for the cloned object's internal reference pointers. - */ - public function __clone() - { - $this->headers = clone $this->headers; - } - - /******************************************************************************* - * Status - ******************************************************************************/ - - /** - * Gets the response status code. - * - * The status code is a 3-digit integer result code of the server's attempt - * to understand and satisfy the request. - * - * @return int Status code. - */ - public function getStatusCode() - { - return $this->status; - } - - /** - * Return an instance with the specified status code and, optionally, reason phrase. - * - * If no reason phrase is specified, implementations MAY choose to default - * to the RFC 7231 or IANA recommended reason phrase for the response's - * status code. - * - * This method MUST be implemented in such a way as to retain the - * immutability of the message, and MUST return an instance that has the - * updated status and reason phrase. - * - * @link http://tools.ietf.org/html/rfc7231#section-6 - * @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml - * @param int $code The 3-digit integer result code to set. - * @param string $reasonPhrase The reason phrase to use with the - * provided status code; if none is provided, implementations MAY - * use the defaults as suggested in the HTTP specification. - * @return static - * @throws \InvalidArgumentException For invalid status code arguments. - */ - public function withStatus($code, $reasonPhrase = '') - { - $code = $this->filterStatus($code); - - if (!is_string($reasonPhrase) && !method_exists($reasonPhrase, '__toString')) { - throw new InvalidArgumentException('ReasonPhrase must be a string'); - } - - $clone = clone $this; - $clone->status = $code; - if ($reasonPhrase === '' && isset(static::$messages[$code])) { - $reasonPhrase = static::$messages[$code]; - } - - if ($reasonPhrase === '') { - throw new InvalidArgumentException('ReasonPhrase must be supplied for this code'); - } - - $clone->reasonPhrase = $reasonPhrase; - - return $clone; - } - - /** - * Filter HTTP status code. - * - * @param int $status HTTP status code. - * @return int - * @throws \InvalidArgumentException If an invalid HTTP status code is provided. - */ - protected function filterStatus($status) - { - if (!is_integer($status) || $status<100 || $status>599) { - throw new InvalidArgumentException('Invalid HTTP status code'); - } - - return $status; - } - - /** - * Gets the response reason phrase associated with the status code. - * - * Because a reason phrase is not a required element in a response - * status line, the reason phrase value MAY be null. Implementations MAY - * choose to return the default RFC 7231 recommended reason phrase (or those - * listed in the IANA HTTP Status Code Registry) for the response's - * status code. - * - * @link http://tools.ietf.org/html/rfc7231#section-6 - * @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml - * @return string Reason phrase; must return an empty string if none present. - */ - public function getReasonPhrase() - { - if ($this->reasonPhrase) { - return $this->reasonPhrase; - } - if (isset(static::$messages[$this->status])) { - return static::$messages[$this->status]; - } - return ''; - } - - /******************************************************************************* - * Headers - ******************************************************************************/ - - /** - * Return an instance with the provided value replacing the specified header. - * - * If a Location header is set and the status code is 200, then set the status - * code to 302 to mimic what PHP does. See https://github.com/slimphp/Slim/issues/1730 - * - * @param string $name Case-insensitive header field name. - * @param string|string[] $value Header value(s). - * @return static - * @throws \InvalidArgumentException for invalid header names or values. - */ - public function withHeader($name, $value) - { - $clone = clone $this; - $clone->headers->set($name, $value); - - if ($clone->getStatusCode() === 200 && strtolower($name) === 'location') { - $clone = $clone->withStatus(302); - } - - return $clone; - } - - - /******************************************************************************* - * Body - ******************************************************************************/ - - /** - * Write data to the response body. - * - * Note: This method is not part of the PSR-7 standard. - * - * Proxies to the underlying stream and writes the provided data to it. - * - * @param string $data - * @return $this - */ - public function write($data) - { - $this->getBody()->write($data); - - return $this; - } - - /******************************************************************************* - * Response Helpers - ******************************************************************************/ - - /** - * Redirect. - * - * Note: This method is not part of the PSR-7 standard. - * - * This method prepares the response object to return an HTTP Redirect - * response to the client. - * - * @param string|UriInterface $url The redirect destination. - * @param int|null $status The redirect HTTP status code. - * @return static - */ - public function withRedirect($url, $status = null) - { - $responseWithRedirect = $this->withHeader('Location', (string)$url); - - if (is_null($status) && $this->getStatusCode() === 200) { - $status = 302; - } - - if (!is_null($status)) { - return $responseWithRedirect->withStatus($status); - } - - return $responseWithRedirect; - } - - /** - * Json. - * - * Note: This method is not part of the PSR-7 standard. - * - * This method prepares the response object to return an HTTP Json - * response to the client. - * - * @param mixed $data The data - * @param int $status The HTTP status code. - * @param int $encodingOptions Json encoding options - * @throws \RuntimeException - * @return static - */ - public function withJson($data, $status = null, $encodingOptions = 0) - { - $response = $this->withBody(new Body(fopen('php://temp', 'r+'))); - $response->body->write($json = json_encode($data, $encodingOptions)); - - // Ensure that the json encoding passed successfully - if ($json === false) { - throw new \RuntimeException(json_last_error_msg(), json_last_error()); - } - - $responseWithJson = $response->withHeader('Content-Type', 'application/json;charset=utf-8'); - if (isset($status)) { - return $responseWithJson->withStatus($status); - } - return $responseWithJson; - } - - /** - * Is this response empty? - * - * Note: This method is not part of the PSR-7 standard. - * - * @return bool - */ - public function isEmpty() - { - return in_array($this->getStatusCode(), [204, 205, 304]); - } - - /** - * Is this response informational? - * - * Note: This method is not part of the PSR-7 standard. - * - * @return bool - */ - public function isInformational() - { - return $this->getStatusCode() >= 100 && $this->getStatusCode() < 200; - } - - /** - * Is this response OK? - * - * Note: This method is not part of the PSR-7 standard. - * - * @return bool - */ - public function isOk() - { - return $this->getStatusCode() === 200; - } - - /** - * Is this response successful? - * - * Note: This method is not part of the PSR-7 standard. - * - * @return bool - */ - public function isSuccessful() - { - return $this->getStatusCode() >= 200 && $this->getStatusCode() < 300; - } - - /** - * Is this response a redirect? - * - * Note: This method is not part of the PSR-7 standard. - * - * @return bool - */ - public function isRedirect() - { - return in_array($this->getStatusCode(), [301, 302, 303, 307]); - } - - /** - * Is this response a redirection? - * - * Note: This method is not part of the PSR-7 standard. - * - * @return bool - */ - public function isRedirection() - { - return $this->getStatusCode() >= 300 && $this->getStatusCode() < 400; - } - - /** - * Is this response forbidden? - * - * Note: This method is not part of the PSR-7 standard. - * - * @return bool - * @api - */ - public function isForbidden() - { - return $this->getStatusCode() === 403; - } - - /** - * Is this response not Found? - * - * Note: This method is not part of the PSR-7 standard. - * - * @return bool - */ - public function isNotFound() - { - return $this->getStatusCode() === 404; - } - - /** - * Is this response a client error? - * - * Note: This method is not part of the PSR-7 standard. - * - * @return bool - */ - public function isClientError() - { - return $this->getStatusCode() >= 400 && $this->getStatusCode() < 500; - } - - /** - * Is this response a server error? - * - * Note: This method is not part of the PSR-7 standard. - * - * @return bool - */ - public function isServerError() - { - return $this->getStatusCode() >= 500 && $this->getStatusCode() < 600; - } - - /** - * Convert response to string. - * - * Note: This method is not part of the PSR-7 standard. - * - * @return string - */ - public function __toString() - { - $output = sprintf( - 'HTTP/%s %s %s', - $this->getProtocolVersion(), - $this->getStatusCode(), - $this->getReasonPhrase() - ); - $output .= Response::EOL; - foreach ($this->getHeaders() as $name => $values) { - $output .= sprintf('%s: %s', $name, $this->getHeaderLine($name)) . Response::EOL; - } - $output .= Response::EOL; - $output .= (string)$this->getBody(); - - return $output; - } -} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Http/Stream.php b/advancedcontentfilter/vendor/slim/slim/Slim/Http/Stream.php deleted file mode 100644 index 27c7a7645..000000000 --- a/advancedcontentfilter/vendor/slim/slim/Slim/Http/Stream.php +++ /dev/null @@ -1,450 +0,0 @@ - ['r', 'r+', 'w+', 'a+', 'x+', 'c+'], - 'writable' => ['r+', 'w', 'w+', 'a', 'a+', 'x', 'x+', 'c', 'c+'], - ]; - - /** - * The underlying stream resource - * - * @var resource - */ - protected $stream; - - /** - * Stream metadata - * - * @var array - */ - protected $meta; - - /** - * Is this stream readable? - * - * @var bool - */ - protected $readable; - - /** - * Is this stream writable? - * - * @var bool - */ - protected $writable; - - /** - * Is this stream seekable? - * - * @var bool - */ - protected $seekable; - - /** - * The size of the stream if known - * - * @var null|int - */ - protected $size; - - /** - * Is this stream a pipe? - * - * @var bool - */ - protected $isPipe; - - /** - * Create a new Stream. - * - * @param resource $stream A PHP resource handle. - * - * @throws InvalidArgumentException If argument is not a resource. - */ - public function __construct($stream) - { - $this->attach($stream); - } - - /** - * Get stream metadata as an associative array or retrieve a specific key. - * - * The keys returned are identical to the keys returned from PHP's - * stream_get_meta_data() function. - * - * @link http://php.net/manual/en/function.stream-get-meta-data.php - * - * @param string $key Specific metadata to retrieve. - * - * @return array|mixed|null Returns an associative array if no key is - * provided. Returns a specific key value if a key is provided and the - * value is found, or null if the key is not found. - */ - public function getMetadata($key = null) - { - $this->meta = stream_get_meta_data($this->stream); - if (is_null($key) === true) { - return $this->meta; - } - - return isset($this->meta[$key]) ? $this->meta[$key] : null; - } - - /** - * Is a resource attached to this stream? - * - * Note: This method is not part of the PSR-7 standard. - * - * @return bool - */ - protected function isAttached() - { - return is_resource($this->stream); - } - - /** - * Attach new resource to this object. - * - * Note: This method is not part of the PSR-7 standard. - * - * @param resource $newStream A PHP resource handle. - * - * @throws InvalidArgumentException If argument is not a valid PHP resource. - */ - protected function attach($newStream) - { - if (is_resource($newStream) === false) { - throw new InvalidArgumentException(__METHOD__ . ' argument must be a valid PHP resource'); - } - - if ($this->isAttached() === true) { - $this->detach(); - } - - $this->stream = $newStream; - } - - /** - * Separates any underlying resources from the stream. - * - * After the stream has been detached, the stream is in an unusable state. - * - * @return resource|null Underlying PHP stream, if any - */ - public function detach() - { - $oldResource = $this->stream; - $this->stream = null; - $this->meta = null; - $this->readable = null; - $this->writable = null; - $this->seekable = null; - $this->size = null; - $this->isPipe = null; - - return $oldResource; - } - - /** - * Reads all data from the stream into a string, from the beginning to end. - * - * This method MUST attempt to seek to the beginning of the stream before - * reading data and read the stream until the end is reached. - * - * Warning: This could attempt to load a large amount of data into memory. - * - * This method MUST NOT raise an exception in order to conform with PHP's - * string casting operations. - * - * @see http://php.net/manual/en/language.oop5.magic.php#object.tostring - * @return string - */ - public function __toString() - { - if (!$this->isAttached()) { - return ''; - } - - try { - $this->rewind(); - return $this->getContents(); - } catch (RuntimeException $e) { - return ''; - } - } - - /** - * Closes the stream and any underlying resources. - */ - public function close() - { - if ($this->isAttached() === true) { - if ($this->isPipe()) { - pclose($this->stream); - } else { - fclose($this->stream); - } - } - - $this->detach(); - } - - /** - * Get the size of the stream if known. - * - * @return int|null Returns the size in bytes if known, or null if unknown. - */ - public function getSize() - { - if (!$this->size && $this->isAttached() === true) { - $stats = fstat($this->stream); - $this->size = isset($stats['size']) && !$this->isPipe() ? $stats['size'] : null; - } - - return $this->size; - } - - /** - * Returns the current position of the file read/write pointer - * - * @return int Position of the file pointer - * - * @throws RuntimeException on error. - */ - public function tell() - { - if (!$this->isAttached() || ($position = ftell($this->stream)) === false || $this->isPipe()) { - throw new RuntimeException('Could not get the position of the pointer in stream'); - } - - return $position; - } - - /** - * Returns true if the stream is at the end of the stream. - * - * @return bool - */ - public function eof() - { - return $this->isAttached() ? feof($this->stream) : true; - } - - /** - * Returns whether or not the stream is readable. - * - * @return bool - */ - public function isReadable() - { - if ($this->readable === null) { - if ($this->isPipe()) { - $this->readable = true; - } else { - $this->readable = false; - if ($this->isAttached()) { - $meta = $this->getMetadata(); - foreach (self::$modes['readable'] as $mode) { - if (strpos($meta['mode'], $mode) === 0) { - $this->readable = true; - break; - } - } - } - } - } - - return $this->readable; - } - - /** - * Returns whether or not the stream is writable. - * - * @return bool - */ - public function isWritable() - { - if ($this->writable === null) { - $this->writable = false; - if ($this->isAttached()) { - $meta = $this->getMetadata(); - foreach (self::$modes['writable'] as $mode) { - if (strpos($meta['mode'], $mode) === 0) { - $this->writable = true; - break; - } - } - } - } - - return $this->writable; - } - - /** - * Returns whether or not the stream is seekable. - * - * @return bool - */ - public function isSeekable() - { - if ($this->seekable === null) { - $this->seekable = false; - if ($this->isAttached()) { - $meta = $this->getMetadata(); - $this->seekable = !$this->isPipe() && $meta['seekable']; - } - } - - return $this->seekable; - } - - /** - * Seek to a position in the stream. - * - * @link http://www.php.net/manual/en/function.fseek.php - * - * @param int $offset Stream offset - * @param int $whence Specifies how the cursor position will be calculated - * based on the seek offset. Valid values are identical to the built-in - * PHP $whence values for `fseek()`. SEEK_SET: Set position equal to - * offset bytes SEEK_CUR: Set position to current location plus offset - * SEEK_END: Set position to end-of-stream plus offset. - * - * @throws RuntimeException on failure. - */ - public function seek($offset, $whence = SEEK_SET) - { - // Note that fseek returns 0 on success! - if (!$this->isSeekable() || fseek($this->stream, $offset, $whence) === -1) { - throw new RuntimeException('Could not seek in stream'); - } - } - - /** - * Seek to the beginning of the stream. - * - * If the stream is not seekable, this method will raise an exception; - * otherwise, it will perform a seek(0). - * - * @see seek() - * - * @link http://www.php.net/manual/en/function.fseek.php - * - * @throws RuntimeException on failure. - */ - public function rewind() - { - if (!$this->isSeekable() || rewind($this->stream) === false) { - throw new RuntimeException('Could not rewind stream'); - } - } - - /** - * Read data from the stream. - * - * @param int $length Read up to $length bytes from the object and return - * them. Fewer than $length bytes may be returned if underlying stream - * call returns fewer bytes. - * - * @return string Returns the data read from the stream, or an empty string - * if no bytes are available. - * - * @throws RuntimeException if an error occurs. - */ - public function read($length) - { - if (!$this->isReadable() || ($data = fread($this->stream, $length)) === false) { - throw new RuntimeException('Could not read from stream'); - } - - return $data; - } - - /** - * Write data to the stream. - * - * @param string $string The string that is to be written. - * - * @return int Returns the number of bytes written to the stream. - * - * @throws RuntimeException on failure. - */ - public function write($string) - { - if (!$this->isWritable() || ($written = fwrite($this->stream, $string)) === false) { - throw new RuntimeException('Could not write to stream'); - } - - // reset size so that it will be recalculated on next call to getSize() - $this->size = null; - - return $written; - } - - /** - * Returns the remaining contents in a string - * - * @return string - * - * @throws RuntimeException if unable to read or an error occurs while - * reading. - */ - public function getContents() - { - if (!$this->isReadable() || ($contents = stream_get_contents($this->stream)) === false) { - throw new RuntimeException('Could not get contents of stream'); - } - - return $contents; - } - - /** - * Returns whether or not the stream is a pipe. - * - * @return bool - */ - public function isPipe() - { - if ($this->isPipe === null) { - $this->isPipe = false; - if ($this->isAttached()) { - $mode = fstat($this->stream)['mode']; - $this->isPipe = ($mode & self::FSTAT_MODE_S_IFIFO) !== 0; - } - } - - return $this->isPipe; - } -} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Http/UploadedFile.php b/advancedcontentfilter/vendor/slim/slim/Slim/Http/UploadedFile.php deleted file mode 100644 index ae5dfb65e..000000000 --- a/advancedcontentfilter/vendor/slim/slim/Slim/Http/UploadedFile.php +++ /dev/null @@ -1,327 +0,0 @@ -has('slim.files')) { - return $env['slim.files']; - } elseif (isset($_FILES)) { - return static::parseUploadedFiles($_FILES); - } - - return []; - } - - /** - * Parse a non-normalized, i.e. $_FILES superglobal, tree of uploaded file data. - * - * @param array $uploadedFiles The non-normalized tree of uploaded file data. - * - * @return array A normalized tree of UploadedFile instances. - */ - private static function parseUploadedFiles(array $uploadedFiles) - { - $parsed = []; - foreach ($uploadedFiles as $field => $uploadedFile) { - if (!isset($uploadedFile['error'])) { - if (is_array($uploadedFile)) { - $parsed[$field] = static::parseUploadedFiles($uploadedFile); - } - continue; - } - - $parsed[$field] = []; - if (!is_array($uploadedFile['error'])) { - $parsed[$field] = new static( - $uploadedFile['tmp_name'], - isset($uploadedFile['name']) ? $uploadedFile['name'] : null, - isset($uploadedFile['type']) ? $uploadedFile['type'] : null, - isset($uploadedFile['size']) ? $uploadedFile['size'] : null, - $uploadedFile['error'], - true - ); - } else { - $subArray = []; - foreach ($uploadedFile['error'] as $fileIdx => $error) { - // normalise subarray and re-parse to move the input's keyname up a level - $subArray[$fileIdx]['name'] = $uploadedFile['name'][$fileIdx]; - $subArray[$fileIdx]['type'] = $uploadedFile['type'][$fileIdx]; - $subArray[$fileIdx]['tmp_name'] = $uploadedFile['tmp_name'][$fileIdx]; - $subArray[$fileIdx]['error'] = $uploadedFile['error'][$fileIdx]; - $subArray[$fileIdx]['size'] = $uploadedFile['size'][$fileIdx]; - - $parsed[$field] = static::parseUploadedFiles($subArray); - } - } - } - - return $parsed; - } - - /** - * Construct a new UploadedFile instance. - * - * @param string $file The full path to the uploaded file provided by the client. - * @param string|null $name The file name. - * @param string|null $type The file media type. - * @param int|null $size The file size in bytes. - * @param int $error The UPLOAD_ERR_XXX code representing the status of the upload. - * @param bool $sapi Indicates if the upload is in a SAPI environment. - */ - public function __construct($file, $name = null, $type = null, $size = null, $error = UPLOAD_ERR_OK, $sapi = false) - { - $this->file = $file; - $this->name = $name; - $this->type = $type; - $this->size = $size; - $this->error = $error; - $this->sapi = $sapi; - } - - /** - * Retrieve a stream representing the uploaded file. - * - * This method MUST return a StreamInterface instance, representing the - * uploaded file. The purpose of this method is to allow utilizing native PHP - * stream functionality to manipulate the file upload, such as - * stream_copy_to_stream() (though the result will need to be decorated in a - * native PHP stream wrapper to work with such functions). - * - * If the moveTo() method has been called previously, this method MUST raise - * an exception. - * - * @return StreamInterface Stream representation of the uploaded file. - * @throws \RuntimeException in cases when no stream is available or can be - * created. - */ - public function getStream() - { - if ($this->moved) { - throw new \RuntimeException(sprintf('Uploaded file %1s has already been moved', $this->name)); - } - if ($this->stream === null) { - $this->stream = new Stream(fopen($this->file, 'r')); - } - - return $this->stream; - } - - /** - * Move the uploaded file to a new location. - * - * Use this method as an alternative to move_uploaded_file(). This method is - * guaranteed to work in both SAPI and non-SAPI environments. - * Implementations must determine which environment they are in, and use the - * appropriate method (move_uploaded_file(), rename(), or a stream - * operation) to perform the operation. - * - * $targetPath may be an absolute path, or a relative path. If it is a - * relative path, resolution should be the same as used by PHP's rename() - * function. - * - * The original file or stream MUST be removed on completion. - * - * If this method is called more than once, any subsequent calls MUST raise - * an exception. - * - * When used in an SAPI environment where $_FILES is populated, when writing - * files via moveTo(), is_uploaded_file() and move_uploaded_file() SHOULD be - * used to ensure permissions and upload status are verified correctly. - * - * If you wish to move to a stream, use getStream(), as SAPI operations - * cannot guarantee writing to stream destinations. - * - * @see http://php.net/is_uploaded_file - * @see http://php.net/move_uploaded_file - * - * @param string $targetPath Path to which to move the uploaded file. - * - * @throws InvalidArgumentException if the $path specified is invalid. - * @throws RuntimeException on any error during the move operation, or on - * the second or subsequent call to the method. - */ - public function moveTo($targetPath) - { - if ($this->moved) { - throw new RuntimeException('Uploaded file already moved'); - } - - $targetIsStream = strpos($targetPath, '://') > 0; - if (!$targetIsStream && !is_writable(dirname($targetPath))) { - throw new InvalidArgumentException('Upload target path is not writable'); - } - - if ($targetIsStream) { - if (!copy($this->file, $targetPath)) { - throw new RuntimeException(sprintf('Error moving uploaded file %1s to %2s', $this->name, $targetPath)); - } - if (!unlink($this->file)) { - throw new RuntimeException(sprintf('Error removing uploaded file %1s', $this->name)); - } - } elseif ($this->sapi) { - if (!is_uploaded_file($this->file)) { - throw new RuntimeException(sprintf('%1s is not a valid uploaded file', $this->file)); - } - - if (!move_uploaded_file($this->file, $targetPath)) { - throw new RuntimeException(sprintf('Error moving uploaded file %1s to %2s', $this->name, $targetPath)); - } - } else { - if (!rename($this->file, $targetPath)) { - throw new RuntimeException(sprintf('Error moving uploaded file %1s to %2s', $this->name, $targetPath)); - } - } - - $this->moved = true; - } - - /** - * Retrieve the error associated with the uploaded file. - * - * The return value MUST be one of PHP's UPLOAD_ERR_XXX constants. - * - * If the file was uploaded successfully, this method MUST return - * UPLOAD_ERR_OK. - * - * Implementations SHOULD return the value stored in the "error" key of - * the file in the $_FILES array. - * - * @see http://php.net/manual/en/features.file-upload.errors.php - * - * @return int One of PHP's UPLOAD_ERR_XXX constants. - */ - public function getError() - { - return $this->error; - } - - /** - * Retrieve the filename sent by the client. - * - * Do not trust the value returned by this method. A client could send - * a malicious filename with the intention to corrupt or hack your - * application. - * - * Implementations SHOULD return the value stored in the "name" key of - * the file in the $_FILES array. - * - * @return string|null The filename sent by the client or null if none - * was provided. - */ - public function getClientFilename() - { - return $this->name; - } - - /** - * Retrieve the media type sent by the client. - * - * Do not trust the value returned by this method. A client could send - * a malicious media type with the intention to corrupt or hack your - * application. - * - * Implementations SHOULD return the value stored in the "type" key of - * the file in the $_FILES array. - * - * @return string|null The media type sent by the client or null if none - * was provided. - */ - public function getClientMediaType() - { - return $this->type; - } - - /** - * Retrieve the file size. - * - * Implementations SHOULD return the value stored in the "size" key of - * the file in the $_FILES array if available, as PHP calculates this based - * on the actual size transmitted. - * - * @return int|null The file size in bytes or null if unknown. - */ - public function getSize() - { - return $this->size; - } -} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Http/Uri.php b/advancedcontentfilter/vendor/slim/slim/Slim/Http/Uri.php deleted file mode 100644 index fb0f04b5c..000000000 --- a/advancedcontentfilter/vendor/slim/slim/Slim/Http/Uri.php +++ /dev/null @@ -1,845 +0,0 @@ -scheme = $this->filterScheme($scheme); - $this->host = $host; - $this->port = $this->filterPort($port); - $this->path = empty($path) ? '/' : $this->filterPath($path); - $this->query = $this->filterQuery($query); - $this->fragment = $this->filterQuery($fragment); - $this->user = $user; - $this->password = $password; - } - - /** - * Create new Uri from string. - * - * @param string $uri Complete Uri string - * (i.e., https://user:pass@host:443/path?query). - * - * @return self - */ - public static function createFromString($uri) - { - if (!is_string($uri) && !method_exists($uri, '__toString')) { - throw new InvalidArgumentException('Uri must be a string'); - } - - $parts = parse_url($uri); - $scheme = isset($parts['scheme']) ? $parts['scheme'] : ''; - $user = isset($parts['user']) ? $parts['user'] : ''; - $pass = isset($parts['pass']) ? $parts['pass'] : ''; - $host = isset($parts['host']) ? $parts['host'] : ''; - $port = isset($parts['port']) ? $parts['port'] : null; - $path = isset($parts['path']) ? $parts['path'] : ''; - $query = isset($parts['query']) ? $parts['query'] : ''; - $fragment = isset($parts['fragment']) ? $parts['fragment'] : ''; - - return new static($scheme, $host, $port, $path, $query, $fragment, $user, $pass); - } - - /** - * Create new Uri from environment. - * - * @param Environment $env - * - * @return self - */ - public static function createFromEnvironment(Environment $env) - { - // Scheme - $isSecure = $env->get('HTTPS'); - $scheme = (empty($isSecure) || $isSecure === 'off') ? 'http' : 'https'; - - // Authority: Username and password - $username = $env->get('PHP_AUTH_USER', ''); - $password = $env->get('PHP_AUTH_PW', ''); - - // Authority: Host - if ($env->has('HTTP_HOST')) { - $host = $env->get('HTTP_HOST'); - } else { - $host = $env->get('SERVER_NAME'); - } - - // Authority: Port - $port = (int)$env->get('SERVER_PORT', 80); - if (preg_match('/^(\[[a-fA-F0-9:.]+\])(:\d+)?\z/', $host, $matches)) { - $host = $matches[1]; - - if (isset($matches[2])) { - $port = (int) substr($matches[2], 1); - } - } else { - $pos = strpos($host, ':'); - if ($pos !== false) { - $port = (int) substr($host, $pos + 1); - $host = strstr($host, ':', true); - } - } - - // Path - $requestScriptName = parse_url($env->get('SCRIPT_NAME'), PHP_URL_PATH); - $requestScriptDir = dirname($requestScriptName); - - // parse_url() requires a full URL. As we don't extract the domain name or scheme, - // we use a stand-in. - $requestUri = parse_url('http://example.com' . $env->get('REQUEST_URI'), PHP_URL_PATH); - - $basePath = ''; - $virtualPath = $requestUri; - if (stripos($requestUri, $requestScriptName) === 0) { - $basePath = $requestScriptName; - } elseif ($requestScriptDir !== '/' && stripos($requestUri, $requestScriptDir) === 0) { - $basePath = $requestScriptDir; - } - - if ($basePath) { - $virtualPath = ltrim(substr($requestUri, strlen($basePath)), '/'); - } - - // Query string - $queryString = $env->get('QUERY_STRING', ''); - if ($queryString === '') { - $queryString = parse_url('http://example.com' . $env->get('REQUEST_URI'), PHP_URL_QUERY); - } - - // Fragment - $fragment = ''; - - // Build Uri - $uri = new static($scheme, $host, $port, $virtualPath, $queryString, $fragment, $username, $password); - if ($basePath) { - $uri = $uri->withBasePath($basePath); - } - - return $uri; - } - - /******************************************************************************** - * Scheme - *******************************************************************************/ - - /** - * Retrieve the scheme component of the URI. - * - * If no scheme is present, this method MUST return an empty string. - * - * The value returned MUST be normalized to lowercase, per RFC 3986 - * Section 3.1. - * - * The trailing ":" character is not part of the scheme and MUST NOT be - * added. - * - * @see https://tools.ietf.org/html/rfc3986#section-3.1 - * @return string The URI scheme. - */ - public function getScheme() - { - return $this->scheme; - } - - /** - * Return an instance with the specified scheme. - * - * This method MUST retain the state of the current instance, and return - * an instance that contains the specified scheme. - * - * Implementations MUST support the schemes "http" and "https" case - * insensitively, and MAY accommodate other schemes if required. - * - * An empty scheme is equivalent to removing the scheme. - * - * @param string $scheme The scheme to use with the new instance. - * @return self A new instance with the specified scheme. - * @throws \InvalidArgumentException for invalid or unsupported schemes. - */ - public function withScheme($scheme) - { - $scheme = $this->filterScheme($scheme); - $clone = clone $this; - $clone->scheme = $scheme; - - return $clone; - } - - /** - * Filter Uri scheme. - * - * @param string $scheme Raw Uri scheme. - * @return string - * - * @throws InvalidArgumentException If the Uri scheme is not a string. - * @throws InvalidArgumentException If Uri scheme is not "", "https", or "http". - */ - protected function filterScheme($scheme) - { - static $valid = [ - '' => true, - 'https' => true, - 'http' => true, - ]; - - if (!is_string($scheme) && !method_exists($scheme, '__toString')) { - throw new InvalidArgumentException('Uri scheme must be a string'); - } - - $scheme = str_replace('://', '', strtolower((string)$scheme)); - if (!isset($valid[$scheme])) { - throw new InvalidArgumentException('Uri scheme must be one of: "", "https", "http"'); - } - - return $scheme; - } - - /******************************************************************************** - * Authority - *******************************************************************************/ - - /** - * Retrieve the authority component of the URI. - * - * If no authority information is present, this method MUST return an empty - * string. - * - * The authority syntax of the URI is: - * - *
-     * [user-info@]host[:port]
-     * 
- * - * If the port component is not set or is the standard port for the current - * scheme, it SHOULD NOT be included. - * - * @see https://tools.ietf.org/html/rfc3986#section-3.2 - * @return string The URI authority, in "[user-info@]host[:port]" format. - */ - public function getAuthority() - { - $userInfo = $this->getUserInfo(); - $host = $this->getHost(); - $port = $this->getPort(); - - return ($userInfo ? $userInfo . '@' : '') . $host . ($port !== null ? ':' . $port : ''); - } - - /** - * Retrieve the user information component of the URI. - * - * If no user information is present, this method MUST return an empty - * string. - * - * If a user is present in the URI, this will return that value; - * additionally, if the password is also present, it will be appended to the - * user value, with a colon (":") separating the values. - * - * The trailing "@" character is not part of the user information and MUST - * NOT be added. - * - * @return string The URI user information, in "username[:password]" format. - */ - public function getUserInfo() - { - return $this->user . ($this->password ? ':' . $this->password : ''); - } - - /** - * Return an instance with the specified user information. - * - * This method MUST retain the state of the current instance, and return - * an instance that contains the specified user information. - * - * Password is optional, but the user information MUST include the - * user; an empty string for the user is equivalent to removing user - * information. - * - * @param string $user The user name to use for authority. - * @param null|string $password The password associated with $user. - * @return self A new instance with the specified user information. - */ - public function withUserInfo($user, $password = null) - { - $clone = clone $this; - $clone->user = $this->filterUserInfo($user); - if ($clone->user) { - $clone->password = $password ? $this->filterUserInfo($password) : ''; - } else { - $clone->password = ''; - } - - return $clone; - } - - /** - * Filters the user info string. - * - * @param string $query The raw uri query string. - * @return string The percent-encoded query string. - */ - protected function filterUserInfo($query) - { - return preg_replace_callback( - '/(?:[^a-zA-Z0-9_\-\.~!\$&\'\(\)\*\+,;=]+|%(?![A-Fa-f0-9]{2}))/u', - function ($match) { - return rawurlencode($match[0]); - }, - $query - ); - } - - /** - * Retrieve the host component of the URI. - * - * If no host is present, this method MUST return an empty string. - * - * The value returned MUST be normalized to lowercase, per RFC 3986 - * Section 3.2.2. - * - * @see http://tools.ietf.org/html/rfc3986#section-3.2.2 - * @return string The URI host. - */ - public function getHost() - { - return $this->host; - } - - /** - * Return an instance with the specified host. - * - * This method MUST retain the state of the current instance, and return - * an instance that contains the specified host. - * - * An empty host value is equivalent to removing the host. - * - * @param string $host The hostname to use with the new instance. - * @return self A new instance with the specified host. - * @throws \InvalidArgumentException for invalid hostnames. - */ - public function withHost($host) - { - $clone = clone $this; - $clone->host = $host; - - return $clone; - } - - /** - * Retrieve the port component of the URI. - * - * If a port is present, and it is non-standard for the current scheme, - * this method MUST return it as an integer. If the port is the standard port - * used with the current scheme, this method SHOULD return null. - * - * If no port is present, and no scheme is present, this method MUST return - * a null value. - * - * If no port is present, but a scheme is present, this method MAY return - * the standard port for that scheme, but SHOULD return null. - * - * @return null|int The URI port. - */ - public function getPort() - { - return $this->port && !$this->hasStandardPort() ? $this->port : null; - } - - /** - * Return an instance with the specified port. - * - * This method MUST retain the state of the current instance, and return - * an instance that contains the specified port. - * - * Implementations MUST raise an exception for ports outside the - * established TCP and UDP port ranges. - * - * A null value provided for the port is equivalent to removing the port - * information. - * - * @param null|int $port The port to use with the new instance; a null value - * removes the port information. - * @return self A new instance with the specified port. - * @throws \InvalidArgumentException for invalid ports. - */ - public function withPort($port) - { - $port = $this->filterPort($port); - $clone = clone $this; - $clone->port = $port; - - return $clone; - } - - /** - * Does this Uri use a standard port? - * - * @return bool - */ - protected function hasStandardPort() - { - return ($this->scheme === 'http' && $this->port === 80) || ($this->scheme === 'https' && $this->port === 443); - } - - /** - * Filter Uri port. - * - * @param null|int $port The Uri port number. - * @return null|int - * - * @throws InvalidArgumentException If the port is invalid. - */ - protected function filterPort($port) - { - if (is_null($port) || (is_integer($port) && ($port >= 1 && $port <= 65535))) { - return $port; - } - - throw new InvalidArgumentException('Uri port must be null or an integer between 1 and 65535 (inclusive)'); - } - - /******************************************************************************** - * Path - *******************************************************************************/ - - /** - * Retrieve the path component of the URI. - * - * The path can either be empty or absolute (starting with a slash) or - * rootless (not starting with a slash). Implementations MUST support all - * three syntaxes. - * - * Normally, the empty path "" and absolute path "/" are considered equal as - * defined in RFC 7230 Section 2.7.3. But this method MUST NOT automatically - * do this normalization because in contexts with a trimmed base path, e.g. - * the front controller, this difference becomes significant. It's the task - * of the user to handle both "" and "/". - * - * The value returned MUST be percent-encoded, but MUST NOT double-encode - * any characters. To determine what characters to encode, please refer to - * RFC 3986, Sections 2 and 3.3. - * - * As an example, if the value should include a slash ("/") not intended as - * delimiter between path segments, that value MUST be passed in encoded - * form (e.g., "%2F") to the instance. - * - * @see https://tools.ietf.org/html/rfc3986#section-2 - * @see https://tools.ietf.org/html/rfc3986#section-3.3 - * @return string The URI path. - */ - public function getPath() - { - return $this->path; - } - - /** - * Return an instance with the specified path. - * - * This method MUST retain the state of the current instance, and return - * an instance that contains the specified path. - * - * The path can either be empty or absolute (starting with a slash) or - * rootless (not starting with a slash). Implementations MUST support all - * three syntaxes. - * - * If the path is intended to be domain-relative rather than path relative then - * it must begin with a slash ("/"). Paths not starting with a slash ("/") - * are assumed to be relative to some base path known to the application or - * consumer. - * - * Users can provide both encoded and decoded path characters. - * Implementations ensure the correct encoding as outlined in getPath(). - * - * @param string $path The path to use with the new instance. - * @return self A new instance with the specified path. - * @throws \InvalidArgumentException for invalid paths. - */ - public function withPath($path) - { - if (!is_string($path)) { - throw new InvalidArgumentException('Uri path must be a string'); - } - - $clone = clone $this; - $clone->path = $this->filterPath($path); - - // if the path is absolute, then clear basePath - if (substr($path, 0, 1) == '/') { - $clone->basePath = ''; - } - - return $clone; - } - - /** - * Retrieve the base path segment of the URI. - * - * Note: This method is not part of the PSR-7 standard. - * - * This method MUST return a string; if no path is present it MUST return - * an empty string. - * - * @return string The base path segment of the URI. - */ - public function getBasePath() - { - return $this->basePath; - } - - /** - * Set base path. - * - * Note: This method is not part of the PSR-7 standard. - * - * @param string $basePath - * @return self - */ - public function withBasePath($basePath) - { - if (!is_string($basePath)) { - throw new InvalidArgumentException('Uri path must be a string'); - } - if (!empty($basePath)) { - $basePath = '/' . trim($basePath, '/'); // <-- Trim on both sides - } - $clone = clone $this; - - if ($basePath !== '/') { - $clone->basePath = $this->filterPath($basePath); - } - - return $clone; - } - - /** - * Filter Uri path. - * - * This method percent-encodes all reserved - * characters in the provided path string. This method - * will NOT double-encode characters that are already - * percent-encoded. - * - * @param string $path The raw uri path. - * @return string The RFC 3986 percent-encoded uri path. - * @link http://www.faqs.org/rfcs/rfc3986.html - */ - protected function filterPath($path) - { - return preg_replace_callback( - '/(?:[^a-zA-Z0-9_\-\.~:@&=\+\$,\/;%]+|%(?![A-Fa-f0-9]{2}))/', - function ($match) { - return rawurlencode($match[0]); - }, - $path - ); - } - - /******************************************************************************** - * Query - *******************************************************************************/ - - /** - * Retrieve the query string of the URI. - * - * If no query string is present, this method MUST return an empty string. - * - * The leading "?" character is not part of the query and MUST NOT be - * added. - * - * The value returned MUST be percent-encoded, but MUST NOT double-encode - * any characters. To determine what characters to encode, please refer to - * RFC 3986, Sections 2 and 3.4. - * - * As an example, if a value in a key/value pair of the query string should - * include an ampersand ("&") not intended as a delimiter between values, - * that value MUST be passed in encoded form (e.g., "%26") to the instance. - * - * @see https://tools.ietf.org/html/rfc3986#section-2 - * @see https://tools.ietf.org/html/rfc3986#section-3.4 - * @return string The URI query string. - */ - public function getQuery() - { - return $this->query; - } - - /** - * Return an instance with the specified query string. - * - * This method MUST retain the state of the current instance, and return - * an instance that contains the specified query string. - * - * Users can provide both encoded and decoded query characters. - * Implementations ensure the correct encoding as outlined in getQuery(). - * - * An empty query string value is equivalent to removing the query string. - * - * @param string $query The query string to use with the new instance. - * @return self A new instance with the specified query string. - * @throws \InvalidArgumentException for invalid query strings. - */ - public function withQuery($query) - { - if (!is_string($query) && !method_exists($query, '__toString')) { - throw new InvalidArgumentException('Uri query must be a string'); - } - $query = ltrim((string)$query, '?'); - $clone = clone $this; - $clone->query = $this->filterQuery($query); - - return $clone; - } - - /** - * Filters the query string or fragment of a URI. - * - * @param string $query The raw uri query string. - * @return string The percent-encoded query string. - */ - protected function filterQuery($query) - { - return preg_replace_callback( - '/(?:[^a-zA-Z0-9_\-\.~!\$&\'\(\)\*\+,;=%:@\/\?]+|%(?![A-Fa-f0-9]{2}))/', - function ($match) { - return rawurlencode($match[0]); - }, - $query - ); - } - - /******************************************************************************** - * Fragment - *******************************************************************************/ - - /** - * Retrieve the fragment component of the URI. - * - * If no fragment is present, this method MUST return an empty string. - * - * The leading "#" character is not part of the fragment and MUST NOT be - * added. - * - * The value returned MUST be percent-encoded, but MUST NOT double-encode - * any characters. To determine what characters to encode, please refer to - * RFC 3986, Sections 2 and 3.5. - * - * @see https://tools.ietf.org/html/rfc3986#section-2 - * @see https://tools.ietf.org/html/rfc3986#section-3.5 - * @return string The URI fragment. - */ - public function getFragment() - { - return $this->fragment; - } - - /** - * Return an instance with the specified URI fragment. - * - * This method MUST retain the state of the current instance, and return - * an instance that contains the specified URI fragment. - * - * Users can provide both encoded and decoded fragment characters. - * Implementations ensure the correct encoding as outlined in getFragment(). - * - * An empty fragment value is equivalent to removing the fragment. - * - * @param string $fragment The fragment to use with the new instance. - * @return self A new instance with the specified fragment. - */ - public function withFragment($fragment) - { - if (!is_string($fragment) && !method_exists($fragment, '__toString')) { - throw new InvalidArgumentException('Uri fragment must be a string'); - } - $fragment = ltrim((string)$fragment, '#'); - $clone = clone $this; - $clone->fragment = $this->filterQuery($fragment); - - return $clone; - } - - /******************************************************************************** - * Helpers - *******************************************************************************/ - - /** - * Return the string representation as a URI reference. - * - * Depending on which components of the URI are present, the resulting - * string is either a full URI or relative reference according to RFC 3986, - * Section 4.1. The method concatenates the various components of the URI, - * using the appropriate delimiters: - * - * - If a scheme is present, it MUST be suffixed by ":". - * - If an authority is present, it MUST be prefixed by "//". - * - The path can be concatenated without delimiters. But there are two - * cases where the path has to be adjusted to make the URI reference - * valid as PHP does not allow to throw an exception in __toString(): - * - If the path is rootless and an authority is present, the path MUST - * be prefixed by "/". - * - If the path is starting with more than one "/" and no authority is - * present, the starting slashes MUST be reduced to one. - * - If a query is present, it MUST be prefixed by "?". - * - If a fragment is present, it MUST be prefixed by "#". - * - * @see http://tools.ietf.org/html/rfc3986#section-4.1 - * @return string - */ - public function __toString() - { - $scheme = $this->getScheme(); - $authority = $this->getAuthority(); - $basePath = $this->getBasePath(); - $path = $this->getPath(); - $query = $this->getQuery(); - $fragment = $this->getFragment(); - - $path = $basePath . '/' . ltrim($path, '/'); - - return ($scheme ? $scheme . ':' : '') - . ($authority ? '//' . $authority : '') - . $path - . ($query ? '?' . $query : '') - . ($fragment ? '#' . $fragment : ''); - } - - /** - * Return the fully qualified base URL. - * - * Note that this method never includes a trailing / - * - * This method is not part of PSR-7. - * - * @return string - */ - public function getBaseUrl() - { - $scheme = $this->getScheme(); - $authority = $this->getAuthority(); - $basePath = $this->getBasePath(); - - if ($authority && substr($basePath, 0, 1) !== '/') { - $basePath = $basePath . '/' . $basePath; - } - - return ($scheme ? $scheme . ':' : '') - . ($authority ? '//' . $authority : '') - . rtrim($basePath, '/'); - } -} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Interfaces/AdvancedCallableResolverInterface.php b/advancedcontentfilter/vendor/slim/slim/Slim/Interfaces/AdvancedCallableResolverInterface.php new file mode 100644 index 000000000..aa1d897de --- /dev/null +++ b/advancedcontentfilter/vendor/slim/slim/Slim/Interfaces/AdvancedCallableResolverInterface.php @@ -0,0 +1,28 @@ + $routeArguments The route's placeholder arguments * - * @return ResponseInterface|string The response from the callable. + * @return ResponseInterface The response from the callable. */ public function __invoke( callable $callable, ServerRequestInterface $request, ResponseInterface $response, array $routeArguments - ); + ): ResponseInterface; } diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Interfaces/MiddlewareDispatcherInterface.php b/advancedcontentfilter/vendor/slim/slim/Slim/Interfaces/MiddlewareDispatcherInterface.php new file mode 100644 index 000000000..aa7a26ad2 --- /dev/null +++ b/advancedcontentfilter/vendor/slim/slim/Slim/Interfaces/MiddlewareDispatcherInterface.php @@ -0,0 +1,42 @@ + + */ + public function getArguments(): array; + + /** + * Set a route argument + */ + public function setArgument(string $name, string $value): RouteInterface; + + /** + * Replace route arguments + * + * @param array $arguments + */ + public function setArguments(array $arguments): self; + + /** + * @param MiddlewareInterface|string|callable $middleware + */ + public function add($middleware): self; + + public function addMiddleware(MiddlewareInterface $middleware): self; /** * Prepare the route for use * - * @param ServerRequestInterface $request - * @param array $arguments + * @param array $arguments */ - public function prepare(ServerRequestInterface $request, array $arguments); + public function prepare(array $arguments): self; /** * Run route @@ -117,24 +118,6 @@ interface RouteInterface * This method traverses the middleware stack, including the route's callable * and captures the resultant HTTP response object. It then sends the response * back to the Application. - * - * @param ServerRequestInterface $request - * @param ResponseInterface $response - * @return ResponseInterface */ - public function run(ServerRequestInterface $request, ResponseInterface $response); - - /** - * Dispatch route callable against current Request and Response objects - * - * This method invokes the route object's callable. If middleware is - * registered for the route, each callable middleware is invoked in - * the order specified. - * - * @param ServerRequestInterface $request The current Request object - * @param ResponseInterface $response The current Response object - * - * @return ResponseInterface - */ - public function __invoke(ServerRequestInterface $request, ResponseInterface $response); + public function run(ServerRequestInterface $request): ResponseInterface; } diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Interfaces/RouteParserInterface.php b/advancedcontentfilter/vendor/slim/slim/Slim/Interfaces/RouteParserInterface.php new file mode 100644 index 000000000..03d932665 --- /dev/null +++ b/advancedcontentfilter/vendor/slim/slim/Slim/Interfaces/RouteParserInterface.php @@ -0,0 +1,52 @@ + $data Named argument replacement data + * @param array $queryParams Optional query string parameters + * + * @throws RuntimeException If named route does not exist + * @throws InvalidArgumentException If required data not provided + */ + public function relativeUrlFor(string $routeName, array $data = [], array $queryParams = []): string; + + /** + * Build the path for a named route including the base path + * + * @param string $routeName Route name + * @param array $data Named argument replacement data + * @param array $queryParams Optional query string parameters + * + * @throws RuntimeException If named route does not exist + * @throws InvalidArgumentException If required data not provided + */ + public function urlFor(string $routeName, array $data = [], array $queryParams = []): string; + + /** + * Get fully qualified URL for named route + * + * @param UriInterface $uri + * @param string $routeName Route name + * @param array $data Named argument replacement data + * @param array $queryParams Optional query string parameters + */ + public function fullUrlFor(UriInterface $uri, string $routeName, array $data = [], array $queryParams = []): string; +} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Interfaces/RouteResolverInterface.php b/advancedcontentfilter/vendor/slim/slim/Slim/Interfaces/RouteResolverInterface.php new file mode 100644 index 000000000..256a35997 --- /dev/null +++ b/advancedcontentfilter/vendor/slim/slim/Slim/Interfaces/RouteResolverInterface.php @@ -0,0 +1,17 @@ +getPath() + */ + public function computeRoutingResults(string $uri, string $method): RoutingResults; + + public function resolveRoute(string $identifier): RouteInterface; +} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Interfaces/RouterInterface.php b/advancedcontentfilter/vendor/slim/slim/Slim/Interfaces/RouterInterface.php deleted file mode 100644 index 2ab8b678f..000000000 --- a/advancedcontentfilter/vendor/slim/slim/Slim/Interfaces/RouterInterface.php +++ /dev/null @@ -1,111 +0,0 @@ - $context + * + * @throws InvalidArgumentException + */ + public function log($level, $message, array $context = []): void + { + error_log((string) $message); + } +} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Middleware/BodyParsingMiddleware.php b/advancedcontentfilter/vendor/slim/slim/Slim/Middleware/BodyParsingMiddleware.php new file mode 100644 index 000000000..9a90f30c4 --- /dev/null +++ b/advancedcontentfilter/vendor/slim/slim/Slim/Middleware/BodyParsingMiddleware.php @@ -0,0 +1,196 @@ + callable + */ + public function __construct(array $bodyParsers = []) + { + $this->registerDefaultBodyParsers(); + + foreach ($bodyParsers as $mediaType => $parser) { + $this->registerBodyParser($mediaType, $parser); + } + } + + public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface + { + $parsedBody = $request->getParsedBody(); + + if (empty($parsedBody)) { + $parsedBody = $this->parseBody($request); + $request = $request->withParsedBody($parsedBody); + } + + return $handler->handle($request); + } + + /** + * @param string $mediaType A HTTP media type (excluding content-type params). + * @param callable $callable A callable that returns parsed contents for media type. + */ + public function registerBodyParser(string $mediaType, callable $callable): self + { + $this->bodyParsers[$mediaType] = $callable; + return $this; + } + + /** + * @param string $mediaType A HTTP media type (excluding content-type params). + */ + public function hasBodyParser(string $mediaType): bool + { + return isset($this->bodyParsers[$mediaType]); + } + + /** + * @param string $mediaType A HTTP media type (excluding content-type params). + * @throws RuntimeException + */ + public function getBodyParser(string $mediaType): callable + { + if (!isset($this->bodyParsers[$mediaType])) { + throw new RuntimeException('No parser for type ' . $mediaType); + } + return $this->bodyParsers[$mediaType]; + } + + protected function registerDefaultBodyParsers(): void + { + $this->registerBodyParser('application/json', static function ($input) { + $result = json_decode($input, true); + + if (!is_array($result)) { + return null; + } + + return $result; + }); + + $this->registerBodyParser('application/x-www-form-urlencoded', static function ($input) { + parse_str($input, $data); + return $data; + }); + + $xmlCallable = static function ($input) { + $backup = self::disableXmlEntityLoader(true); + $backup_errors = libxml_use_internal_errors(true); + $result = simplexml_load_string($input); + + self::disableXmlEntityLoader($backup); + libxml_clear_errors(); + libxml_use_internal_errors($backup_errors); + + if ($result === false) { + return null; + } + + return $result; + }; + + $this->registerBodyParser('application/xml', $xmlCallable); + $this->registerBodyParser('text/xml', $xmlCallable); + } + + /** + * @return null|array|object + */ + protected function parseBody(ServerRequestInterface $request) + { + $mediaType = $this->getMediaType($request); + if ($mediaType === null) { + return null; + } + + // Check if this specific media type has a parser registered first + if (!isset($this->bodyParsers[$mediaType])) { + // If not, look for a media type with a structured syntax suffix (RFC 6839) + $parts = explode('+', $mediaType); + if (count($parts) >= 2) { + $mediaType = 'application/' . $parts[count($parts) - 1]; + } + } + + if (isset($this->bodyParsers[$mediaType])) { + $body = (string)$request->getBody(); + $parsed = $this->bodyParsers[$mediaType]($body); + + if ($parsed !== null && !is_object($parsed) && !is_array($parsed)) { + throw new RuntimeException( + 'Request body media type parser return value must be an array, an object, or null' + ); + } + + return $parsed; + } + + return null; + } + + /** + * @return string|null The serverRequest media type, minus content-type params + */ + protected function getMediaType(ServerRequestInterface $request): ?string + { + $contentType = $request->getHeader('Content-Type')[0] ?? null; + + if (is_string($contentType) && trim($contentType) !== '') { + $contentTypeParts = explode(';', $contentType); + return strtolower(trim($contentTypeParts[0])); + } + + return null; + } + + protected static function disableXmlEntityLoader(bool $disable): bool + { + if (LIBXML_VERSION >= 20900) { + // libxml >= 2.9.0 disables entity loading by default, so it is + // safe to skip the real call (deprecated in PHP 8). + return true; + } + + // @codeCoverageIgnoreStart + return libxml_disable_entity_loader($disable); + // @codeCoverageIgnoreEnd + } +} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Middleware/ContentLengthMiddleware.php b/advancedcontentfilter/vendor/slim/slim/Slim/Middleware/ContentLengthMiddleware.php new file mode 100644 index 000000000..8fa13bcf7 --- /dev/null +++ b/advancedcontentfilter/vendor/slim/slim/Slim/Middleware/ContentLengthMiddleware.php @@ -0,0 +1,32 @@ +handle($request); + + // Add Content-Length header if not already added + $size = $response->getBody()->getSize(); + if ($size !== null && !$response->hasHeader('Content-Length')) { + $response = $response->withHeader('Content-Length', (string) $size); + } + + return $response; + } +} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Middleware/ErrorMiddleware.php b/advancedcontentfilter/vendor/slim/slim/Slim/Middleware/ErrorMiddleware.php new file mode 100644 index 000000000..2eb5cc96f --- /dev/null +++ b/advancedcontentfilter/vendor/slim/slim/Slim/Middleware/ErrorMiddleware.php @@ -0,0 +1,212 @@ +callableResolver = $callableResolver; + $this->responseFactory = $responseFactory; + $this->displayErrorDetails = $displayErrorDetails; + $this->logErrors = $logErrors; + $this->logErrorDetails = $logErrorDetails; + $this->logger = $logger; + } + + public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface + { + try { + return $handler->handle($request); + } catch (Throwable $e) { + return $this->handleException($request, $e); + } + } + + public function handleException(ServerRequestInterface $request, Throwable $exception): ResponseInterface + { + if ($exception instanceof HttpException) { + $request = $exception->getRequest(); + } + + $exceptionType = get_class($exception); + $handler = $this->getErrorHandler($exceptionType); + + return $handler($request, $exception, $this->displayErrorDetails, $this->logErrors, $this->logErrorDetails); + } + + /** + * Get callable to handle scenarios where an error + * occurs when processing the current request. + * + * @param string $type Exception/Throwable name. ie: RuntimeException::class + * @return callable|ErrorHandler + */ + public function getErrorHandler(string $type) + { + if (isset($this->handlers[$type])) { + return $this->callableResolver->resolve($this->handlers[$type]); + } + + if (isset($this->subClassHandlers[$type])) { + return $this->callableResolver->resolve($this->subClassHandlers[$type]); + } + + foreach ($this->subClassHandlers as $class => $handler) { + if (is_subclass_of($type, $class)) { + return $this->callableResolver->resolve($handler); + } + } + + return $this->getDefaultErrorHandler(); + } + + /** + * Get default error handler + * + * @return ErrorHandler|callable + */ + public function getDefaultErrorHandler() + { + if ($this->defaultErrorHandler === null) { + $this->defaultErrorHandler = new ErrorHandler( + $this->callableResolver, + $this->responseFactory, + $this->logger + ); + } + + return $this->callableResolver->resolve($this->defaultErrorHandler); + } + + /** + * Set callable as the default Slim application error handler. + * + * The callable signature MUST match the ErrorHandlerInterface + * + * @see \Slim\Interfaces\ErrorHandlerInterface + * + * 1. Instance of \Psr\Http\Message\ServerRequestInterface + * 2. Instance of \Throwable + * 3. Boolean $displayErrorDetails + * 4. Boolean $logErrors + * 5. Boolean $logErrorDetails + * + * The callable MUST return an instance of + * \Psr\Http\Message\ResponseInterface. + * + * @param string|callable|ErrorHandler $handler + */ + public function setDefaultErrorHandler($handler): self + { + $this->defaultErrorHandler = $handler; + return $this; + } + + /** + * Set callable to handle scenarios where an error + * occurs when processing the current request. + * + * The callable signature MUST match the ErrorHandlerInterface + * + * Pass true to $handleSubclasses to make the handler handle all subclasses of + * the type as well. Pass an array of classes to make the same function handle multiple exceptions. + * + * @see \Slim\Interfaces\ErrorHandlerInterface + * + * 1. Instance of \Psr\Http\Message\ServerRequestInterface + * 2. Instance of \Throwable + * 3. Boolean $displayErrorDetails + * 4. Boolean $logErrors + * 5. Boolean $logErrorDetails + * + * The callable MUST return an instance of + * \Psr\Http\Message\ResponseInterface. + * + * @param string|string[] $typeOrTypes Exception/Throwable name. + * ie: RuntimeException::class or an array of classes + * ie: [HttpNotFoundException::class, HttpMethodNotAllowedException::class] + * @param string|callable|ErrorHandlerInterface $handler + */ + public function setErrorHandler($typeOrTypes, $handler, bool $handleSubclasses = false): self + { + if (is_array($typeOrTypes)) { + foreach ($typeOrTypes as $type) { + $this->addErrorHandler($type, $handler, $handleSubclasses); + } + } else { + $this->addErrorHandler($typeOrTypes, $handler, $handleSubclasses); + } + + return $this; + } + + /** + * Used internally to avoid code repetition when passing multiple exceptions to setErrorHandler(). + * @param string|callable|ErrorHandlerInterface $handler + */ + private function addErrorHandler(string $type, $handler, bool $handleSubclasses): void + { + if ($handleSubclasses) { + $this->subClassHandlers[$type] = $handler; + } else { + $this->handlers[$type] = $handler; + } + } +} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Middleware/MethodOverrideMiddleware.php b/advancedcontentfilter/vendor/slim/slim/Slim/Middleware/MethodOverrideMiddleware.php new file mode 100644 index 000000000..079a1f189 --- /dev/null +++ b/advancedcontentfilter/vendor/slim/slim/Slim/Middleware/MethodOverrideMiddleware.php @@ -0,0 +1,43 @@ +getHeaderLine('X-Http-Method-Override'); + + if ($methodHeader) { + $request = $request->withMethod($methodHeader); + } elseif (strtoupper($request->getMethod()) === 'POST') { + $body = $request->getParsedBody(); + + if (is_array($body) && !empty($body['_METHOD'])) { + $request = $request->withMethod($body['_METHOD']); + } + + if ($request->getBody()->eof()) { + $request->getBody()->rewind(); + } + } + + return $handler->handle($request); + } +} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Middleware/OutputBufferingMiddleware.php b/advancedcontentfilter/vendor/slim/slim/Slim/Middleware/OutputBufferingMiddleware.php new file mode 100644 index 000000000..69ee1f6f1 --- /dev/null +++ b/advancedcontentfilter/vendor/slim/slim/Slim/Middleware/OutputBufferingMiddleware.php @@ -0,0 +1,74 @@ +streamFactory = $streamFactory; + $this->style = $style; + + if (!in_array($style, [static::APPEND, static::PREPEND], true)) { + throw new InvalidArgumentException("Invalid style `{$style}`. Must be `append` or `prepend`"); + } + } + + /** + * @throws Throwable + */ + public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface + { + try { + ob_start(); + $response = $handler->handle($request); + $output = ob_get_clean(); + } catch (Throwable $e) { + ob_end_clean(); + throw $e; + } + + if (!empty($output)) { + if ($this->style === static::PREPEND) { + $body = $this->streamFactory->createStream(); + $body->write($output . $response->getBody()); + $response = $response->withBody($body); + } elseif ($this->style === static::APPEND && $response->getBody()->isWritable()) { + $response->getBody()->write($output); + } + } + + return $response; + } +} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Middleware/RoutingMiddleware.php b/advancedcontentfilter/vendor/slim/slim/Slim/Middleware/RoutingMiddleware.php new file mode 100644 index 000000000..a3d3085bd --- /dev/null +++ b/advancedcontentfilter/vendor/slim/slim/Slim/Middleware/RoutingMiddleware.php @@ -0,0 +1,98 @@ +routeResolver = $routeResolver; + $this->routeParser = $routeParser; + } + + /** + * @throws HttpNotFoundException + * @throws HttpMethodNotAllowedException + * @throws RuntimeException + */ + public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface + { + $request = $this->performRouting($request); + return $handler->handle($request); + } + + /** + * Perform routing + * + * @param ServerRequestInterface $request PSR7 Server Request + * + * @throws HttpNotFoundException + * @throws HttpMethodNotAllowedException + * @throws RuntimeException + */ + public function performRouting(ServerRequestInterface $request): ServerRequestInterface + { + $request = $request->withAttribute(RouteContext::ROUTE_PARSER, $this->routeParser); + + $routingResults = $this->resolveRoutingResultsFromRequest($request); + $routeStatus = $routingResults->getRouteStatus(); + + $request = $request->withAttribute(RouteContext::ROUTING_RESULTS, $routingResults); + + switch ($routeStatus) { + case RoutingResults::FOUND: + $routeArguments = $routingResults->getRouteArguments(); + $routeIdentifier = $routingResults->getRouteIdentifier() ?? ''; + $route = $this->routeResolver + ->resolveRoute($routeIdentifier) + ->prepare($routeArguments); + return $request->withAttribute(RouteContext::ROUTE, $route); + + case RoutingResults::NOT_FOUND: + throw new HttpNotFoundException($request); + + case RoutingResults::METHOD_NOT_ALLOWED: + $exception = new HttpMethodNotAllowedException($request); + $exception->setAllowedMethods($routingResults->getAllowedMethods()); + throw $exception; + + default: + throw new RuntimeException('An unexpected error occurred while performing routing.'); + } + } + + /** + * Resolves the route from the given request + */ + protected function resolveRoutingResultsFromRequest(ServerRequestInterface $request): RoutingResults + { + return $this->routeResolver->computeRoutingResults( + $request->getUri()->getPath(), + $request->getMethod() + ); + } +} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/MiddlewareAwareTrait.php b/advancedcontentfilter/vendor/slim/slim/Slim/MiddlewareAwareTrait.php deleted file mode 100644 index 8b8a1755d..000000000 --- a/advancedcontentfilter/vendor/slim/slim/Slim/MiddlewareAwareTrait.php +++ /dev/null @@ -1,121 +0,0 @@ -middlewareLock) { - throw new RuntimeException('Middleware can’t be added once the stack is dequeuing'); - } - - if (is_null($this->tip)) { - $this->seedMiddlewareStack(); - } - $next = $this->tip; - $this->tip = function ( - ServerRequestInterface $request, - ResponseInterface $response - ) use ( - $callable, - $next - ) { - $result = call_user_func($callable, $request, $response, $next); - if ($result instanceof ResponseInterface === false) { - throw new UnexpectedValueException( - 'Middleware must return instance of \Psr\Http\Message\ResponseInterface' - ); - } - - return $result; - }; - - return $this; - } - - /** - * Seed middleware stack with first callable - * - * @param callable $kernel The last item to run as middleware - * - * @throws RuntimeException if the stack is seeded more than once - */ - protected function seedMiddlewareStack(callable $kernel = null) - { - if (!is_null($this->tip)) { - throw new RuntimeException('MiddlewareStack can only be seeded once.'); - } - if ($kernel === null) { - $kernel = $this; - } - $this->tip = $kernel; - } - - /** - * Call middleware stack - * - * @param ServerRequestInterface $request A request object - * @param ResponseInterface $response A response object - * - * @return ResponseInterface - */ - public function callMiddlewareStack(ServerRequestInterface $request, ResponseInterface $response) - { - if (is_null($this->tip)) { - $this->seedMiddlewareStack(); - } - /** @var callable $start */ - $start = $this->tip; - $this->middlewareLock = true; - $response = $start($request, $response); - $this->middlewareLock = false; - return $response; - } -} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/MiddlewareDispatcher.php b/advancedcontentfilter/vendor/slim/slim/Slim/MiddlewareDispatcher.php new file mode 100644 index 000000000..7e0564414 --- /dev/null +++ b/advancedcontentfilter/vendor/slim/slim/Slim/MiddlewareDispatcher.php @@ -0,0 +1,275 @@ +seedMiddlewareStack($kernel); + $this->callableResolver = $callableResolver; + $this->container = $container; + } + + /** + * {@inheritdoc} + */ + public function seedMiddlewareStack(RequestHandlerInterface $kernel): void + { + $this->tip = $kernel; + } + + /** + * Invoke the middleware stack + */ + public function handle(ServerRequestInterface $request): ResponseInterface + { + return $this->tip->handle($request); + } + + /** + * Add a new middleware to the stack + * + * Middleware are organized as a stack. That means middleware + * that have been added before will be executed after the newly + * added one (last in, first out). + * + * @param MiddlewareInterface|string|callable $middleware + */ + public function add($middleware): MiddlewareDispatcherInterface + { + if ($middleware instanceof MiddlewareInterface) { + return $this->addMiddleware($middleware); + } + + if (is_string($middleware)) { + return $this->addDeferred($middleware); + } + + if (is_callable($middleware)) { + return $this->addCallable($middleware); + } + + /** @phpstan-ignore-next-line */ + throw new RuntimeException( + 'A middleware must be an object/class name referencing an implementation of ' . + 'MiddlewareInterface or a callable with a matching signature.' + ); + } + + /** + * Add a new middleware to the stack + * + * Middleware are organized as a stack. That means middleware + * that have been added before will be executed after the newly + * added one (last in, first out). + */ + public function addMiddleware(MiddlewareInterface $middleware): MiddlewareDispatcherInterface + { + $next = $this->tip; + $this->tip = new class ($middleware, $next) implements RequestHandlerInterface { + private MiddlewareInterface $middleware; + + private RequestHandlerInterface $next; + + public function __construct(MiddlewareInterface $middleware, RequestHandlerInterface $next) + { + $this->middleware = $middleware; + $this->next = $next; + } + + public function handle(ServerRequestInterface $request): ResponseInterface + { + return $this->middleware->process($request, $this->next); + } + }; + + return $this; + } + + /** + * Add a new middleware by class name + * + * Middleware are organized as a stack. That means middleware + * that have been added before will be executed after the newly + * added one (last in, first out). + */ + public function addDeferred(string $middleware): self + { + $next = $this->tip; + $this->tip = new class ( + $middleware, + $next, + $this->container, + $this->callableResolver + ) implements RequestHandlerInterface { + private string $middleware; + + private RequestHandlerInterface $next; + + private ?ContainerInterface $container; + + private ?CallableResolverInterface $callableResolver; + + public function __construct( + string $middleware, + RequestHandlerInterface $next, + ?ContainerInterface $container = null, + ?CallableResolverInterface $callableResolver = null + ) { + $this->middleware = $middleware; + $this->next = $next; + $this->container = $container; + $this->callableResolver = $callableResolver; + } + + public function handle(ServerRequestInterface $request): ResponseInterface + { + if ($this->callableResolver instanceof AdvancedCallableResolverInterface) { + $callable = $this->callableResolver->resolveMiddleware($this->middleware); + return $callable($request, $this->next); + } + + $callable = null; + + if ($this->callableResolver instanceof CallableResolverInterface) { + try { + $callable = $this->callableResolver->resolve($this->middleware); + } catch (RuntimeException $e) { + // Do Nothing + } + } + + if (!$callable) { + $resolved = $this->middleware; + $instance = null; + $method = null; + + // Check for Slim callable as `class:method` + if (preg_match(CallableResolver::$callablePattern, $resolved, $matches)) { + $resolved = $matches[1]; + $method = $matches[2]; + } + + if ($this->container && $this->container->has($resolved)) { + $instance = $this->container->get($resolved); + if ($instance instanceof MiddlewareInterface) { + return $instance->process($request, $this->next); + } + } elseif (!function_exists($resolved)) { + if (!class_exists($resolved)) { + throw new RuntimeException(sprintf('Middleware %s does not exist', $resolved)); + } + $instance = new $resolved($this->container); + } + + if ($instance && $instance instanceof MiddlewareInterface) { + return $instance->process($request, $this->next); + } + + $callable = $instance ?? $resolved; + if ($instance && $method) { + $callable = [$instance, $method]; + } + + if ($this->container && $callable instanceof Closure) { + $callable = $callable->bindTo($this->container); + } + } + + if (!is_callable($callable)) { + throw new RuntimeException( + sprintf( + 'Middleware %s is not resolvable', + $this->middleware + ) + ); + } + + return $callable($request, $this->next); + } + }; + + return $this; + } + + /** + * Add a (non-standard) callable middleware to the stack + * + * Middleware are organized as a stack. That means middleware + * that have been added before will be executed after the newly + * added one (last in, first out). + */ + public function addCallable(callable $middleware): self + { + $next = $this->tip; + + if ($this->container && $middleware instanceof Closure) { + /** @var Closure $middleware */ + $middleware = $middleware->bindTo($this->container); + } + + $this->tip = new class ($middleware, $next) implements RequestHandlerInterface { + /** + * @var callable + */ + private $middleware; + + /** + * @var RequestHandlerInterface + */ + private $next; + + public function __construct(callable $middleware, RequestHandlerInterface $next) + { + $this->middleware = $middleware; + $this->next = $next; + } + + public function handle(ServerRequestInterface $request): ResponseInterface + { + return ($this->middleware)($request, $this->next); + } + }; + + return $this; + } +} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/ResponseEmitter.php b/advancedcontentfilter/vendor/slim/slim/Slim/ResponseEmitter.php new file mode 100644 index 000000000..fac36e9e7 --- /dev/null +++ b/advancedcontentfilter/vendor/slim/slim/Slim/ResponseEmitter.php @@ -0,0 +1,136 @@ +responseChunkSize = $responseChunkSize; + } + + /** + * Send the response the client + */ + public function emit(ResponseInterface $response): void + { + $isEmpty = $this->isResponseEmpty($response); + if (headers_sent() === false) { + $this->emitHeaders($response); + + // Set the status _after_ the headers, because of PHP's "helpful" behavior with location headers. + // See https://github.com/slimphp/Slim/issues/1730 + + $this->emitStatusLine($response); + } + + if (!$isEmpty) { + $this->emitBody($response); + } + } + + /** + * Emit Response Headers + */ + private function emitHeaders(ResponseInterface $response): void + { + foreach ($response->getHeaders() as $name => $values) { + $first = strtolower($name) !== 'set-cookie'; + foreach ($values as $value) { + $header = sprintf('%s: %s', $name, $value); + header($header, $first); + $first = false; + } + } + } + + /** + * Emit Status Line + */ + private function emitStatusLine(ResponseInterface $response): void + { + $statusLine = sprintf( + 'HTTP/%s %s %s', + $response->getProtocolVersion(), + $response->getStatusCode(), + $response->getReasonPhrase() + ); + header($statusLine, true, $response->getStatusCode()); + } + + /** + * Emit Body + */ + private function emitBody(ResponseInterface $response): void + { + $body = $response->getBody(); + if ($body->isSeekable()) { + $body->rewind(); + } + + $amountToRead = (int) $response->getHeaderLine('Content-Length'); + if (!$amountToRead) { + $amountToRead = $body->getSize(); + } + + if ($amountToRead) { + while ($amountToRead > 0 && !$body->eof()) { + $length = min($this->responseChunkSize, $amountToRead); + $data = $body->read($length); + echo $data; + + $amountToRead -= strlen($data); + + if (connection_status() !== CONNECTION_NORMAL) { + break; + } + } + } else { + while (!$body->eof()) { + echo $body->read($this->responseChunkSize); + if (connection_status() !== CONNECTION_NORMAL) { + break; + } + } + } + } + + /** + * Asserts response body is empty or status code is 204, 205 or 304 + */ + public function isResponseEmpty(ResponseInterface $response): bool + { + if (in_array($response->getStatusCode(), [204, 205, 304], true)) { + return true; + } + $stream = $response->getBody(); + $seekable = $stream->isSeekable(); + if ($seekable) { + $stream->rewind(); + } + return $seekable ? $stream->read(1) === '' : $stream->eof(); + } +} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Routable.php b/advancedcontentfilter/vendor/slim/slim/Slim/Routable.php deleted file mode 100644 index c912db433..000000000 --- a/advancedcontentfilter/vendor/slim/slim/Slim/Routable.php +++ /dev/null @@ -1,106 +0,0 @@ -middleware; - } - - /** - * Get the route pattern - * - * @return string - */ - public function getPattern() - { - return $this->pattern; - } - - /** - * Set container for use with resolveCallable - * - * @param ContainerInterface $container - * - * @return self - */ - public function setContainer(ContainerInterface $container) - { - $this->container = $container; - return $this; - } - - /** - * Prepend middleware to the middleware collection - * - * @param callable|string $callable The callback routine - * - * @return static - */ - public function add($callable) - { - $this->middleware[] = new DeferredCallable($callable, $this->container); - return $this; - } - - /** - * Set the route pattern - * - * @param string $newPattern - */ - public function setPattern($newPattern) - { - $this->pattern = $newPattern; - } -} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Route.php b/advancedcontentfilter/vendor/slim/slim/Slim/Route.php deleted file mode 100644 index fa8be4e44..000000000 --- a/advancedcontentfilter/vendor/slim/slim/Slim/Route.php +++ /dev/null @@ -1,349 +0,0 @@ -methods = is_string($methods) ? [$methods] : $methods; - $this->pattern = $pattern; - $this->callable = $callable; - $this->groups = $groups; - $this->identifier = 'route' . $identifier; - } - - /** - * Finalize the route in preparation for dispatching - */ - public function finalize() - { - if ($this->finalized) { - return; - } - - $groupMiddleware = []; - foreach ($this->getGroups() as $group) { - $groupMiddleware = array_merge($group->getMiddleware(), $groupMiddleware); - } - - $this->middleware = array_merge($this->middleware, $groupMiddleware); - - foreach ($this->getMiddleware() as $middleware) { - $this->addMiddleware($middleware); - } - - $this->finalized = true; - } - - /** - * Get route callable - * - * @return callable - */ - public function getCallable() - { - return $this->callable; - } - - /** - * This method enables you to override the Route's callable - * - * @param string|\Closure $callable - */ - public function setCallable($callable) - { - $this->callable = $callable; - } - - /** - * Get route methods - * - * @return string[] - */ - public function getMethods() - { - return $this->methods; - } - - /** - * Get parent route groups - * - * @return RouteGroup[] - */ - public function getGroups() - { - return $this->groups; - } - - /** - * Get route name - * - * @return null|string - */ - public function getName() - { - return $this->name; - } - - /** - * Get route identifier - * - * @return string - */ - public function getIdentifier() - { - return $this->identifier; - } - - /** - * Get output buffering mode - * - * @return boolean|string - */ - public function getOutputBuffering() - { - return $this->outputBuffering; - } - - /** - * Set output buffering mode - * - * One of: false, 'prepend' or 'append' - * - * @param boolean|string $mode - * - * @throws InvalidArgumentException If an unknown buffering mode is specified - */ - public function setOutputBuffering($mode) - { - if (!in_array($mode, [false, 'prepend', 'append'], true)) { - throw new InvalidArgumentException('Unknown output buffering mode'); - } - $this->outputBuffering = $mode; - } - - /** - * Set route name - * - * @param string $name - * - * @return self - * - * @throws InvalidArgumentException if the route name is not a string - */ - public function setName($name) - { - if (!is_string($name)) { - throw new InvalidArgumentException('Route name must be a string'); - } - $this->name = $name; - return $this; - } - - /** - * Set a route argument - * - * @param string $name - * @param string $value - * - * @return self - */ - public function setArgument($name, $value) - { - $this->arguments[$name] = $value; - return $this; - } - - /** - * Replace route arguments - * - * @param array $arguments - * - * @return self - */ - public function setArguments(array $arguments) - { - $this->arguments = $arguments; - return $this; - } - - /** - * Retrieve route arguments - * - * @return array - */ - public function getArguments() - { - return $this->arguments; - } - - /** - * Retrieve a specific route argument - * - * @param string $name - * @param string|null $default - * - * @return mixed - */ - public function getArgument($name, $default = null) - { - if (array_key_exists($name, $this->arguments)) { - return $this->arguments[$name]; - } - return $default; - } - - /******************************************************************************** - * Route Runner - *******************************************************************************/ - - /** - * Prepare the route for use - * - * @param ServerRequestInterface $request - * @param array $arguments - */ - public function prepare(ServerRequestInterface $request, array $arguments) - { - // Add the arguments - foreach ($arguments as $k => $v) { - $this->setArgument($k, $v); - } - } - - /** - * Run route - * - * This method traverses the middleware stack, including the route's callable - * and captures the resultant HTTP response object. It then sends the response - * back to the Application. - * - * @param ServerRequestInterface $request - * @param ResponseInterface $response - * - * @return ResponseInterface - */ - public function run(ServerRequestInterface $request, ResponseInterface $response) - { - // Finalise route now that we are about to run it - $this->finalize(); - - // Traverse middleware stack and fetch updated response - return $this->callMiddlewareStack($request, $response); - } - - /** - * Dispatch route callable against current Request and Response objects - * - * This method invokes the route object's callable. If middleware is - * registered for the route, each callable middleware is invoked in - * the order specified. - * - * @param ServerRequestInterface $request The current Request object - * @param ResponseInterface $response The current Response object - * @return \Psr\Http\Message\ResponseInterface - * @throws \Exception if the route callable throws an exception - */ - public function __invoke(ServerRequestInterface $request, ResponseInterface $response) - { - $this->callable = $this->resolveCallable($this->callable); - - /** @var InvocationStrategyInterface $handler */ - $handler = isset($this->container) ? $this->container->get('foundHandler') : new RequestResponse(); - - $newResponse = $handler($this->callable, $request, $response, $this->arguments); - - if ($newResponse instanceof ResponseInterface) { - // if route callback returns a ResponseInterface, then use it - $response = $newResponse; - } elseif (is_string($newResponse)) { - // if route callback returns a string, then append it to the response - if ($response->getBody()->isWritable()) { - $response->getBody()->write($newResponse); - } - } - - return $response; - } -} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/RouteGroup.php b/advancedcontentfilter/vendor/slim/slim/Slim/RouteGroup.php deleted file mode 100644 index 8260bbd6c..000000000 --- a/advancedcontentfilter/vendor/slim/slim/Slim/RouteGroup.php +++ /dev/null @@ -1,47 +0,0 @@ -pattern = $pattern; - $this->callable = $callable; - } - - /** - * Invoke the group to register any Routable objects within it. - * - * @param App $app The App instance to bind/pass to the group callable - */ - public function __invoke(App $app = null) - { - $callable = $this->resolveCallable($this->callable); - if ($callable instanceof Closure && $app !== null) { - $callable = $callable->bindTo($app); - } - - $callable($app); - } -} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Router.php b/advancedcontentfilter/vendor/slim/slim/Slim/Router.php deleted file mode 100644 index 83116288c..000000000 --- a/advancedcontentfilter/vendor/slim/slim/Slim/Router.php +++ /dev/null @@ -1,455 +0,0 @@ -routeParser = $parser ?: new StdParser; - } - - /** - * Set the base path used in pathFor() - * - * @param string $basePath - * - * @return self - */ - public function setBasePath($basePath) - { - if (!is_string($basePath)) { - throw new InvalidArgumentException('Router basePath must be a string'); - } - - $this->basePath = $basePath; - - return $this; - } - - /** - * Set path to fast route cache file. If this is false then route caching is disabled. - * - * @param string|false $cacheFile - * - * @return self - */ - public function setCacheFile($cacheFile) - { - if (!is_string($cacheFile) && $cacheFile !== false) { - throw new InvalidArgumentException('Router cacheFile must be a string or false'); - } - - $this->cacheFile = $cacheFile; - - if ($cacheFile !== false && !is_writable(dirname($cacheFile))) { - throw new RuntimeException('Router cacheFile directory must be writable'); - } - - - return $this; - } - - /** - * @param ContainerInterface $container - */ - public function setContainer(ContainerInterface $container) - { - $this->container = $container; - } - - /** - * Add route - * - * @param string[] $methods Array of HTTP methods - * @param string $pattern The route pattern - * @param callable $handler The route callable - * - * @return RouteInterface - * - * @throws InvalidArgumentException if the route pattern isn't a string - */ - public function map($methods, $pattern, $handler) - { - if (!is_string($pattern)) { - throw new InvalidArgumentException('Route pattern must be a string'); - } - - // Prepend parent group pattern(s) - if ($this->routeGroups) { - $pattern = $this->processGroups() . $pattern; - } - - // According to RFC methods are defined in uppercase (See RFC 7231) - $methods = array_map("strtoupper", $methods); - - // Add route - $route = $this->createRoute($methods, $pattern, $handler); - $this->routes[$route->getIdentifier()] = $route; - $this->routeCounter++; - - return $route; - } - - /** - * Dispatch router for HTTP request - * - * @param ServerRequestInterface $request The current HTTP request object - * - * @return array - * - * @link https://github.com/nikic/FastRoute/blob/master/src/Dispatcher.php - */ - public function dispatch(ServerRequestInterface $request) - { - $uri = '/' . ltrim($request->getUri()->getPath(), '/'); - - return $this->createDispatcher()->dispatch( - $request->getMethod(), - $uri - ); - } - - /** - * Create a new Route object - * - * @param string[] $methods Array of HTTP methods - * @param string $pattern The route pattern - * @param callable $callable The route callable - * - * @return \Slim\Interfaces\RouteInterface - */ - protected function createRoute($methods, $pattern, $callable) - { - $route = new Route($methods, $pattern, $callable, $this->routeGroups, $this->routeCounter); - if (!empty($this->container)) { - $route->setContainer($this->container); - } - - return $route; - } - - /** - * @return \FastRoute\Dispatcher - */ - protected function createDispatcher() - { - if ($this->dispatcher) { - return $this->dispatcher; - } - - $routeDefinitionCallback = function (RouteCollector $r) { - foreach ($this->getRoutes() as $route) { - $r->addRoute($route->getMethods(), $route->getPattern(), $route->getIdentifier()); - } - }; - - if ($this->cacheFile) { - $this->dispatcher = \FastRoute\cachedDispatcher($routeDefinitionCallback, [ - 'routeParser' => $this->routeParser, - 'cacheFile' => $this->cacheFile, - ]); - } else { - $this->dispatcher = \FastRoute\simpleDispatcher($routeDefinitionCallback, [ - 'routeParser' => $this->routeParser, - ]); - } - - return $this->dispatcher; - } - - /** - * @param \FastRoute\Dispatcher $dispatcher - */ - public function setDispatcher(Dispatcher $dispatcher) - { - $this->dispatcher = $dispatcher; - } - - /** - * Get route objects - * - * @return Route[] - */ - public function getRoutes() - { - return $this->routes; - } - - /** - * Get named route object - * - * @param string $name Route name - * - * @return Route - * - * @throws RuntimeException If named route does not exist - */ - public function getNamedRoute($name) - { - foreach ($this->routes as $route) { - if ($name == $route->getName()) { - return $route; - } - } - throw new RuntimeException('Named route does not exist for name: ' . $name); - } - - /** - * Remove named route - * - * @param string $name Route name - * - * @throws RuntimeException If named route does not exist - */ - public function removeNamedRoute($name) - { - $route = $this->getNamedRoute($name); - - // no exception, route exists, now remove by id - unset($this->routes[$route->getIdentifier()]); - } - - /** - * Process route groups - * - * @return string A group pattern to prefix routes with - */ - protected function processGroups() - { - $pattern = ""; - foreach ($this->routeGroups as $group) { - $pattern .= $group->getPattern(); - } - return $pattern; - } - - /** - * Add a route group to the array - * - * @param string $pattern - * @param callable $callable - * - * @return RouteGroupInterface - */ - public function pushGroup($pattern, $callable) - { - $group = new RouteGroup($pattern, $callable); - array_push($this->routeGroups, $group); - return $group; - } - - /** - * Removes the last route group from the array - * - * @return RouteGroup|bool The RouteGroup if successful, else False - */ - public function popGroup() - { - $group = array_pop($this->routeGroups); - return $group instanceof RouteGroup ? $group : false; - } - - /** - * @param $identifier - * @return \Slim\Interfaces\RouteInterface - */ - public function lookupRoute($identifier) - { - if (!isset($this->routes[$identifier])) { - throw new RuntimeException('Route not found, looks like your route cache is stale.'); - } - return $this->routes[$identifier]; - } - - /** - * Build the path for a named route excluding the base path - * - * @param string $name Route name - * @param array $data Named argument replacement data - * @param array $queryParams Optional query string parameters - * - * @return string - * - * @throws RuntimeException If named route does not exist - * @throws InvalidArgumentException If required data not provided - */ - public function relativePathFor($name, array $data = [], array $queryParams = []) - { - $route = $this->getNamedRoute($name); - $pattern = $route->getPattern(); - - $routeDatas = $this->routeParser->parse($pattern); - // $routeDatas is an array of all possible routes that can be made. There is - // one routedata for each optional parameter plus one for no optional parameters. - // - // The most specific is last, so we look for that first. - $routeDatas = array_reverse($routeDatas); - - $segments = []; - foreach ($routeDatas as $routeData) { - foreach ($routeData as $item) { - if (is_string($item)) { - // this segment is a static string - $segments[] = $item; - continue; - } - - // This segment has a parameter: first element is the name - if (!array_key_exists($item[0], $data)) { - // we don't have a data element for this segment: cancel - // testing this routeData item, so that we can try a less - // specific routeData item. - $segments = []; - $segmentName = $item[0]; - break; - } - $segments[] = $data[$item[0]]; - } - if (!empty($segments)) { - // we found all the parameters for this route data, no need to check - // less specific ones - break; - } - } - - if (empty($segments)) { - throw new InvalidArgumentException('Missing data for URL segment: ' . $segmentName); - } - $url = implode('', $segments); - - if ($queryParams) { - $url .= '?' . http_build_query($queryParams); - } - - return $url; - } - - - /** - * Build the path for a named route including the base path - * - * @param string $name Route name - * @param array $data Named argument replacement data - * @param array $queryParams Optional query string parameters - * - * @return string - * - * @throws RuntimeException If named route does not exist - * @throws InvalidArgumentException If required data not provided - */ - public function pathFor($name, array $data = [], array $queryParams = []) - { - $url = $this->relativePathFor($name, $data, $queryParams); - - if ($this->basePath) { - $url = $this->basePath . $url; - } - - return $url; - } - - /** - * Build the path for a named route. - * - * This method is deprecated. Use pathFor() from now on. - * - * @param string $name Route name - * @param array $data Named argument replacement data - * @param array $queryParams Optional query string parameters - * - * @return string - * - * @throws RuntimeException If named route does not exist - * @throws InvalidArgumentException If required data not provided - */ - public function urlFor($name, array $data = [], array $queryParams = []) - { - trigger_error('urlFor() is deprecated. Use pathFor() instead.', E_USER_DEPRECATED); - return $this->pathFor($name, $data, $queryParams); - } -} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Routing/Dispatcher.php b/advancedcontentfilter/vendor/slim/slim/Slim/Routing/Dispatcher.php new file mode 100644 index 000000000..e33eac396 --- /dev/null +++ b/advancedcontentfilter/vendor/slim/slim/Slim/Routing/Dispatcher.php @@ -0,0 +1,78 @@ +routeCollector = $routeCollector; + } + + protected function createDispatcher(): FastRouteDispatcher + { + if ($this->dispatcher) { + return $this->dispatcher; + } + + $routeDefinitionCallback = function (FastRouteCollector $r): void { + $basePath = $this->routeCollector->getBasePath(); + + foreach ($this->routeCollector->getRoutes() as $route) { + $r->addRoute($route->getMethods(), $basePath . $route->getPattern(), $route->getIdentifier()); + } + }; + + $cacheFile = $this->routeCollector->getCacheFile(); + if ($cacheFile) { + /** @var FastRouteDispatcher $dispatcher */ + $dispatcher = \FastRoute\cachedDispatcher($routeDefinitionCallback, [ + 'dataGenerator' => GroupCountBased::class, + 'dispatcher' => FastRouteDispatcher::class, + 'routeParser' => new Std(), + 'cacheFile' => $cacheFile, + ]); + } else { + /** @var FastRouteDispatcher $dispatcher */ + $dispatcher = \FastRoute\simpleDispatcher($routeDefinitionCallback, [ + 'dataGenerator' => GroupCountBased::class, + 'dispatcher' => FastRouteDispatcher::class, + 'routeParser' => new Std(), + ]); + } + + $this->dispatcher = $dispatcher; + return $this->dispatcher; + } + + /** + * {@inheritdoc} + */ + public function dispatch(string $method, string $uri): RoutingResults + { + $dispatcher = $this->createDispatcher(); + $results = $dispatcher->dispatch($method, $uri); + return new RoutingResults($this, $method, $uri, $results[0], $results[1], $results[2]); + } + + /** + * {@inheritdoc} + */ + public function getAllowedMethods(string $uri): array + { + $dispatcher = $this->createDispatcher(); + return $dispatcher->getAllowedMethods($uri); + } +} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Routing/FastRouteDispatcher.php b/advancedcontentfilter/vendor/slim/slim/Slim/Routing/FastRouteDispatcher.php new file mode 100644 index 000000000..797746bbb --- /dev/null +++ b/advancedcontentfilter/vendor/slim/slim/Slim/Routing/FastRouteDispatcher.php @@ -0,0 +1,109 @@ +} + */ + public function dispatch($httpMethod, $uri): array + { + $routingResults = $this->routingResults($httpMethod, $uri); + if ($routingResults[0] === self::FOUND) { + return $routingResults; + } + + // For HEAD requests, attempt fallback to GET + if ($httpMethod === 'HEAD') { + $routingResults = $this->routingResults('GET', $uri); + if ($routingResults[0] === self::FOUND) { + return $routingResults; + } + } + + // If nothing else matches, try fallback routes + $routingResults = $this->routingResults('*', $uri); + if ($routingResults[0] === self::FOUND) { + return $routingResults; + } + + if (!empty($this->getAllowedMethods($uri))) { + return [self::METHOD_NOT_ALLOWED, null, []]; + } + + return [self::NOT_FOUND, null, []]; + } + + /** + * @param string $httpMethod + * @param string $uri + * + * @return array{int, string|null, array} + */ + private function routingResults(string $httpMethod, string $uri): array + { + if (isset($this->staticRouteMap[$httpMethod][$uri])) { + /** @var string $routeIdentifier */ + $routeIdentifier = $this->staticRouteMap[$httpMethod][$uri]; + return [self::FOUND, $routeIdentifier, []]; + } + + if (isset($this->variableRouteData[$httpMethod])) { + /** @var array{0: int, 1?: string, 2?: array} $result */ + $result = $this->dispatchVariableRoute($this->variableRouteData[$httpMethod], $uri); + if ($result[0] === self::FOUND) { + /** @var array{int, string, array} $result */ + return [self::FOUND, $result[1], $result[2]]; + } + } + + return [self::NOT_FOUND, null, []]; + } + + /** + * @param string $uri + * + * @return string[] + */ + public function getAllowedMethods(string $uri): array + { + if (isset($this->allowedMethods[$uri])) { + return $this->allowedMethods[$uri]; + } + + $allowedMethods = []; + foreach ($this->staticRouteMap as $method => $uriMap) { + if (isset($uriMap[$uri])) { + $allowedMethods[$method] = true; + } + } + + foreach ($this->variableRouteData as $method => $routeData) { + $result = $this->dispatchVariableRoute($routeData, $uri); + if ($result[0] === self::FOUND) { + $allowedMethods[$method] = true; + } + } + + return $this->allowedMethods[$uri] = array_keys($allowedMethods); + } +} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Routing/Route.php b/advancedcontentfilter/vendor/slim/slim/Slim/Routing/Route.php new file mode 100644 index 000000000..2cd9fa567 --- /dev/null +++ b/advancedcontentfilter/vendor/slim/slim/Slim/Routing/Route.php @@ -0,0 +1,360 @@ + + */ + protected array $arguments = []; + + /** + * Route arguments parameters + * + * @var string[] + */ + protected array $savedArguments = []; + + /** + * Container + */ + protected ?ContainerInterface $container = null; + + protected MiddlewareDispatcher $middlewareDispatcher; + + /** + * Route callable + * + * @var callable|string + */ + protected $callable; + + protected CallableResolverInterface $callableResolver; + + protected ResponseFactoryInterface $responseFactory; + + /** + * Route pattern + */ + protected string $pattern; + + protected bool $groupMiddlewareAppended = false; + + /** + * @param string[] $methods The route HTTP methods + * @param string $pattern The route pattern + * @param callable|string $callable The route callable + * @param ResponseFactoryInterface $responseFactory + * @param CallableResolverInterface $callableResolver + * @param ContainerInterface|null $container + * @param InvocationStrategyInterface|null $invocationStrategy + * @param RouteGroupInterface[] $groups The parent route groups + * @param int $identifier The route identifier + */ + public function __construct( + array $methods, + string $pattern, + $callable, + ResponseFactoryInterface $responseFactory, + CallableResolverInterface $callableResolver, + ?ContainerInterface $container = null, + ?InvocationStrategyInterface $invocationStrategy = null, + array $groups = [], + int $identifier = 0 + ) { + $this->methods = $methods; + $this->pattern = $pattern; + $this->callable = $callable; + $this->responseFactory = $responseFactory; + $this->callableResolver = $callableResolver; + $this->container = $container; + $this->invocationStrategy = $invocationStrategy ?? new RequestResponse(); + $this->groups = $groups; + $this->identifier = 'route' . $identifier; + $this->middlewareDispatcher = new MiddlewareDispatcher($this, $callableResolver, $container); + } + + public function getCallableResolver(): CallableResolverInterface + { + return $this->callableResolver; + } + + /** + * {@inheritdoc} + */ + public function getInvocationStrategy(): InvocationStrategyInterface + { + return $this->invocationStrategy; + } + + /** + * {@inheritdoc} + */ + public function setInvocationStrategy(InvocationStrategyInterface $invocationStrategy): RouteInterface + { + $this->invocationStrategy = $invocationStrategy; + return $this; + } + + /** + * {@inheritdoc} + */ + public function getMethods(): array + { + return $this->methods; + } + + /** + * {@inheritdoc} + */ + public function getPattern(): string + { + return $this->pattern; + } + + /** + * {@inheritdoc} + */ + public function setPattern(string $pattern): RouteInterface + { + $this->pattern = $pattern; + return $this; + } + + /** + * {@inheritdoc} + */ + public function getCallable() + { + return $this->callable; + } + + /** + * {@inheritdoc} + */ + public function setCallable($callable): RouteInterface + { + $this->callable = $callable; + return $this; + } + + /** + * {@inheritdoc} + */ + public function getName(): ?string + { + return $this->name; + } + + /** + * {@inheritdoc} + */ + public function setName(string $name): RouteInterface + { + $this->name = $name; + return $this; + } + + /** + * {@inheritdoc} + */ + public function getIdentifier(): string + { + return $this->identifier; + } + + /** + * {@inheritdoc} + */ + public function getArgument(string $name, ?string $default = null): ?string + { + if (array_key_exists($name, $this->arguments)) { + return $this->arguments[$name]; + } + return $default; + } + + /** + * {@inheritdoc} + */ + public function getArguments(): array + { + return $this->arguments; + } + + /** + * {@inheritdoc} + */ + public function setArguments(array $arguments, bool $includeInSavedArguments = true): RouteInterface + { + if ($includeInSavedArguments) { + $this->savedArguments = $arguments; + } + + $this->arguments = $arguments; + return $this; + } + + /** + * @return RouteGroupInterface[] + */ + public function getGroups(): array + { + return $this->groups; + } + + /** + * {@inheritdoc} + */ + public function add($middleware): RouteInterface + { + $this->middlewareDispatcher->add($middleware); + return $this; + } + + /** + * {@inheritdoc} + */ + public function addMiddleware(MiddlewareInterface $middleware): RouteInterface + { + $this->middlewareDispatcher->addMiddleware($middleware); + return $this; + } + + /** + * {@inheritdoc} + */ + public function prepare(array $arguments): RouteInterface + { + $this->arguments = array_replace($this->savedArguments, $arguments); + return $this; + } + + /** + * {@inheritdoc} + */ + public function setArgument(string $name, string $value, bool $includeInSavedArguments = true): RouteInterface + { + if ($includeInSavedArguments) { + $this->savedArguments[$name] = $value; + } + + $this->arguments[$name] = $value; + return $this; + } + + /** + * {@inheritdoc} + */ + public function run(ServerRequestInterface $request): ResponseInterface + { + if (!$this->groupMiddlewareAppended) { + $this->appendGroupMiddlewareToRoute(); + } + + return $this->middlewareDispatcher->handle($request); + } + + /** + * @return void + */ + protected function appendGroupMiddlewareToRoute(): void + { + $inner = $this->middlewareDispatcher; + $this->middlewareDispatcher = new MiddlewareDispatcher($inner, $this->callableResolver, $this->container); + + /** @var RouteGroupInterface $group */ + foreach (array_reverse($this->groups) as $group) { + $group->appendMiddlewareToDispatcher($this->middlewareDispatcher); + } + + $this->groupMiddlewareAppended = true; + } + + /** + * {@inheritdoc} + */ + public function handle(ServerRequestInterface $request): ResponseInterface + { + if ($this->callableResolver instanceof AdvancedCallableResolverInterface) { + $callable = $this->callableResolver->resolveRoute($this->callable); + } else { + $callable = $this->callableResolver->resolve($this->callable); + } + $strategy = $this->invocationStrategy; + + /** @var string[] $strategyImplements */ + $strategyImplements = class_implements($strategy); + + if ( + is_array($callable) + && $callable[0] instanceof RequestHandlerInterface + && !in_array(RequestHandlerInvocationStrategyInterface::class, $strategyImplements) + ) { + $strategy = new RequestHandler(); + } + + $response = $this->responseFactory->createResponse(); + return $strategy($callable, $request, $response, $this->arguments); + } +} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Routing/RouteCollector.php b/advancedcontentfilter/vendor/slim/slim/Slim/Routing/RouteCollector.php new file mode 100644 index 000000000..61b450300 --- /dev/null +++ b/advancedcontentfilter/vendor/slim/slim/Slim/Routing/RouteCollector.php @@ -0,0 +1,293 @@ +responseFactory = $responseFactory; + $this->callableResolver = $callableResolver; + $this->container = $container; + $this->defaultInvocationStrategy = $defaultInvocationStrategy ?? new RequestResponse(); + $this->routeParser = $routeParser ?? new RouteParser($this); + + if ($cacheFile) { + $this->setCacheFile($cacheFile); + } + } + + public function getRouteParser(): RouteParserInterface + { + return $this->routeParser; + } + + /** + * Get default route invocation strategy + */ + public function getDefaultInvocationStrategy(): InvocationStrategyInterface + { + return $this->defaultInvocationStrategy; + } + + public function setDefaultInvocationStrategy(InvocationStrategyInterface $strategy): RouteCollectorInterface + { + $this->defaultInvocationStrategy = $strategy; + return $this; + } + + /** + * {@inheritdoc} + */ + public function getCacheFile(): ?string + { + return $this->cacheFile; + } + + /** + * {@inheritdoc} + */ + public function setCacheFile(string $cacheFile): RouteCollectorInterface + { + if (file_exists($cacheFile) && !is_readable($cacheFile)) { + throw new RuntimeException( + sprintf('Route collector cache file `%s` is not readable', $cacheFile) + ); + } + + if (!file_exists($cacheFile) && !is_writable(dirname($cacheFile))) { + throw new RuntimeException( + sprintf('Route collector cache file directory `%s` is not writable', dirname($cacheFile)) + ); + } + + $this->cacheFile = $cacheFile; + return $this; + } + + /** + * {@inheritdoc} + */ + public function getBasePath(): string + { + return $this->basePath; + } + + /** + * Set the base path used in urlFor() + */ + public function setBasePath(string $basePath): RouteCollectorInterface + { + $this->basePath = $basePath; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getRoutes(): array + { + return $this->routes; + } + + /** + * {@inheritdoc} + */ + public function removeNamedRoute(string $name): RouteCollectorInterface + { + $route = $this->getNamedRoute($name); + + unset($this->routesByName[$route->getName()], $this->routes[$route->getIdentifier()]); + return $this; + } + + /** + * {@inheritdoc} + */ + public function getNamedRoute(string $name): RouteInterface + { + if (isset($this->routesByName[$name])) { + $route = $this->routesByName[$name]; + if ($route->getName() === $name) { + return $route; + } + + unset($this->routesByName[$name]); + } + + foreach ($this->routes as $route) { + if ($name === $route->getName()) { + $this->routesByName[$name] = $route; + return $route; + } + } + + throw new RuntimeException('Named route does not exist for name: ' . $name); + } + + /** + * {@inheritdoc} + */ + public function lookupRoute(string $identifier): RouteInterface + { + if (!isset($this->routes[$identifier])) { + throw new RuntimeException('Route not found, looks like your route cache is stale.'); + } + return $this->routes[$identifier]; + } + + /** + * {@inheritdoc} + */ + public function group(string $pattern, $callable): RouteGroupInterface + { + $routeGroup = $this->createGroup($pattern, $callable); + $this->routeGroups[] = $routeGroup; + + $routeGroup->collectRoutes(); + array_pop($this->routeGroups); + + return $routeGroup; + } + + /** + * @param string|callable $callable + */ + protected function createGroup(string $pattern, $callable): RouteGroupInterface + { + $routeCollectorProxy = $this->createProxy($pattern); + return new RouteGroup($pattern, $callable, $this->callableResolver, $routeCollectorProxy); + } + + protected function createProxy(string $pattern): RouteCollectorProxyInterface + { + return new RouteCollectorProxy( + $this->responseFactory, + $this->callableResolver, + $this->container, + $this, + $pattern + ); + } + + /** + * {@inheritdoc} + */ + public function map(array $methods, string $pattern, $handler): RouteInterface + { + $route = $this->createRoute($methods, $pattern, $handler); + $this->routes[$route->getIdentifier()] = $route; + + $routeName = $route->getName(); + if ($routeName !== null && !isset($this->routesByName[$routeName])) { + $this->routesByName[$routeName] = $route; + } + + $this->routeCounter++; + + return $route; + } + + /** + * @param string[] $methods + * @param callable|string $callable + */ + protected function createRoute(array $methods, string $pattern, $callable): RouteInterface + { + return new Route( + $methods, + $pattern, + $callable, + $this->responseFactory, + $this->callableResolver, + $this->container, + $this->defaultInvocationStrategy, + $this->routeGroups, + $this->routeCounter + ); + } +} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Routing/RouteCollectorProxy.php b/advancedcontentfilter/vendor/slim/slim/Slim/Routing/RouteCollectorProxy.php new file mode 100644 index 000000000..f8bc232bc --- /dev/null +++ b/advancedcontentfilter/vendor/slim/slim/Slim/Routing/RouteCollectorProxy.php @@ -0,0 +1,187 @@ +responseFactory = $responseFactory; + $this->callableResolver = $callableResolver; + $this->container = $container; + $this->routeCollector = $routeCollector ?? new RouteCollector($responseFactory, $callableResolver, $container); + $this->groupPattern = $groupPattern; + } + + /** + * {@inheritdoc} + */ + public function getResponseFactory(): ResponseFactoryInterface + { + return $this->responseFactory; + } + + /** + * {@inheritdoc} + */ + public function getCallableResolver(): CallableResolverInterface + { + return $this->callableResolver; + } + + /** + * {@inheritdoc} + */ + public function getContainer(): ?ContainerInterface + { + return $this->container; + } + + /** + * {@inheritdoc} + */ + public function getRouteCollector(): RouteCollectorInterface + { + return $this->routeCollector; + } + + /** + * {@inheritdoc} + */ + public function getBasePath(): string + { + return $this->routeCollector->getBasePath(); + } + + /** + * {@inheritdoc} + */ + public function setBasePath(string $basePath): RouteCollectorProxyInterface + { + $this->routeCollector->setBasePath($basePath); + + return $this; + } + + /** + * {@inheritdoc} + */ + public function get(string $pattern, $callable): RouteInterface + { + return $this->map(['GET'], $pattern, $callable); + } + + /** + * {@inheritdoc} + */ + public function post(string $pattern, $callable): RouteInterface + { + return $this->map(['POST'], $pattern, $callable); + } + + /** + * {@inheritdoc} + */ + public function put(string $pattern, $callable): RouteInterface + { + return $this->map(['PUT'], $pattern, $callable); + } + + /** + * {@inheritdoc} + */ + public function patch(string $pattern, $callable): RouteInterface + { + return $this->map(['PATCH'], $pattern, $callable); + } + + /** + * {@inheritdoc} + */ + public function delete(string $pattern, $callable): RouteInterface + { + return $this->map(['DELETE'], $pattern, $callable); + } + + /** + * {@inheritdoc} + */ + public function options(string $pattern, $callable): RouteInterface + { + return $this->map(['OPTIONS'], $pattern, $callable); + } + + /** + * {@inheritdoc} + */ + public function any(string $pattern, $callable): RouteInterface + { + return $this->map(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'], $pattern, $callable); + } + + /** + * {@inheritdoc} + */ + public function map(array $methods, string $pattern, $callable): RouteInterface + { + $pattern = $this->groupPattern . $pattern; + + return $this->routeCollector->map($methods, $pattern, $callable); + } + + /** + * {@inheritdoc} + */ + public function group(string $pattern, $callable): RouteGroupInterface + { + $pattern = $this->groupPattern . $pattern; + + return $this->routeCollector->group($pattern, $callable); + } + + /** + * {@inheritdoc} + */ + public function redirect(string $from, $to, int $status = 302): RouteInterface + { + $responseFactory = $this->responseFactory; + + $handler = function () use ($to, $status, $responseFactory) { + $response = $responseFactory->createResponse($status); + return $response->withHeader('Location', (string) $to); + }; + + return $this->get($from, $handler); + } +} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Routing/RouteContext.php b/advancedcontentfilter/vendor/slim/slim/Slim/Routing/RouteContext.php new file mode 100644 index 000000000..3ba5e23a6 --- /dev/null +++ b/advancedcontentfilter/vendor/slim/slim/Slim/Routing/RouteContext.php @@ -0,0 +1,88 @@ +getAttribute(self::ROUTE); + $routeParser = $serverRequest->getAttribute(self::ROUTE_PARSER); + $routingResults = $serverRequest->getAttribute(self::ROUTING_RESULTS); + $basePath = $serverRequest->getAttribute(self::BASE_PATH); + + if ($routeParser === null || $routingResults === null) { + throw new RuntimeException('Cannot create RouteContext before routing has been completed'); + } + + /** @var RouteInterface|null $route */ + /** @var RouteParserInterface $routeParser */ + /** @var RoutingResults $routingResults */ + /** @var string|null $basePath */ + return new self($route, $routeParser, $routingResults, $basePath); + } + + private ?RouteInterface $route; + + private RouteParserInterface $routeParser; + + private RoutingResults $routingResults; + + private ?string $basePath; + + private function __construct( + ?RouteInterface $route, + RouteParserInterface $routeParser, + RoutingResults $routingResults, + ?string $basePath = null + ) { + $this->route = $route; + $this->routeParser = $routeParser; + $this->routingResults = $routingResults; + $this->basePath = $basePath; + } + + public function getRoute(): ?RouteInterface + { + return $this->route; + } + + public function getRouteParser(): RouteParserInterface + { + return $this->routeParser; + } + + public function getRoutingResults(): RoutingResults + { + return $this->routingResults; + } + + public function getBasePath(): string + { + if ($this->basePath === null) { + throw new RuntimeException('No base path defined.'); + } + return $this->basePath; + } +} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Routing/RouteGroup.php b/advancedcontentfilter/vendor/slim/slim/Slim/Routing/RouteGroup.php new file mode 100644 index 000000000..cd2f4e79a --- /dev/null +++ b/advancedcontentfilter/vendor/slim/slim/Slim/Routing/RouteGroup.php @@ -0,0 +1,104 @@ +pattern = $pattern; + $this->callable = $callable; + $this->callableResolver = $callableResolver; + $this->routeCollectorProxy = $routeCollectorProxy; + } + + /** + * {@inheritdoc} + */ + public function collectRoutes(): RouteGroupInterface + { + if ($this->callableResolver instanceof AdvancedCallableResolverInterface) { + $callable = $this->callableResolver->resolveRoute($this->callable); + } else { + $callable = $this->callableResolver->resolve($this->callable); + } + $callable($this->routeCollectorProxy); + return $this; + } + + /** + * {@inheritdoc} + */ + public function add($middleware): RouteGroupInterface + { + $this->middleware[] = $middleware; + return $this; + } + + /** + * {@inheritdoc} + */ + public function addMiddleware(MiddlewareInterface $middleware): RouteGroupInterface + { + $this->middleware[] = $middleware; + return $this; + } + + /** + * {@inheritdoc} + */ + public function appendMiddlewareToDispatcher(MiddlewareDispatcher $dispatcher): RouteGroupInterface + { + foreach ($this->middleware as $middleware) { + $dispatcher->add($middleware); + } + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getPattern(): string + { + return $this->pattern; + } +} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Routing/RouteParser.php b/advancedcontentfilter/vendor/slim/slim/Slim/Routing/RouteParser.php new file mode 100644 index 000000000..afb533cc5 --- /dev/null +++ b/advancedcontentfilter/vendor/slim/slim/Slim/Routing/RouteParser.php @@ -0,0 +1,127 @@ +routeCollector = $routeCollector; + $this->routeParser = new Std(); + } + + /** + * {@inheritdoc} + */ + public function relativeUrlFor(string $routeName, array $data = [], array $queryParams = []): string + { + $route = $this->routeCollector->getNamedRoute($routeName); + $pattern = $route->getPattern(); + + $segments = []; + $segmentName = ''; + + /* + * $routes is an associative array of expressions representing a route as multiple segments + * There is an expression for each optional parameter plus one without the optional parameters + * The most specific is last, hence why we reverse the array before iterating over it + */ + $expressions = array_reverse($this->routeParser->parse($pattern)); + foreach ($expressions as $expression) { + foreach ($expression as $segment) { + /* + * Each $segment is either a string or an array of strings + * containing optional parameters of an expression + */ + if (is_string($segment)) { + $segments[] = $segment; + continue; + } + + /** @var string[] $segment */ + /* + * If we don't have a data element for this segment in the provided $data + * we cancel testing to move onto the next expression with a less specific item + */ + if (!array_key_exists($segment[0], $data)) { + $segments = []; + $segmentName = $segment[0]; + break; + } + + $segments[] = $data[$segment[0]]; + } + + /* + * If we get to this logic block we have found all the parameters + * for the provided $data which means we don't need to continue testing + * less specific expressions + */ + if (!empty($segments)) { + break; + } + } + + if (empty($segments)) { + throw new InvalidArgumentException('Missing data for URL segment: ' . $segmentName); + } + + $url = implode('', $segments); + if ($queryParams) { + $url .= '?' . http_build_query($queryParams); + } + + return $url; + } + + /** + * {@inheritdoc} + */ + public function urlFor(string $routeName, array $data = [], array $queryParams = []): string + { + $basePath = $this->routeCollector->getBasePath(); + $url = $this->relativeUrlFor($routeName, $data, $queryParams); + + if ($basePath) { + $url = $basePath . $url; + } + + return $url; + } + + /** + * {@inheritdoc} + */ + public function fullUrlFor(UriInterface $uri, string $routeName, array $data = [], array $queryParams = []): string + { + $path = $this->urlFor($routeName, $data, $queryParams); + $scheme = $uri->getScheme(); + $authority = $uri->getAuthority(); + $protocol = ($scheme ? $scheme . ':' : '') . ($authority ? '//' . $authority : ''); + return $protocol . $path; + } +} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Routing/RouteResolver.php b/advancedcontentfilter/vendor/slim/slim/Slim/Routing/RouteResolver.php new file mode 100644 index 000000000..d4f4eafa3 --- /dev/null +++ b/advancedcontentfilter/vendor/slim/slim/Slim/Routing/RouteResolver.php @@ -0,0 +1,56 @@ +routeCollector = $routeCollector; + $this->dispatcher = $dispatcher ?? new Dispatcher($routeCollector); + } + + /** + * @param string $uri Should be $request->getUri()->getPath() + */ + public function computeRoutingResults(string $uri, string $method): RoutingResults + { + $uri = rawurldecode($uri); + if ($uri === '' || $uri[0] !== '/') { + $uri = '/' . $uri; + } + return $this->dispatcher->dispatch($method, $uri); + } + + /** + * @throws RuntimeException + */ + public function resolveRoute(string $identifier): RouteInterface + { + return $this->routeCollector->lookupRoute($identifier); + } +} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Routing/RouteRunner.php b/advancedcontentfilter/vendor/slim/slim/Slim/Routing/RouteRunner.php new file mode 100644 index 000000000..40946af56 --- /dev/null +++ b/advancedcontentfilter/vendor/slim/slim/Slim/Routing/RouteRunner.php @@ -0,0 +1,70 @@ +routeResolver = $routeResolver; + $this->routeParser = $routeParser; + $this->routeCollectorProxy = $routeCollectorProxy; + } + + /** + * This request handler is instantiated automatically in App::__construct() + * It is at the very tip of the middleware queue meaning it will be executed + * last and it detects whether or not routing has been performed in the user + * defined middleware stack. In the event that the user did not perform routing + * it is done here + * + * @throws HttpNotFoundException + * @throws HttpMethodNotAllowedException + */ + public function handle(ServerRequestInterface $request): ResponseInterface + { + // If routing hasn't been done, then do it now so we can dispatch + if ($request->getAttribute(RouteContext::ROUTING_RESULTS) === null) { + $routingMiddleware = new RoutingMiddleware($this->routeResolver, $this->routeParser); + $request = $routingMiddleware->performRouting($request); + } + + if ($this->routeCollectorProxy !== null) { + $request = $request->withAttribute( + RouteContext::BASE_PATH, + $this->routeCollectorProxy->getBasePath() + ); + } + + /** @var Route $route */ + $route = $request->getAttribute(RouteContext::ROUTE); + return $route->run($request); + } +} diff --git a/advancedcontentfilter/vendor/slim/slim/Slim/Routing/RoutingResults.php b/advancedcontentfilter/vendor/slim/slim/Slim/Routing/RoutingResults.php new file mode 100644 index 000000000..ac2fa64f9 --- /dev/null +++ b/advancedcontentfilter/vendor/slim/slim/Slim/Routing/RoutingResults.php @@ -0,0 +1,112 @@ + + */ + protected array $routeArguments; + + /** + * @param array $routeArguments + */ + public function __construct( + DispatcherInterface $dispatcher, + string $method, + string $uri, + int $routeStatus, + ?string $routeIdentifier = null, + array $routeArguments = [] + ) { + $this->dispatcher = $dispatcher; + $this->method = $method; + $this->uri = $uri; + $this->routeStatus = $routeStatus; + $this->routeIdentifier = $routeIdentifier; + $this->routeArguments = $routeArguments; + } + + public function getDispatcher(): DispatcherInterface + { + return $this->dispatcher; + } + + public function getMethod(): string + { + return $this->method; + } + + public function getUri(): string + { + return $this->uri; + } + + public function getRouteStatus(): int + { + return $this->routeStatus; + } + + public function getRouteIdentifier(): ?string + { + return $this->routeIdentifier; + } + + /** + * @return array + */ + public function getRouteArguments(bool $urlDecode = true): array + { + if (!$urlDecode) { + return $this->routeArguments; + } + + $routeArguments = []; + foreach ($this->routeArguments as $key => $value) { + $routeArguments[$key] = rawurldecode($value); + } + + return $routeArguments; + } + + /** + * @return string[] + */ + public function getAllowedMethods(): array + { + return $this->dispatcher->getAllowedMethods($this->uri); + } +} diff --git a/advancedcontentfilter/vendor/slim/slim/composer.json b/advancedcontentfilter/vendor/slim/slim/composer.json index 554a838a9..36c0c1d19 100644 --- a/advancedcontentfilter/vendor/slim/slim/composer.json +++ b/advancedcontentfilter/vendor/slim/slim/composer.json @@ -3,7 +3,7 @@ "type": "library", "description": "Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs", "keywords": ["framework","micro","api","router"], - "homepage": "https://slimframework.com", + "homepage": "https://www.slimframework.com", "license": "MIT", "authors": [ { @@ -21,38 +21,82 @@ "email": "rob@akrabat.com", "homepage": "http://akrabat.com" }, + { + "name": "Pierre Berube", + "email": "pierre@lgse.com", + "homepage": "http://www.lgse.com" + }, { "name": "Gabriel Manricks", "email": "gmanricks@me.com", "homepage": "http://gabrielmanricks.com" } ], + "support": { + "docs": "https://www.slimframework.com/docs/v4/", + "forum": "https://discourse.slimframework.com/", + "irc": "irc://irc.freenode.net:6667/slimphp", + "issues": "https://github.com/slimphp/Slim/issues", + "rss": "https://www.slimframework.com/blog/feed.rss", + "slack": "https://slimphp.slack.com/", + "source": "https://github.com/slimphp/Slim", + "wiki": "https://github.com/slimphp/Slim/wiki" + }, "require": { - "php": ">=5.5.0", - "pimple/pimple": "^3.0", - "psr/http-message": "^1.0", - "nikic/fast-route": "^1.0", - "container-interop/container-interop": "^1.2", - "psr/container": "^1.0" + "php": "^7.4 || ^8.0", + "ext-json": "*", + "nikic/fast-route": "^1.3", + "psr/container": "^1.0 || ^2.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1", + "psr/http-server-handler": "^1.0", + "psr/http-server-middleware": "^1.0", + "psr/log": "^1.1 || ^2.0 || ^3.0" }, "require-dev": { - "squizlabs/php_codesniffer": "^2.5", - "phpunit/phpunit": "^4.0" - }, - "provide": { - "psr/http-message-implementation": "1.0" + "ext-simplexml": "*", + "adriansuter/php-autoload-override": "^1.4", + "guzzlehttp/psr7": "^2.5", + "httpsoft/http-message": "^1.1", + "httpsoft/http-server-request": "^1.1", + "laminas/laminas-diactoros": "^2.17", + "nyholm/psr7": "^1.8", + "nyholm/psr7-server": "^1.0", + "phpspec/prophecy": "^1.17", + "phpspec/prophecy-phpunit": "^2.0", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^9.6", + "slim/http": "^1.3", + "slim/psr7": "^1.6", + "squizlabs/php_codesniffer": "^3.7" }, "autoload": { "psr-4": { "Slim\\": "Slim" } }, + "autoload-dev": { + "psr-4": { + "Slim\\Tests\\": "tests" + } + }, "scripts": { "test": [ "@phpunit", - "@phpcs" + "@phpcs", + "@phpstan" ], - "phpunit": "php vendor/bin/phpunit", - "phpcs": "php vendor/bin/phpcs" + "phpunit": "phpunit", + "phpcs": "phpcs", + "phpstan": "phpstan --memory-limit=-1" + }, + "suggest": { + "ext-simplexml": "Needed to support XML format in BodyParsingMiddleware", + "ext-xml": "Needed to support XML format in BodyParsingMiddleware", + "slim/psr7": "Slim PSR-7 implementation. See https://www.slimframework.com/docs/v4/start/installation.html for more information.", + "php-di/php-di": "PHP-DI is the recommended container library to be used with Slim" + }, + "config": { + "sort-packages": true } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Adapter/AbstractAdapter.php b/advancedcontentfilter/vendor/symfony/cache/Adapter/AbstractAdapter.php index 727fc84c9..ab7dc9607 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Adapter/AbstractAdapter.php +++ b/advancedcontentfilter/vendor/symfony/cache/Adapter/AbstractAdapter.php @@ -14,7 +14,6 @@ namespace Symfony\Component\Cache\Adapter; use Psr\Cache\CacheItemInterface; use Psr\Log\LoggerAwareInterface; use Psr\Log\LoggerInterface; -use Psr\Log\NullLogger; use Symfony\Component\Cache\CacheItem; use Symfony\Component\Cache\Exception\InvalidArgumentException; use Symfony\Component\Cache\ResettableInterface; @@ -25,6 +24,11 @@ use Symfony\Component\Cache\Traits\AbstractTrait; */ abstract class AbstractAdapter implements AdapterInterface, LoggerAwareInterface, ResettableInterface { + /** + * @internal + */ + const NS_SEPARATOR = ':'; + use AbstractTrait; private static $apcuSupported; @@ -39,17 +43,16 @@ abstract class AbstractAdapter implements AdapterInterface, LoggerAwareInterface */ protected function __construct($namespace = '', $defaultLifetime = 0) { - $this->namespace = '' === $namespace ? '' : CacheItem::validateKey($namespace).':'; - if (null !== $this->maxIdLength && strlen($namespace) > $this->maxIdLength - 24) { - throw new InvalidArgumentException(sprintf('Namespace must be %d chars max, %d given ("%s")', $this->maxIdLength - 24, strlen($namespace), $namespace)); + $this->namespace = '' === $namespace ? '' : CacheItem::validateKey($namespace).static::NS_SEPARATOR; + if (null !== $this->maxIdLength && \strlen($namespace) > $this->maxIdLength - 24) { + throw new InvalidArgumentException(sprintf('Namespace must be %d chars max, %d given ("%s").', $this->maxIdLength - 24, \strlen($namespace), $namespace)); } $this->createCacheItem = \Closure::bind( - function ($key, $value, $isHit) use ($defaultLifetime) { + static function ($key, $value, $isHit) { $item = new CacheItem(); $item->key = $key; $item->value = $value; $item->isHit = $isHit; - $item->defaultLifetime = $defaultLifetime; return $item; }, @@ -58,14 +61,16 @@ abstract class AbstractAdapter implements AdapterInterface, LoggerAwareInterface ); $getId = function ($key) { return $this->getId((string) $key); }; $this->mergeByLifetime = \Closure::bind( - function ($deferred, $namespace, &$expiredIds) use ($getId) { - $byLifetime = array(); + static function ($deferred, $namespace, &$expiredIds) use ($getId, $defaultLifetime) { + $byLifetime = []; $now = time(); - $expiredIds = array(); + $expiredIds = []; foreach ($deferred as $key => $item) { if (null === $item->expiry) { - $byLifetime[0 < $item->defaultLifetime ? $item->defaultLifetime : 0][$getId($key)] = $item->value; + $byLifetime[0 < $defaultLifetime ? $defaultLifetime : 0][$getId($key)] = $item->value; + } elseif (0 === $item->expiry) { + $byLifetime[0][$getId($key)] = $item->value; } elseif ($item->expiry > $now) { $byLifetime[$item->expiry - $now][$getId($key)] = $item->value; } else { @@ -81,11 +86,10 @@ abstract class AbstractAdapter implements AdapterInterface, LoggerAwareInterface } /** - * @param string $namespace - * @param int $defaultLifetime - * @param string $version - * @param string $directory - * @param LoggerInterface|null $logger + * @param string $namespace + * @param int $defaultLifetime + * @param string $version + * @param string $directory * * @return AdapterInterface */ @@ -112,24 +116,22 @@ abstract class AbstractAdapter implements AdapterInterface, LoggerAwareInterface if (null !== $logger) { $fs->setLogger($logger); } - if (!self::$apcuSupported) { + if (!self::$apcuSupported || (\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) && !filter_var(ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOLEAN))) { return $fs; } $apcu = new ApcuAdapter($namespace, (int) $defaultLifetime / 5, $version); - if ('cli' === \PHP_SAPI && !ini_get('apc.enable_cli')) { - $apcu->setLogger(new NullLogger()); - } elseif (null !== $logger) { + if (null !== $logger) { $apcu->setLogger($logger); } - return new ChainAdapter(array($apcu, $fs)); + return new ChainAdapter([$apcu, $fs]); } - public static function createConnection($dsn, array $options = array()) + public static function createConnection($dsn, array $options = []) { - if (!is_string($dsn)) { - throw new InvalidArgumentException(sprintf('The %s() method expect argument #1 to be string, %s given.', __METHOD__, gettype($dsn))); + if (!\is_string($dsn)) { + throw new InvalidArgumentException(sprintf('The "%s()" method expect argument #1 to be string, "%s" given.', __METHOD__, \gettype($dsn))); } if (0 === strpos($dsn, 'redis://')) { return RedisAdapter::createConnection($dsn, $options); @@ -138,7 +140,7 @@ abstract class AbstractAdapter implements AdapterInterface, LoggerAwareInterface return MemcachedAdapter::createConnection($dsn, $options); } - throw new InvalidArgumentException(sprintf('Unsupported DSN: %s.', $dsn)); + throw new InvalidArgumentException(sprintf('Unsupported DSN: "%s".', $dsn)); } /** @@ -156,11 +158,11 @@ abstract class AbstractAdapter implements AdapterInterface, LoggerAwareInterface $value = null; try { - foreach ($this->doFetch(array($id)) as $value) { + foreach ($this->doFetch([$id]) as $value) { $isHit = true; } } catch (\Exception $e) { - CacheItem::log($this->logger, 'Failed to fetch key "{key}"', array('key' => $key, 'exception' => $e)); + CacheItem::log($this->logger, 'Failed to fetch key "{key}"', ['key' => $key, 'exception' => $e]); } return $f($key, $value, $isHit); @@ -169,12 +171,12 @@ abstract class AbstractAdapter implements AdapterInterface, LoggerAwareInterface /** * {@inheritdoc} */ - public function getItems(array $keys = array()) + public function getItems(array $keys = []) { if ($this->deferred) { $this->commit(); } - $ids = array(); + $ids = []; foreach ($keys as $key) { $ids[] = $this->getId($key); @@ -182,8 +184,8 @@ abstract class AbstractAdapter implements AdapterInterface, LoggerAwareInterface try { $items = $this->doFetch($ids); } catch (\Exception $e) { - CacheItem::log($this->logger, 'Failed to fetch requested items', array('keys' => $keys, 'exception' => $e)); - $items = array(); + CacheItem::log($this->logger, 'Failed to fetch requested items', ['keys' => $keys, 'exception' => $e]); + $items = []; } $ids = array_combine($ids, $keys); @@ -224,7 +226,7 @@ abstract class AbstractAdapter implements AdapterInterface, LoggerAwareInterface $ok = true; $byLifetime = $this->mergeByLifetime; $byLifetime = $byLifetime($this->deferred, $this->namespace, $expiredIds); - $retry = $this->deferred = array(); + $retry = $this->deferred = []; if ($expiredIds) { $this->doDelete($expiredIds); @@ -234,15 +236,15 @@ abstract class AbstractAdapter implements AdapterInterface, LoggerAwareInterface $e = $this->doSave($values, $lifetime); } catch (\Exception $e) { } - if (true === $e || array() === $e) { + if (true === $e || [] === $e) { continue; } - if (is_array($e) || 1 === count($values)) { - foreach (is_array($e) ? $e : array_keys($values) as $id) { + if (\is_array($e) || 1 === \count($values)) { + foreach (\is_array($e) ? $e : array_keys($values) as $id) { $ok = false; $v = $values[$id]; - $type = is_object($v) ? get_class($v) : gettype($v); - CacheItem::log($this->logger, 'Failed to save key "{key}" ({type})', array('key' => substr($id, strlen($this->namespace)), 'type' => $type, 'exception' => $e instanceof \Exception ? $e : null)); + $type = \is_object($v) ? \get_class($v) : \gettype($v); + CacheItem::log($this->logger, 'Failed to save key "{key}" ({type})', ['key' => substr($id, \strlen($this->namespace)), 'type' => $type, 'exception' => $e instanceof \Exception ? $e : null]); } } else { foreach ($values as $id => $v) { @@ -256,21 +258,31 @@ abstract class AbstractAdapter implements AdapterInterface, LoggerAwareInterface foreach ($ids as $id) { try { $v = $byLifetime[$lifetime][$id]; - $e = $this->doSave(array($id => $v), $lifetime); + $e = $this->doSave([$id => $v], $lifetime); } catch (\Exception $e) { } - if (true === $e || array() === $e) { + if (true === $e || [] === $e) { continue; } $ok = false; - $type = is_object($v) ? get_class($v) : gettype($v); - CacheItem::log($this->logger, 'Failed to save key "{key}" ({type})', array('key' => substr($id, strlen($this->namespace)), 'type' => $type, 'exception' => $e instanceof \Exception ? $e : null)); + $type = \is_object($v) ? \get_class($v) : \gettype($v); + CacheItem::log($this->logger, 'Failed to save key "{key}" ({type})', ['key' => substr($id, \strlen($this->namespace)), 'type' => $type, 'exception' => $e instanceof \Exception ? $e : null]); } } return $ok; } + public function __sleep() + { + throw new \BadMethodCallException('Cannot serialize '.__CLASS__); + } + + public function __wakeup() + { + throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); + } + public function __destruct() { if ($this->deferred) { @@ -292,7 +304,7 @@ abstract class AbstractAdapter implements AdapterInterface, LoggerAwareInterface yield $key => $f($key, $value, true); } } catch (\Exception $e) { - CacheItem::log($this->logger, 'Failed to fetch requested items', array('keys' => array_values($keys), 'exception' => $e)); + CacheItem::log($this->logger, 'Failed to fetch requested items', ['keys' => array_values($keys), 'exception' => $e]); } foreach ($keys as $key) { diff --git a/advancedcontentfilter/vendor/symfony/cache/Adapter/AdapterInterface.php b/advancedcontentfilter/vendor/symfony/cache/Adapter/AdapterInterface.php index 41222c1ab..85fe07684 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Adapter/AdapterInterface.php +++ b/advancedcontentfilter/vendor/symfony/cache/Adapter/AdapterInterface.php @@ -33,5 +33,5 @@ interface AdapterInterface extends CacheItemPoolInterface * * @return \Traversable|CacheItem[] */ - public function getItems(array $keys = array()); + public function getItems(array $keys = []); } diff --git a/advancedcontentfilter/vendor/symfony/cache/Adapter/ArrayAdapter.php b/advancedcontentfilter/vendor/symfony/cache/Adapter/ArrayAdapter.php index 2118e9c6f..33f55a869 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Adapter/ArrayAdapter.php +++ b/advancedcontentfilter/vendor/symfony/cache/Adapter/ArrayAdapter.php @@ -25,6 +25,7 @@ class ArrayAdapter implements AdapterInterface, LoggerAwareInterface, Resettable use ArrayTrait; private $createCacheItem; + private $defaultLifetime; /** * @param int $defaultLifetime @@ -32,14 +33,14 @@ class ArrayAdapter implements AdapterInterface, LoggerAwareInterface, Resettable */ public function __construct($defaultLifetime = 0, $storeSerialized = true) { + $this->defaultLifetime = $defaultLifetime; $this->storeSerialized = $storeSerialized; $this->createCacheItem = \Closure::bind( - function ($key, $value, $isHit) use ($defaultLifetime) { + static function ($key, $value, $isHit) { $item = new CacheItem(); $item->key = $key; $item->value = $value; $item->isHit = $isHit; - $item->defaultLifetime = $defaultLifetime; return $item; }, @@ -66,7 +67,7 @@ class ArrayAdapter implements AdapterInterface, LoggerAwareInterface, Resettable $isHit = false; } } catch (\Exception $e) { - CacheItem::log($this->logger, 'Failed to unserialize key "{key}"', array('key' => $key, 'exception' => $e)); + CacheItem::log($this->logger, 'Failed to unserialize key "{key}"', ['key' => $key, 'exception' => $e]); $this->values[$key] = $value = null; $isHit = false; } @@ -78,7 +79,7 @@ class ArrayAdapter implements AdapterInterface, LoggerAwareInterface, Resettable /** * {@inheritdoc} */ - public function getItems(array $keys = array()) + public function getItems(array $keys = []) { foreach ($keys as $key) { CacheItem::validateKey($key); @@ -112,6 +113,10 @@ class ArrayAdapter implements AdapterInterface, LoggerAwareInterface, Resettable $value = $item["\0*\0value"]; $expiry = $item["\0*\0expiry"]; + if (0 === $expiry) { + $expiry = \PHP_INT_MAX; + } + if (null !== $expiry && $expiry <= time()) { $this->deleteItem($key); @@ -121,18 +126,18 @@ class ArrayAdapter implements AdapterInterface, LoggerAwareInterface, Resettable try { $value = serialize($value); } catch (\Exception $e) { - $type = is_object($value) ? get_class($value) : gettype($value); - CacheItem::log($this->logger, 'Failed to save key "{key}" ({type})', array('key' => $key, 'type' => $type, 'exception' => $e)); + $type = \is_object($value) ? \get_class($value) : \gettype($value); + CacheItem::log($this->logger, 'Failed to save key "{key}" ({type})', ['key' => $key, 'type' => $type, 'exception' => $e]); return false; } } - if (null === $expiry && 0 < $item["\0*\0defaultLifetime"]) { - $expiry = time() + $item["\0*\0defaultLifetime"]; + if (null === $expiry && 0 < $this->defaultLifetime) { + $expiry = time() + $this->defaultLifetime; } $this->values[$key] = $value; - $this->expiries[$key] = null !== $expiry ? $expiry : PHP_INT_MAX; + $this->expiries[$key] = null !== $expiry ? $expiry : \PHP_INT_MAX; return true; } diff --git a/advancedcontentfilter/vendor/symfony/cache/Adapter/ChainAdapter.php b/advancedcontentfilter/vendor/symfony/cache/Adapter/ChainAdapter.php index 6bdf6b2d5..fdb28846f 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Adapter/ChainAdapter.php +++ b/advancedcontentfilter/vendor/symfony/cache/Adapter/ChainAdapter.php @@ -28,15 +28,15 @@ use Symfony\Component\Cache\ResettableInterface; */ class ChainAdapter implements AdapterInterface, PruneableInterface, ResettableInterface { - private $adapters = array(); + private $adapters = []; private $adapterCount; - private $saveUp; + private $syncItem; /** - * @param CacheItemPoolInterface[] $adapters The ordered list of adapters used to fetch cached items - * @param int $maxLifetime The max lifetime of items propagated from lower adapters to upper ones + * @param CacheItemPoolInterface[] $adapters The ordered list of adapters used to fetch cached items + * @param int $defaultLifetime The default lifetime of items propagated from lower adapters to upper ones */ - public function __construct(array $adapters, $maxLifetime = 0) + public function __construct(array $adapters, $defaultLifetime = 0) { if (!$adapters) { throw new InvalidArgumentException('At least one adapter must be specified.'); @@ -44,7 +44,10 @@ class ChainAdapter implements AdapterInterface, PruneableInterface, ResettableIn foreach ($adapters as $adapter) { if (!$adapter instanceof CacheItemPoolInterface) { - throw new InvalidArgumentException(sprintf('The class "%s" does not implement the "%s" interface.', get_class($adapter), CacheItemPoolInterface::class)); + throw new InvalidArgumentException(sprintf('The class "%s" does not implement the "%s" interface.', \get_class($adapter), CacheItemPoolInterface::class)); + } + if (\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) && $adapter instanceof ApcuAdapter && !filter_var(ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOLEAN)) { + continue; // skip putting APCu in the chain when the backend is disabled } if ($adapter instanceof AdapterInterface) { @@ -53,18 +56,18 @@ class ChainAdapter implements AdapterInterface, PruneableInterface, ResettableIn $this->adapters[] = new ProxyAdapter($adapter); } } - $this->adapterCount = count($this->adapters); + $this->adapterCount = \count($this->adapters); - $this->saveUp = \Closure::bind( - function ($adapter, $item) use ($maxLifetime) { - $origDefaultLifetime = $item->defaultLifetime; + $this->syncItem = \Closure::bind( + static function ($sourceItem, $item) use ($defaultLifetime) { + $item->value = $sourceItem->value; + $item->isHit = $sourceItem->isHit; - if (0 < $maxLifetime && ($origDefaultLifetime <= 0 || $maxLifetime < $origDefaultLifetime)) { - $item->defaultLifetime = $maxLifetime; + if (0 < $defaultLifetime) { + $item->expiresAfter($defaultLifetime); } - $adapter->save($item); - $item->defaultLifetime = $origDefaultLifetime; + return $item; }, null, CacheItem::class @@ -76,18 +79,21 @@ class ChainAdapter implements AdapterInterface, PruneableInterface, ResettableIn */ public function getItem($key) { - $saveUp = $this->saveUp; + $syncItem = $this->syncItem; + $misses = []; foreach ($this->adapters as $i => $adapter) { $item = $adapter->getItem($key); if ($item->isHit()) { while (0 <= --$i) { - $saveUp($this->adapters[$i], $item); + $this->adapters[$i]->save($syncItem($item, $misses[$i])); } return $item; } + + $misses[$i] = $item; } return $item; @@ -96,14 +102,15 @@ class ChainAdapter implements AdapterInterface, PruneableInterface, ResettableIn /** * {@inheritdoc} */ - public function getItems(array $keys = array()) + public function getItems(array $keys = []) { return $this->generateItems($this->adapters[0]->getItems($keys), 0); } private function generateItems($items, $adapterIndex) { - $missing = array(); + $missing = []; + $misses = []; $nextAdapterIndex = $adapterIndex + 1; $nextAdapter = isset($this->adapters[$nextAdapterIndex]) ? $this->adapters[$nextAdapterIndex] : null; @@ -112,17 +119,18 @@ class ChainAdapter implements AdapterInterface, PruneableInterface, ResettableIn yield $k => $item; } else { $missing[] = $k; + $misses[$k] = $item; } } if ($missing) { - $saveUp = $this->saveUp; + $syncItem = $this->syncItem; $adapter = $this->adapters[$adapterIndex]; $items = $this->generateItems($nextAdapter->getItems($missing), $nextAdapterIndex); foreach ($items as $k => $item) { if ($item->isHit()) { - $saveUp($adapter, $item); + $adapter->save($syncItem($item, $misses[$k])); } yield $k => $item; diff --git a/advancedcontentfilter/vendor/symfony/cache/Adapter/DoctrineAdapter.php b/advancedcontentfilter/vendor/symfony/cache/Adapter/DoctrineAdapter.php index 972d2b415..8081d7dc3 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Adapter/DoctrineAdapter.php +++ b/advancedcontentfilter/vendor/symfony/cache/Adapter/DoctrineAdapter.php @@ -19,9 +19,8 @@ class DoctrineAdapter extends AbstractAdapter use DoctrineTrait; /** - * @param CacheProvider $provider - * @param string $namespace - * @param int $defaultLifetime + * @param string $namespace + * @param int $defaultLifetime */ public function __construct(CacheProvider $provider, $namespace = '', $defaultLifetime = 0) { diff --git a/advancedcontentfilter/vendor/symfony/cache/Adapter/NullAdapter.php b/advancedcontentfilter/vendor/symfony/cache/Adapter/NullAdapter.php index f58f81e5b..c81a1cd64 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Adapter/NullAdapter.php +++ b/advancedcontentfilter/vendor/symfony/cache/Adapter/NullAdapter.php @@ -49,7 +49,7 @@ class NullAdapter implements AdapterInterface /** * {@inheritdoc} */ - public function getItems(array $keys = array()) + public function getItems(array $keys = []) { return $this->generateItems($keys); } diff --git a/advancedcontentfilter/vendor/symfony/cache/Adapter/PdoAdapter.php b/advancedcontentfilter/vendor/symfony/cache/Adapter/PdoAdapter.php index c3fc45b67..590386794 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Adapter/PdoAdapter.php +++ b/advancedcontentfilter/vendor/symfony/cache/Adapter/PdoAdapter.php @@ -35,7 +35,7 @@ class PdoAdapter extends AbstractAdapter implements PruneableInterface * * db_time_col: The column where to store the timestamp [default: item_time] * * db_username: The username when lazy-connect [default: ''] * * db_password: The password when lazy-connect [default: ''] - * * db_connection_options: An array of driver-specific connection options [default: array()] + * * db_connection_options: An array of driver-specific connection options [default: []] * * @param \PDO|Connection|string $connOrDsn A \PDO or Connection instance or DSN string or null * @param string $namespace @@ -46,7 +46,7 @@ class PdoAdapter extends AbstractAdapter implements PruneableInterface * @throws InvalidArgumentException When PDO error mode is not PDO::ERRMODE_EXCEPTION * @throws InvalidArgumentException When namespace contains invalid characters */ - public function __construct($connOrDsn, $namespace = '', $defaultLifetime = 0, array $options = array()) + public function __construct($connOrDsn, $namespace = '', $defaultLifetime = 0, array $options = []) { $this->init($connOrDsn, $namespace, $defaultLifetime, $options); } diff --git a/advancedcontentfilter/vendor/symfony/cache/Adapter/PhpArrayAdapter.php b/advancedcontentfilter/vendor/symfony/cache/Adapter/PhpArrayAdapter.php index d3b9d77d4..47a259c13 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Adapter/PhpArrayAdapter.php +++ b/advancedcontentfilter/vendor/symfony/cache/Adapter/PhpArrayAdapter.php @@ -40,9 +40,9 @@ class PhpArrayAdapter implements AdapterInterface, PruneableInterface, Resettabl { $this->file = $file; $this->pool = $fallbackPool; - $this->zendDetectUnicode = ini_get('zend.detect_unicode'); + $this->zendDetectUnicode = filter_var(ini_get('zend.detect_unicode'), \FILTER_VALIDATE_BOOLEAN); $this->createCacheItem = \Closure::bind( - function ($key, $value, $isHit) { + static function ($key, $value, $isHit) { $item = new CacheItem(); $item->key = $key; $item->value = $value; @@ -61,14 +61,13 @@ class PhpArrayAdapter implements AdapterInterface, PruneableInterface, Resettabl * fallback pool with this adapter only if the current PHP version is supported. * * @param string $file The PHP file were values are cached - * @param CacheItemPoolInterface $fallbackPool Fallback for old PHP versions or opcache disabled + * @param CacheItemPoolInterface $fallbackPool A pool to fallback on when an item is not hit * * @return CacheItemPoolInterface */ public static function create($file, CacheItemPoolInterface $fallbackPool) { - // Shared memory is available in PHP 7.0+ with OPCache enabled and in HHVM - if ((\PHP_VERSION_ID >= 70000 && ini_get('opcache.enable')) || defined('HHVM_VERSION')) { + if (\PHP_VERSION_ID >= 70000) { if (!$fallbackPool instanceof AdapterInterface) { $fallbackPool = new ProxyAdapter($fallbackPool); } @@ -84,8 +83,8 @@ class PhpArrayAdapter implements AdapterInterface, PruneableInterface, Resettabl */ public function getItem($key) { - if (!is_string($key)) { - throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', is_object($key) ? get_class($key) : gettype($key))); + if (!\is_string($key)) { + throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key))); } if (null === $this->values) { $this->initialize(); @@ -99,7 +98,7 @@ class PhpArrayAdapter implements AdapterInterface, PruneableInterface, Resettabl if ('N;' === $value) { $value = null; - } elseif (is_string($value) && isset($value[2]) && ':' === $value[1]) { + } elseif (\is_string($value) && isset($value[2]) && ':' === $value[1]) { try { $e = null; $value = unserialize($value); @@ -120,11 +119,11 @@ class PhpArrayAdapter implements AdapterInterface, PruneableInterface, Resettabl /** * {@inheritdoc} */ - public function getItems(array $keys = array()) + public function getItems(array $keys = []) { foreach ($keys as $key) { - if (!is_string($key)) { - throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', is_object($key) ? get_class($key) : gettype($key))); + if (!\is_string($key)) { + throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key))); } } if (null === $this->values) { @@ -139,8 +138,8 @@ class PhpArrayAdapter implements AdapterInterface, PruneableInterface, Resettabl */ public function hasItem($key) { - if (!is_string($key)) { - throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', is_object($key) ? get_class($key) : gettype($key))); + if (!\is_string($key)) { + throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key))); } if (null === $this->values) { $this->initialize(); @@ -154,8 +153,8 @@ class PhpArrayAdapter implements AdapterInterface, PruneableInterface, Resettabl */ public function deleteItem($key) { - if (!is_string($key)) { - throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', is_object($key) ? get_class($key) : gettype($key))); + if (!\is_string($key)) { + throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key))); } if (null === $this->values) { $this->initialize(); @@ -170,11 +169,11 @@ class PhpArrayAdapter implements AdapterInterface, PruneableInterface, Resettabl public function deleteItems(array $keys) { $deleted = true; - $fallbackKeys = array(); + $fallbackKeys = []; foreach ($keys as $key) { - if (!is_string($key)) { - throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', is_object($key) ? get_class($key) : gettype($key))); + if (!\is_string($key)) { + throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key))); } if (isset($this->values[$key])) { @@ -232,7 +231,7 @@ class PhpArrayAdapter implements AdapterInterface, PruneableInterface, Resettabl private function generateItems(array $keys) { $f = $this->createCacheItem; - $fallbackKeys = array(); + $fallbackKeys = []; foreach ($keys as $key) { if (isset($this->values[$key])) { @@ -240,7 +239,7 @@ class PhpArrayAdapter implements AdapterInterface, PruneableInterface, Resettabl if ('N;' === $value) { yield $key => $f($key, null, true); - } elseif (is_string($value) && isset($value[2]) && ':' === $value[1]) { + } elseif (\is_string($value) && isset($value[2]) && ':' === $value[1]) { try { yield $key => $f($key, unserialize($value), true); } catch (\Error $e) { @@ -266,20 +265,27 @@ class PhpArrayAdapter implements AdapterInterface, PruneableInterface, Resettabl /** * @throws \ReflectionException When $class is not found and is required * - * @internal + * @internal to be removed in Symfony 5.0 */ public static function throwOnRequiredClass($class) { $e = new \ReflectionException("Class $class does not exist"); - $trace = $e->getTrace(); - $autoloadFrame = array( + $trace = debug_backtrace(); + $autoloadFrame = [ 'function' => 'spl_autoload_call', - 'args' => array($class), - ); - $i = 1 + array_search($autoloadFrame, $trace, true); + 'args' => [$class], + ]; - if (isset($trace[$i]['function']) && !isset($trace[$i]['class'])) { - switch ($trace[$i]['function']) { + if (\PHP_VERSION_ID >= 80000 && isset($trace[1])) { + $callerFrame = $trace[1]; + } elseif (false !== $i = array_search($autoloadFrame, $trace, true)) { + $callerFrame = $trace[++$i]; + } else { + throw $e; + } + + if (isset($callerFrame['function']) && !isset($callerFrame['class'])) { + switch ($callerFrame['function']) { case 'get_class_methods': case 'get_class_vars': case 'get_parent_class': diff --git a/advancedcontentfilter/vendor/symfony/cache/Adapter/PhpFilesAdapter.php b/advancedcontentfilter/vendor/symfony/cache/Adapter/PhpFilesAdapter.php index 528d9c01f..b56143c2c 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Adapter/PhpFilesAdapter.php +++ b/advancedcontentfilter/vendor/symfony/cache/Adapter/PhpFilesAdapter.php @@ -29,13 +29,13 @@ class PhpFilesAdapter extends AbstractAdapter implements PruneableInterface public function __construct($namespace = '', $defaultLifetime = 0, $directory = null) { if (!static::isSupported()) { - throw new CacheException('OPcache is not enabled'); + throw new CacheException('OPcache is not enabled.'); } parent::__construct('', $defaultLifetime); $this->init($namespace, $directory); $e = new \Exception(); $this->includeHandler = function () use ($e) { throw $e; }; - $this->zendDetectUnicode = ini_get('zend.detect_unicode'); + $this->zendDetectUnicode = filter_var(ini_get('zend.detect_unicode'), \FILTER_VALIDATE_BOOLEAN); } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Adapter/ProxyAdapter.php b/advancedcontentfilter/vendor/symfony/cache/Adapter/ProxyAdapter.php index 82c95c5b0..c89a760ed 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Adapter/ProxyAdapter.php +++ b/advancedcontentfilter/vendor/symfony/cache/Adapter/ProxyAdapter.php @@ -29,28 +29,31 @@ class ProxyAdapter implements AdapterInterface, PruneableInterface, ResettableIn private $namespaceLen; private $createCacheItem; private $poolHash; + private $defaultLifetime; /** - * @param CacheItemPoolInterface $pool - * @param string $namespace - * @param int $defaultLifetime + * @param string $namespace + * @param int $defaultLifetime */ public function __construct(CacheItemPoolInterface $pool, $namespace = '', $defaultLifetime = 0) { $this->pool = $pool; $this->poolHash = $poolHash = spl_object_hash($pool); $this->namespace = '' === $namespace ? '' : CacheItem::validateKey($namespace); - $this->namespaceLen = strlen($namespace); + $this->namespaceLen = \strlen($namespace); + $this->defaultLifetime = $defaultLifetime; $this->createCacheItem = \Closure::bind( - function ($key, $innerItem) use ($defaultLifetime, $poolHash) { + static function ($key, $innerItem) use ($poolHash) { $item = new CacheItem(); $item->key = $key; - $item->value = $innerItem->get(); - $item->isHit = $innerItem->isHit(); - $item->defaultLifetime = $defaultLifetime; - $item->innerItem = $innerItem; $item->poolHash = $poolHash; - $innerItem->set(null); + + if (null !== $innerItem) { + $item->value = $innerItem->get(); + $item->isHit = $innerItem->isHit(); + $item->innerItem = $innerItem; + $innerItem->set(null); + } return $item; }, @@ -73,7 +76,7 @@ class ProxyAdapter implements AdapterInterface, PruneableInterface, ResettableIn /** * {@inheritdoc} */ - public function getItems(array $keys = array()) + public function getItems(array $keys = []) { if ($this->namespaceLen) { foreach ($keys as $i => $key) { @@ -153,10 +156,21 @@ class ProxyAdapter implements AdapterInterface, PruneableInterface, ResettableIn } $item = (array) $item; $expiry = $item["\0*\0expiry"]; - if (null === $expiry && 0 < $item["\0*\0defaultLifetime"]) { - $expiry = time() + $item["\0*\0defaultLifetime"]; + if (null === $expiry && 0 < $this->defaultLifetime) { + $expiry = time() + $this->defaultLifetime; } - $innerItem = $item["\0*\0poolHash"] === $this->poolHash ? $item["\0*\0innerItem"] : $this->pool->getItem($this->namespace.$item["\0*\0key"]); + + if ($item["\0*\0poolHash"] === $this->poolHash && $item["\0*\0innerItem"]) { + $innerItem = $item["\0*\0innerItem"]; + } elseif ($this->pool instanceof AdapterInterface) { + // this is an optimization specific for AdapterInterface implementations + // so we can save a round-trip to the backend by just creating a new item + $f = $this->createCacheItem; + $innerItem = $f($this->namespace.$item["\0*\0key"], null); + } else { + $innerItem = $this->pool->getItem($this->namespace.$item["\0*\0key"]); + } + $innerItem->set($item["\0*\0value"]); $innerItem->expiresAt(null !== $expiry ? \DateTime::createFromFormat('U', $expiry) : null); diff --git a/advancedcontentfilter/vendor/symfony/cache/Adapter/SimpleCacheAdapter.php b/advancedcontentfilter/vendor/symfony/cache/Adapter/SimpleCacheAdapter.php index 24db5d504..d3d0ede64 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Adapter/SimpleCacheAdapter.php +++ b/advancedcontentfilter/vendor/symfony/cache/Adapter/SimpleCacheAdapter.php @@ -13,14 +13,18 @@ namespace Symfony\Component\Cache\Adapter; use Psr\SimpleCache\CacheInterface; use Symfony\Component\Cache\PruneableInterface; -use Symfony\Component\Cache\ResettableInterface; use Symfony\Component\Cache\Traits\ProxyTrait; /** * @author Nicolas Grekas */ -class SimpleCacheAdapter extends AbstractAdapter implements PruneableInterface, ResettableInterface +class SimpleCacheAdapter extends AbstractAdapter implements PruneableInterface { + /** + * @internal + */ + const NS_SEPARATOR = '_'; + use ProxyTrait; private $miss; diff --git a/advancedcontentfilter/vendor/symfony/cache/Adapter/TagAwareAdapter.php b/advancedcontentfilter/vendor/symfony/cache/Adapter/TagAwareAdapter.php index 72bbc143c..febe50900 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Adapter/TagAwareAdapter.php +++ b/advancedcontentfilter/vendor/symfony/cache/Adapter/TagAwareAdapter.php @@ -27,25 +27,26 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface, R use ProxyTrait; - private $deferred = array(); + private $deferred = []; private $createCacheItem; private $setCacheItemTags; private $getTagsByKey; private $invalidateTags; private $tags; + private $knownTagVersions = []; + private $knownTagVersionsTtl; - public function __construct(AdapterInterface $itemsPool, AdapterInterface $tagsPool = null) + public function __construct(AdapterInterface $itemsPool, AdapterInterface $tagsPool = null, $knownTagVersionsTtl = 0.15) { $this->pool = $itemsPool; $this->tags = $tagsPool ?: $itemsPool; + $this->knownTagVersionsTtl = $knownTagVersionsTtl; $this->createCacheItem = \Closure::bind( - function ($key, $value, CacheItem $protoItem) { + static function ($key, $value, CacheItem $protoItem) { $item = new CacheItem(); $item->key = $key; $item->value = $value; - $item->defaultLifetime = $protoItem->defaultLifetime; $item->expiry = $protoItem->expiry; - $item->innerItem = $protoItem->innerItem; $item->poolHash = $protoItem->poolHash; return $item; @@ -54,7 +55,7 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface, R CacheItem::class ); $this->setCacheItemTags = \Closure::bind( - function (CacheItem $item, $key, array &$itemTags) { + static function (CacheItem $item, $key, array &$itemTags) { if (!$item->isHit) { return $item; } @@ -74,8 +75,8 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface, R CacheItem::class ); $this->getTagsByKey = \Closure::bind( - function ($deferred) { - $tagsByKey = array(); + static function ($deferred) { + $tagsByKey = []; foreach ($deferred as $key => $item) { $tagsByKey[$key] = $item->tags; } @@ -86,11 +87,9 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface, R CacheItem::class ); $this->invalidateTags = \Closure::bind( - function (AdapterInterface $tagsAdapter, array $tags) { - foreach ($tagsAdapter->getItems($tags) as $v) { - $v->set(1 + (int) $v->get()); - $v->defaultLifetime = 0; - $v->expiry = null; + static function (AdapterInterface $tagsAdapter, array $tags) { + foreach ($tags as $v) { + $v->expiry = 0; $tagsAdapter->saveDeferred($v); } @@ -106,14 +105,42 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface, R */ public function invalidateTags(array $tags) { - foreach ($tags as $k => $tag) { - if ('' !== $tag && is_string($tag)) { - $tags[$k] = $tag.static::TAGS_PREFIX; - } + $ok = true; + $tagsByKey = []; + $invalidatedTags = []; + foreach ($tags as $tag) { + CacheItem::validateKey($tag); + $invalidatedTags[$tag] = 0; } - $f = $this->invalidateTags; - return $f($this->tags, $tags); + if ($this->deferred) { + $items = $this->deferred; + foreach ($items as $key => $item) { + if (!$this->pool->saveDeferred($item)) { + unset($this->deferred[$key]); + $ok = false; + } + } + + $f = $this->getTagsByKey; + $tagsByKey = $f($items); + $this->deferred = []; + } + + $tagVersions = $this->getTagVersions($tagsByKey, $invalidatedTags); + $f = $this->createCacheItem; + + foreach ($tagsByKey as $key => $tags) { + $this->pool->saveDeferred($f(static::TAGS_PREFIX.$key, array_intersect_key($tagVersions, $tags), $items[$key])); + } + $ok = $this->pool->commit() && $ok; + + if ($invalidatedTags) { + $f = $this->invalidateTags; + $ok = $f($this->tags, $invalidatedTags) && $ok; + } + + return $ok; } /** @@ -127,12 +154,19 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface, R if (!$this->pool->hasItem($key)) { return false; } - if (!$itemTags = $this->pool->getItem(static::TAGS_PREFIX.$key)->get()) { + + $itemTags = $this->pool->getItem(static::TAGS_PREFIX.$key); + + if (!$itemTags->isHit()) { + return false; + } + + if (!$itemTags = $itemTags->get()) { return true; } - foreach ($this->getTagVersions(array($itemTags)) as $tag => $version) { - if ($itemTags[$tag] !== $version) { + foreach ($this->getTagVersions([$itemTags]) as $tag => $version) { + if ($itemTags[$tag] !== $version && 1 !== $itemTags[$tag] - $version) { return false; } } @@ -145,23 +179,25 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface, R */ public function getItem($key) { - foreach ($this->getItems(array($key)) as $item) { + foreach ($this->getItems([$key]) as $item) { return $item; } + + return null; } /** * {@inheritdoc} */ - public function getItems(array $keys = array()) + public function getItems(array $keys = []) { if ($this->deferred) { $this->commit(); } - $tagKeys = array(); + $tagKeys = []; foreach ($keys as $key) { - if ('' !== $key && is_string($key)) { + if ('' !== $key && \is_string($key)) { $key = static::TAGS_PREFIX.$key; $tagKeys[$key] = $key; } @@ -183,7 +219,7 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface, R */ public function clear() { - $this->deferred = array(); + $this->deferred = []; return $this->pool->clear(); } @@ -193,7 +229,7 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface, R */ public function deleteItem($key) { - return $this->deleteItems(array($key)); + return $this->deleteItems([$key]); } /** @@ -202,7 +238,7 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface, R public function deleteItems(array $keys) { foreach ($keys as $key) { - if ('' !== $key && is_string($key)) { + if ('' !== $key && \is_string($key)) { $keys[] = static::TAGS_PREFIX.$key; } } @@ -241,29 +277,17 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface, R */ public function commit() { - $ok = true; + return $this->invalidateTags([]); + } - if ($this->deferred) { - $items = $this->deferred; - foreach ($items as $key => $item) { - if (!$this->pool->saveDeferred($item)) { - unset($this->deferred[$key]); - $ok = false; - } - } + public function __sleep() + { + throw new \BadMethodCallException('Cannot serialize '.__CLASS__); + } - $f = $this->getTagsByKey; - $tagsByKey = $f($items); - $this->deferred = array(); - $tagVersions = $this->getTagVersions($tagsByKey); - $f = $this->createCacheItem; - - foreach ($tagsByKey as $key => $tags) { - $this->pool->saveDeferred($f(static::TAGS_PREFIX.$key, array_intersect_key($tagVersions, $tags), $items[$key])); - } - } - - return $this->pool->commit() && $ok; + public function __wakeup() + { + throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); } public function __destruct() @@ -273,7 +297,7 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface, R private function generateItems($items, array $tagKeys) { - $bufferedItems = $itemTags = array(); + $bufferedItems = $itemTags = []; $f = $this->setCacheItemTags; foreach ($items as $key => $item) { @@ -287,14 +311,17 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface, R } unset($tagKeys[$key]); - $itemTags[$key] = $item->get() ?: array(); + + if ($item->isHit()) { + $itemTags[$key] = $item->get() ?: []; + } if (!$tagKeys) { $tagVersions = $this->getTagVersions($itemTags); foreach ($itemTags as $key => $tags) { foreach ($tags as $tag => $version) { - if ($tagVersions[$tag] !== $version) { + if ($tagVersions[$tag] !== $version && 1 !== $version - $tagVersions[$tag]) { unset($itemTags[$key]); continue 2; } @@ -310,23 +337,55 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface, R } } - private function getTagVersions(array $tagsByKey) + private function getTagVersions(array $tagsByKey, array &$invalidatedTags = []) { - $tagVersions = array(); + $tagVersions = $invalidatedTags; foreach ($tagsByKey as $tags) { $tagVersions += $tags; } - if ($tagVersions) { - $tags = array(); - foreach ($tagVersions as $tag => $version) { - $tagVersions[$tag] = $tag.static::TAGS_PREFIX; - $tags[$tag.static::TAGS_PREFIX] = $tag; + if (!$tagVersions) { + return []; + } + + if (!$fetchTagVersions = 1 !== \func_num_args()) { + foreach ($tagsByKey as $tags) { + foreach ($tags as $tag => $version) { + if ($tagVersions[$tag] > $version) { + $tagVersions[$tag] = $version; + } + } } - foreach ($this->tags->getItems($tagVersions) as $tag => $version) { - $tagVersions[$tags[$tag]] = $version->get() ?: 0; + } + + $now = microtime(true); + $tags = []; + foreach ($tagVersions as $tag => $version) { + $tags[$tag.static::TAGS_PREFIX] = $tag; + if ($fetchTagVersions || !isset($this->knownTagVersions[$tag])) { + $fetchTagVersions = true; + continue; } + $version -= $this->knownTagVersions[$tag][1]; + if ((0 !== $version && 1 !== $version) || $now - $this->knownTagVersions[$tag][0] >= $this->knownTagVersionsTtl) { + // reuse previously fetched tag versions up to the ttl, unless we are storing items or a potential miss arises + $fetchTagVersions = true; + } else { + $this->knownTagVersions[$tag][1] += $version; + } + } + + if (!$fetchTagVersions) { + return $tagVersions; + } + + foreach ($this->tags->getItems(array_keys($tags)) as $tag => $version) { + $tagVersions[$tag = $tags[$tag]] = $version->get() ?: 0; + if (isset($invalidatedTags[$tag])) { + $invalidatedTags[$tag] = $version->set(++$tagVersions[$tag]); + } + $this->knownTagVersions[$tag] = [$now, $tagVersions[$tag]]; } return $tagVersions; diff --git a/advancedcontentfilter/vendor/symfony/cache/Adapter/TraceableAdapter.php b/advancedcontentfilter/vendor/symfony/cache/Adapter/TraceableAdapter.php index 98d0e5269..cc855c132 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Adapter/TraceableAdapter.php +++ b/advancedcontentfilter/vendor/symfony/cache/Adapter/TraceableAdapter.php @@ -25,7 +25,7 @@ use Symfony\Component\Cache\ResettableInterface; class TraceableAdapter implements AdapterInterface, PruneableInterface, ResettableInterface { protected $pool; - private $calls = array(); + private $calls = []; public function __construct(AdapterInterface $pool) { @@ -107,7 +107,7 @@ class TraceableAdapter implements AdapterInterface, PruneableInterface, Resettab /** * {@inheritdoc} */ - public function getItems(array $keys = array()) + public function getItems(array $keys = []) { $event = $this->start(__FUNCTION__); try { @@ -116,7 +116,7 @@ class TraceableAdapter implements AdapterInterface, PruneableInterface, Resettab $event->end = microtime(true); } $f = function () use ($result, $event) { - $event->result = array(); + $event->result = []; foreach ($result as $key => $item) { if ($event->result[$key] = $item->isHit()) { ++$event->hits; @@ -191,15 +191,11 @@ class TraceableAdapter implements AdapterInterface, PruneableInterface, Resettab */ public function reset() { - if (!$this->pool instanceof ResettableInterface) { - return; - } - $event = $this->start(__FUNCTION__); - try { + if ($this->pool instanceof ResettableInterface) { $this->pool->reset(); - } finally { - $event->end = microtime(true); } + + $this->clearCalls(); } public function getCalls() @@ -209,7 +205,7 @@ class TraceableAdapter implements AdapterInterface, PruneableInterface, Resettab public function clearCalls() { - $this->calls = array(); + $this->calls = []; } protected function start($name) diff --git a/advancedcontentfilter/vendor/symfony/cache/CacheItem.php b/advancedcontentfilter/vendor/symfony/cache/CacheItem.php index 93ffea495..7ae6568c2 100644 --- a/advancedcontentfilter/vendor/symfony/cache/CacheItem.php +++ b/advancedcontentfilter/vendor/symfony/cache/CacheItem.php @@ -24,9 +24,8 @@ final class CacheItem implements CacheItemInterface protected $value; protected $isHit = false; protected $expiry; - protected $defaultLifetime; - protected $tags = array(); - protected $prevTags = array(); + protected $tags = []; + protected $prevTags = []; protected $innerItem; protected $poolHash; @@ -56,6 +55,8 @@ final class CacheItem implements CacheItemInterface /** * {@inheritdoc} + * + * @return $this */ public function set($value) { @@ -66,15 +67,17 @@ final class CacheItem implements CacheItemInterface /** * {@inheritdoc} + * + * @return $this */ public function expiresAt($expiration) { if (null === $expiration) { - $this->expiry = $this->defaultLifetime > 0 ? time() + $this->defaultLifetime : null; + $this->expiry = null; } elseif ($expiration instanceof \DateTimeInterface) { $this->expiry = (int) $expiration->format('U'); } else { - throw new InvalidArgumentException(sprintf('Expiration date must implement DateTimeInterface or be null, "%s" given', is_object($expiration) ? get_class($expiration) : gettype($expiration))); + throw new InvalidArgumentException(sprintf('Expiration date must implement DateTimeInterface or be null, "%s" given.', \is_object($expiration) ? \get_class($expiration) : \gettype($expiration))); } return $this; @@ -82,17 +85,19 @@ final class CacheItem implements CacheItemInterface /** * {@inheritdoc} + * + * @return $this */ public function expiresAfter($time) { if (null === $time) { - $this->expiry = $this->defaultLifetime > 0 ? time() + $this->defaultLifetime : null; + $this->expiry = null; } elseif ($time instanceof \DateInterval) { $this->expiry = (int) \DateTime::createFromFormat('U', time())->add($time)->format('U'); - } elseif (is_int($time)) { + } elseif (\is_int($time)) { $this->expiry = $time + time(); } else { - throw new InvalidArgumentException(sprintf('Expiration date must be an integer, a DateInterval or null, "%s" given', is_object($time) ? get_class($time) : gettype($time))); + throw new InvalidArgumentException(sprintf('Expiration date must be an integer, a DateInterval or null, "%s" given.', \is_object($time) ? \get_class($time) : \gettype($time))); } return $this; @@ -103,27 +108,27 @@ final class CacheItem implements CacheItemInterface * * @param string|string[] $tags A tag or array of tags * - * @return static + * @return $this * * @throws InvalidArgumentException When $tag is not valid */ public function tag($tags) { - if (!is_array($tags)) { - $tags = array($tags); + if (!\is_array($tags)) { + $tags = [$tags]; } foreach ($tags as $tag) { - if (!is_string($tag)) { - throw new InvalidArgumentException(sprintf('Cache tag must be string, "%s" given', is_object($tag) ? get_class($tag) : gettype($tag))); + if (!\is_string($tag)) { + throw new InvalidArgumentException(sprintf('Cache tag must be string, "%s" given.', \is_object($tag) ? \get_class($tag) : \gettype($tag))); } if (isset($this->tags[$tag])) { continue; } - if (!isset($tag[0])) { - throw new InvalidArgumentException('Cache tag length must be greater than zero'); + if ('' === $tag) { + throw new InvalidArgumentException('Cache tag length must be greater than zero.'); } if (false !== strpbrk($tag, '{}()/\@:')) { - throw new InvalidArgumentException(sprintf('Cache tag "%s" contains reserved characters {}()/\@:', $tag)); + throw new InvalidArgumentException(sprintf('Cache tag "%s" contains reserved characters {}()/\@:.', $tag)); } $this->tags[$tag] = $tag; } @@ -152,14 +157,14 @@ final class CacheItem implements CacheItemInterface */ public static function validateKey($key) { - if (!is_string($key)) { - throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given', is_object($key) ? get_class($key) : gettype($key))); + if (!\is_string($key)) { + throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key))); } - if (!isset($key[0])) { - throw new InvalidArgumentException('Cache key length must be greater than zero'); + if ('' === $key) { + throw new InvalidArgumentException('Cache key length must be greater than zero.'); } if (false !== strpbrk($key, '{}()/\@:')) { - throw new InvalidArgumentException(sprintf('Cache key "%s" contains reserved characters {}()/\@:', $key)); + throw new InvalidArgumentException(sprintf('Cache key "%s" contains reserved characters {}()/\@:.', $key)); } return $key; @@ -170,18 +175,18 @@ final class CacheItem implements CacheItemInterface * * @internal */ - public static function log(LoggerInterface $logger = null, $message, $context = array()) + public static function log(LoggerInterface $logger = null, $message, $context = []) { if ($logger) { $logger->warning($message, $context); } else { - $replace = array(); + $replace = []; foreach ($context as $k => $v) { if (is_scalar($v)) { $replace['{'.$k.'}'] = $v; } } - @trigger_error(strtr($message, $replace), E_USER_WARNING); + @trigger_error(strtr($message, $replace), \E_USER_WARNING); } } } diff --git a/advancedcontentfilter/vendor/symfony/cache/DataCollector/CacheDataCollector.php b/advancedcontentfilter/vendor/symfony/cache/DataCollector/CacheDataCollector.php index ceef45aa0..c9e87d5cc 100644 --- a/advancedcontentfilter/vendor/symfony/cache/DataCollector/CacheDataCollector.php +++ b/advancedcontentfilter/vendor/symfony/cache/DataCollector/CacheDataCollector.php @@ -27,11 +27,10 @@ class CacheDataCollector extends DataCollector implements LateDataCollectorInter /** * @var TraceableAdapter[] */ - private $instances = array(); + private $instances = []; /** - * @param string $name - * @param TraceableAdapter $instance + * @param string $name */ public function addInstance($name, TraceableAdapter $instance) { @@ -43,8 +42,8 @@ class CacheDataCollector extends DataCollector implements LateDataCollectorInter */ public function collect(Request $request, Response $response, \Exception $exception = null) { - $empty = array('calls' => array(), 'config' => array(), 'options' => array(), 'statistics' => array()); - $this->data = array('instances' => $empty, 'total' => $empty); + $empty = ['calls' => [], 'config' => [], 'options' => [], 'statistics' => []]; + $this->data = ['instances' => $empty, 'total' => $empty]; foreach ($this->instances as $name => $instance) { $this->data['instances']['calls'][$name] = $instance->getCalls(); } @@ -55,7 +54,7 @@ class CacheDataCollector extends DataCollector implements LateDataCollectorInter public function reset() { - $this->data = array(); + $this->data = []; foreach ($this->instances as $instance) { $instance->clearCalls(); } @@ -109,9 +108,9 @@ class CacheDataCollector extends DataCollector implements LateDataCollectorInter */ private function calculateStatistics() { - $statistics = array(); + $statistics = []; foreach ($this->data['instances']['calls'] as $name => $calls) { - $statistics[$name] = array( + $statistics[$name] = [ 'calls' => 0, 'time' => 0, 'reads' => 0, @@ -119,34 +118,33 @@ class CacheDataCollector extends DataCollector implements LateDataCollectorInter 'deletes' => 0, 'hits' => 0, 'misses' => 0, - ); + ]; /** @var TraceableAdapterEvent $call */ foreach ($calls as $call) { - $statistics[$name]['calls'] += 1; + ++$statistics[$name]['calls']; $statistics[$name]['time'] += $call->end - $call->start; if ('getItem' === $call->name) { - $statistics[$name]['reads'] += 1; + ++$statistics[$name]['reads']; if ($call->hits) { - $statistics[$name]['hits'] += 1; + ++$statistics[$name]['hits']; } else { - $statistics[$name]['misses'] += 1; + ++$statistics[$name]['misses']; } } elseif ('getItems' === $call->name) { - $count = $call->hits + $call->misses; - $statistics[$name]['reads'] += $count; + $statistics[$name]['reads'] += $call->hits + $call->misses; $statistics[$name]['hits'] += $call->hits; - $statistics[$name]['misses'] += $count - $call->misses; + $statistics[$name]['misses'] += $call->misses; } elseif ('hasItem' === $call->name) { - $statistics[$name]['reads'] += 1; + ++$statistics[$name]['reads']; if (false === $call->result) { - $statistics[$name]['misses'] += 1; + ++$statistics[$name]['misses']; } else { - $statistics[$name]['hits'] += 1; + ++$statistics[$name]['hits']; } } elseif ('save' === $call->name) { - $statistics[$name]['writes'] += 1; + ++$statistics[$name]['writes']; } elseif ('deleteItem' === $call->name) { - $statistics[$name]['deletes'] += 1; + ++$statistics[$name]['deletes']; } } if ($statistics[$name]['reads']) { @@ -165,7 +163,7 @@ class CacheDataCollector extends DataCollector implements LateDataCollectorInter private function calculateTotalStatistics() { $statistics = $this->getStatistics(); - $totals = array( + $totals = [ 'calls' => 0, 'time' => 0, 'reads' => 0, @@ -173,7 +171,7 @@ class CacheDataCollector extends DataCollector implements LateDataCollectorInter 'deletes' => 0, 'hits' => 0, 'misses' => 0, - ); + ]; foreach ($statistics as $name => $values) { foreach ($totals as $key => $value) { $totals[$key] += $statistics[$name][$key]; diff --git a/advancedcontentfilter/vendor/symfony/cache/DoctrineProvider.php b/advancedcontentfilter/vendor/symfony/cache/DoctrineProvider.php index cebe95fbc..4c5cd0cb1 100644 --- a/advancedcontentfilter/vendor/symfony/cache/DoctrineProvider.php +++ b/advancedcontentfilter/vendor/symfony/cache/DoctrineProvider.php @@ -90,7 +90,7 @@ class DoctrineProvider extends CacheProvider implements PruneableInterface, Rese */ protected function doFlush() { - $this->pool->clear(); + return $this->pool->clear(); } /** @@ -98,5 +98,6 @@ class DoctrineProvider extends CacheProvider implements PruneableInterface, Rese */ protected function doGetStats() { + return null; } } diff --git a/advancedcontentfilter/vendor/symfony/cache/LICENSE b/advancedcontentfilter/vendor/symfony/cache/LICENSE index fcd3fa769..a7ec70801 100644 --- a/advancedcontentfilter/vendor/symfony/cache/LICENSE +++ b/advancedcontentfilter/vendor/symfony/cache/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2016-2018 Fabien Potencier +Copyright (c) 2016-2020 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/advancedcontentfilter/vendor/symfony/cache/Simple/AbstractCache.php b/advancedcontentfilter/vendor/symfony/cache/Simple/AbstractCache.php index e666effaf..baedb7374 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Simple/AbstractCache.php +++ b/advancedcontentfilter/vendor/symfony/cache/Simple/AbstractCache.php @@ -15,14 +15,19 @@ use Psr\Log\LoggerAwareInterface; use Psr\SimpleCache\CacheInterface; use Symfony\Component\Cache\CacheItem; use Symfony\Component\Cache\Exception\InvalidArgumentException; -use Symfony\Component\Cache\Traits\AbstractTrait; use Symfony\Component\Cache\ResettableInterface; +use Symfony\Component\Cache\Traits\AbstractTrait; /** * @author Nicolas Grekas */ abstract class AbstractCache implements CacheInterface, LoggerAwareInterface, ResettableInterface { + /** + * @internal + */ + const NS_SEPARATOR = ':'; + use AbstractTrait { deleteItems as private; AbstractTrait::deleteItem as delete; @@ -39,8 +44,8 @@ abstract class AbstractCache implements CacheInterface, LoggerAwareInterface, Re { $this->defaultLifetime = max(0, (int) $defaultLifetime); $this->namespace = '' === $namespace ? '' : CacheItem::validateKey($namespace).':'; - if (null !== $this->maxIdLength && strlen($namespace) > $this->maxIdLength - 24) { - throw new InvalidArgumentException(sprintf('Namespace must be %d chars max, %d given ("%s")', $this->maxIdLength - 24, strlen($namespace), $namespace)); + if (null !== $this->maxIdLength && \strlen($namespace) > $this->maxIdLength - 24) { + throw new InvalidArgumentException(sprintf('Namespace must be %d chars max, %d given ("%s").', $this->maxIdLength - 24, \strlen($namespace), $namespace)); } } @@ -52,11 +57,11 @@ abstract class AbstractCache implements CacheInterface, LoggerAwareInterface, Re $id = $this->getId($key); try { - foreach ($this->doFetch(array($id)) as $value) { + foreach ($this->doFetch([$id]) as $value) { return $value; } } catch (\Exception $e) { - CacheItem::log($this->logger, 'Failed to fetch key "{key}"', array('key' => $key, 'exception' => $e)); + CacheItem::log($this->logger, 'Failed to fetch key "{key}"', ['key' => $key, 'exception' => $e]); } return $default; @@ -69,7 +74,7 @@ abstract class AbstractCache implements CacheInterface, LoggerAwareInterface, Re { CacheItem::validateKey($key); - return $this->setMultiple(array($key => $value), $ttl); + return $this->setMultiple([$key => $value], $ttl); } /** @@ -79,10 +84,10 @@ abstract class AbstractCache implements CacheInterface, LoggerAwareInterface, Re { if ($keys instanceof \Traversable) { $keys = iterator_to_array($keys, false); - } elseif (!is_array($keys)) { - throw new InvalidArgumentException(sprintf('Cache keys must be array or Traversable, "%s" given', is_object($keys) ? get_class($keys) : gettype($keys))); + } elseif (!\is_array($keys)) { + throw new InvalidArgumentException(sprintf('Cache keys must be array or Traversable, "%s" given.', \is_object($keys) ? \get_class($keys) : \gettype($keys))); } - $ids = array(); + $ids = []; foreach ($keys as $key) { $ids[] = $this->getId($key); @@ -90,8 +95,8 @@ abstract class AbstractCache implements CacheInterface, LoggerAwareInterface, Re try { $values = $this->doFetch($ids); } catch (\Exception $e) { - CacheItem::log($this->logger, 'Failed to fetch requested values', array('keys' => $keys, 'exception' => $e)); - $values = array(); + CacheItem::log($this->logger, 'Failed to fetch requested values', ['keys' => $keys, 'exception' => $e]); + $values = []; } $ids = array_combine($ids, $keys); @@ -103,13 +108,13 @@ abstract class AbstractCache implements CacheInterface, LoggerAwareInterface, Re */ public function setMultiple($values, $ttl = null) { - if (!is_array($values) && !$values instanceof \Traversable) { - throw new InvalidArgumentException(sprintf('Cache values must be array or Traversable, "%s" given', is_object($values) ? get_class($values) : gettype($values))); + if (!\is_array($values) && !$values instanceof \Traversable) { + throw new InvalidArgumentException(sprintf('Cache values must be array or Traversable, "%s" given.', \is_object($values) ? \get_class($values) : \gettype($values))); } - $valuesById = array(); + $valuesById = []; foreach ($values as $key => $value) { - if (is_int($key)) { + if (\is_int($key)) { $key = (string) $key; } $valuesById[$this->getId($key)] = $value; @@ -122,14 +127,14 @@ abstract class AbstractCache implements CacheInterface, LoggerAwareInterface, Re $e = $this->doSave($valuesById, $ttl); } catch (\Exception $e) { } - if (true === $e || array() === $e) { + if (true === $e || [] === $e) { return true; } - $keys = array(); - foreach (is_array($e) ? $e : array_keys($valuesById) as $id) { - $keys[] = substr($id, strlen($this->namespace)); + $keys = []; + foreach (\is_array($e) ? $e : array_keys($valuesById) as $id) { + $keys[] = substr($id, \strlen($this->namespace)); } - CacheItem::log($this->logger, 'Failed to save values', array('keys' => $keys, 'exception' => $e instanceof \Exception ? $e : null)); + CacheItem::log($this->logger, 'Failed to save values', ['keys' => $keys, 'exception' => $e instanceof \Exception ? $e : null]); return false; } @@ -141,8 +146,8 @@ abstract class AbstractCache implements CacheInterface, LoggerAwareInterface, Re { if ($keys instanceof \Traversable) { $keys = iterator_to_array($keys, false); - } elseif (!is_array($keys)) { - throw new InvalidArgumentException(sprintf('Cache keys must be array or Traversable, "%s" given', is_object($keys) ? get_class($keys) : gettype($keys))); + } elseif (!\is_array($keys)) { + throw new InvalidArgumentException(sprintf('Cache keys must be array or Traversable, "%s" given.', \is_object($keys) ? \get_class($keys) : \gettype($keys))); } return $this->deleteItems($keys); @@ -156,11 +161,11 @@ abstract class AbstractCache implements CacheInterface, LoggerAwareInterface, Re if ($ttl instanceof \DateInterval) { $ttl = (int) \DateTime::createFromFormat('U', 0)->add($ttl)->format('U'); } - if (is_int($ttl)) { + if (\is_int($ttl)) { return 0 < $ttl ? $ttl : false; } - throw new InvalidArgumentException(sprintf('Expiration date must be an integer, a DateInterval or null, "%s" given', is_object($ttl) ? get_class($ttl) : gettype($ttl))); + throw new InvalidArgumentException(sprintf('Expiration date must be an integer, a DateInterval or null, "%s" given.', \is_object($ttl) ? \get_class($ttl) : \gettype($ttl))); } private function generateValues($values, &$keys, $default) @@ -175,7 +180,7 @@ abstract class AbstractCache implements CacheInterface, LoggerAwareInterface, Re yield $key => $value; } } catch (\Exception $e) { - CacheItem::log($this->logger, 'Failed to fetch requested values', array('keys' => array_values($keys), 'exception' => $e)); + CacheItem::log($this->logger, 'Failed to fetch requested values', ['keys' => array_values($keys), 'exception' => $e]); } foreach ($keys as $key) { diff --git a/advancedcontentfilter/vendor/symfony/cache/Simple/ArrayCache.php b/advancedcontentfilter/vendor/symfony/cache/Simple/ArrayCache.php index 8d027cd2a..6013f0ad2 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Simple/ArrayCache.php +++ b/advancedcontentfilter/vendor/symfony/cache/Simple/ArrayCache.php @@ -45,7 +45,7 @@ class ArrayCache implements CacheInterface, LoggerAwareInterface, ResettableInte */ public function get($key, $default = null) { - foreach ($this->getMultiple(array($key), $default) as $v) { + foreach ($this->getMultiple([$key], $default) as $v) { return $v; } } @@ -57,8 +57,8 @@ class ArrayCache implements CacheInterface, LoggerAwareInterface, ResettableInte { if ($keys instanceof \Traversable) { $keys = iterator_to_array($keys, false); - } elseif (!is_array($keys)) { - throw new InvalidArgumentException(sprintf('Cache keys must be array or Traversable, "%s" given', is_object($keys) ? get_class($keys) : gettype($keys))); + } elseif (!\is_array($keys)) { + throw new InvalidArgumentException(sprintf('Cache keys must be array or Traversable, "%s" given.', \is_object($keys) ? \get_class($keys) : \gettype($keys))); } foreach ($keys as $key) { CacheItem::validateKey($key); @@ -72,8 +72,8 @@ class ArrayCache implements CacheInterface, LoggerAwareInterface, ResettableInte */ public function deleteMultiple($keys) { - if (!is_array($keys) && !$keys instanceof \Traversable) { - throw new InvalidArgumentException(sprintf('Cache keys must be array or Traversable, "%s" given', is_object($keys) ? get_class($keys) : gettype($keys))); + if (!\is_array($keys) && !$keys instanceof \Traversable) { + throw new InvalidArgumentException(sprintf('Cache keys must be array or Traversable, "%s" given.', \is_object($keys) ? \get_class($keys) : \gettype($keys))); } foreach ($keys as $key) { $this->delete($key); @@ -89,7 +89,7 @@ class ArrayCache implements CacheInterface, LoggerAwareInterface, ResettableInte { CacheItem::validateKey($key); - return $this->setMultiple(array($key => $value), $ttl); + return $this->setMultiple([$key => $value], $ttl); } /** @@ -97,13 +97,13 @@ class ArrayCache implements CacheInterface, LoggerAwareInterface, ResettableInte */ public function setMultiple($values, $ttl = null) { - if (!is_array($values) && !$values instanceof \Traversable) { - throw new InvalidArgumentException(sprintf('Cache values must be array or Traversable, "%s" given', is_object($values) ? get_class($values) : gettype($values))); + if (!\is_array($values) && !$values instanceof \Traversable) { + throw new InvalidArgumentException(sprintf('Cache values must be array or Traversable, "%s" given.', \is_object($values) ? \get_class($values) : \gettype($values))); } - $valuesArray = array(); + $valuesArray = []; foreach ($values as $key => $value) { - is_int($key) || CacheItem::validateKey($key); + \is_int($key) || CacheItem::validateKey($key); $valuesArray[$key] = $value; } if (false === $ttl = $this->normalizeTtl($ttl)) { @@ -114,14 +114,14 @@ class ArrayCache implements CacheInterface, LoggerAwareInterface, ResettableInte try { $valuesArray[$key] = serialize($value); } catch (\Exception $e) { - $type = is_object($value) ? get_class($value) : gettype($value); - CacheItem::log($this->logger, 'Failed to save key "{key}" ({type})', array('key' => $key, 'type' => $type, 'exception' => $e)); + $type = \is_object($value) ? \get_class($value) : \gettype($value); + CacheItem::log($this->logger, 'Failed to save key "{key}" ({type})', ['key' => $key, 'type' => $type, 'exception' => $e]); return false; } } } - $expiry = 0 < $ttl ? time() + $ttl : PHP_INT_MAX; + $expiry = 0 < $ttl ? time() + $ttl : \PHP_INT_MAX; foreach ($valuesArray as $key => $value) { $this->values[$key] = $value; @@ -139,10 +139,10 @@ class ArrayCache implements CacheInterface, LoggerAwareInterface, ResettableInte if ($ttl instanceof \DateInterval) { $ttl = (int) \DateTime::createFromFormat('U', 0)->add($ttl)->format('U'); } - if (is_int($ttl)) { + if (\is_int($ttl)) { return 0 < $ttl ? $ttl : false; } - throw new InvalidArgumentException(sprintf('Expiration date must be an integer, a DateInterval or null, "%s" given', is_object($ttl) ? get_class($ttl) : gettype($ttl))); + throw new InvalidArgumentException(sprintf('Expiration date must be an integer, a DateInterval or null, "%s" given.', \is_object($ttl) ? \get_class($ttl) : \gettype($ttl))); } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Simple/ChainCache.php b/advancedcontentfilter/vendor/symfony/cache/Simple/ChainCache.php index 9d0c75870..2e6c7277d 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Simple/ChainCache.php +++ b/advancedcontentfilter/vendor/symfony/cache/Simple/ChainCache.php @@ -27,7 +27,7 @@ use Symfony\Component\Cache\ResettableInterface; class ChainCache implements CacheInterface, PruneableInterface, ResettableInterface { private $miss; - private $caches = array(); + private $caches = []; private $defaultLifetime; private $cacheCount; @@ -43,13 +43,13 @@ class ChainCache implements CacheInterface, PruneableInterface, ResettableInterf foreach ($caches as $cache) { if (!$cache instanceof CacheInterface) { - throw new InvalidArgumentException(sprintf('The class "%s" does not implement the "%s" interface.', get_class($cache), CacheInterface::class)); + throw new InvalidArgumentException(sprintf('The class "%s" does not implement the "%s" interface.', \get_class($cache), CacheInterface::class)); } } $this->miss = new \stdClass(); $this->caches = array_values($caches); - $this->cacheCount = count($this->caches); + $this->cacheCount = \count($this->caches); $this->defaultLifetime = 0 < $defaultLifetime ? (int) $defaultLifetime : null; } @@ -58,7 +58,7 @@ class ChainCache implements CacheInterface, PruneableInterface, ResettableInterf */ public function get($key, $default = null) { - $miss = null !== $default && is_object($default) ? $default : $this->miss; + $miss = null !== $default && \is_object($default) ? $default : $this->miss; foreach ($this->caches as $i => $cache) { $value = $cache->get($key, $miss); @@ -80,14 +80,14 @@ class ChainCache implements CacheInterface, PruneableInterface, ResettableInterf */ public function getMultiple($keys, $default = null) { - $miss = null !== $default && is_object($default) ? $default : $this->miss; + $miss = null !== $default && \is_object($default) ? $default : $this->miss; return $this->generateItems($this->caches[0]->getMultiple($keys, $miss), 0, $miss, $default); } private function generateItems($values, $cacheIndex, $miss, $default) { - $missing = array(); + $missing = []; $nextCacheIndex = $cacheIndex + 1; $nextCache = isset($this->caches[$nextCacheIndex]) ? $this->caches[$nextCacheIndex] : null; @@ -201,7 +201,7 @@ class ChainCache implements CacheInterface, PruneableInterface, ResettableInterf if ($values instanceof \Traversable) { $valuesIterator = $values; $values = function () use ($valuesIterator, &$values) { - $generatedValues = array(); + $generatedValues = []; foreach ($valuesIterator as $key => $value) { yield $key => $value; diff --git a/advancedcontentfilter/vendor/symfony/cache/Simple/DoctrineCache.php b/advancedcontentfilter/vendor/symfony/cache/Simple/DoctrineCache.php index 00f0b9c6f..ea1a4eda5 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Simple/DoctrineCache.php +++ b/advancedcontentfilter/vendor/symfony/cache/Simple/DoctrineCache.php @@ -19,9 +19,8 @@ class DoctrineCache extends AbstractCache use DoctrineTrait; /** - * @param CacheProvider $provider - * @param string $namespace - * @param int $defaultLifetime + * @param string $namespace + * @param int $defaultLifetime */ public function __construct(CacheProvider $provider, $namespace = '', $defaultLifetime = 0) { diff --git a/advancedcontentfilter/vendor/symfony/cache/Simple/MemcachedCache.php b/advancedcontentfilter/vendor/symfony/cache/Simple/MemcachedCache.php index 771774062..94a9f297d 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Simple/MemcachedCache.php +++ b/advancedcontentfilter/vendor/symfony/cache/Simple/MemcachedCache.php @@ -20,9 +20,8 @@ class MemcachedCache extends AbstractCache protected $maxIdLength = 250; /** - * @param \Memcached $client - * @param string $namespace - * @param int $defaultLifetime + * @param string $namespace + * @param int $defaultLifetime */ public function __construct(\Memcached $client, $namespace = '', $defaultLifetime = 0) { diff --git a/advancedcontentfilter/vendor/symfony/cache/Simple/PdoCache.php b/advancedcontentfilter/vendor/symfony/cache/Simple/PdoCache.php index 931a3b1ff..c92e049a1 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Simple/PdoCache.php +++ b/advancedcontentfilter/vendor/symfony/cache/Simple/PdoCache.php @@ -33,7 +33,7 @@ class PdoCache extends AbstractCache implements PruneableInterface * * db_time_col: The column where to store the timestamp [default: item_time] * * db_username: The username when lazy-connect [default: ''] * * db_password: The password when lazy-connect [default: ''] - * * db_connection_options: An array of driver-specific connection options [default: array()] + * * db_connection_options: An array of driver-specific connection options [default: []] * * @param \PDO|Connection|string $connOrDsn A \PDO or Connection instance or DSN string or null * @param string $namespace @@ -44,7 +44,7 @@ class PdoCache extends AbstractCache implements PruneableInterface * @throws InvalidArgumentException When PDO error mode is not PDO::ERRMODE_EXCEPTION * @throws InvalidArgumentException When namespace contains invalid characters */ - public function __construct($connOrDsn, $namespace = '', $defaultLifetime = 0, array $options = array()) + public function __construct($connOrDsn, $namespace = '', $defaultLifetime = 0, array $options = []) { $this->init($connOrDsn, $namespace, $defaultLifetime, $options); } diff --git a/advancedcontentfilter/vendor/symfony/cache/Simple/PhpArrayCache.php b/advancedcontentfilter/vendor/symfony/cache/Simple/PhpArrayCache.php index 3db8a2ac1..7bb25ff80 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Simple/PhpArrayCache.php +++ b/advancedcontentfilter/vendor/symfony/cache/Simple/PhpArrayCache.php @@ -13,9 +13,9 @@ namespace Symfony\Component\Cache\Simple; use Psr\SimpleCache\CacheInterface; use Symfony\Component\Cache\Exception\InvalidArgumentException; -use Symfony\Component\Cache\Traits\PhpArrayTrait; use Symfony\Component\Cache\PruneableInterface; use Symfony\Component\Cache\ResettableInterface; +use Symfony\Component\Cache\Traits\PhpArrayTrait; /** * Caches items at warm up time using a PHP array that is stored in shared memory by OPCache since PHP 7.0. @@ -36,7 +36,7 @@ class PhpArrayCache implements CacheInterface, PruneableInterface, ResettableInt { $this->file = $file; $this->pool = $fallbackPool; - $this->zendDetectUnicode = ini_get('zend.detect_unicode'); + $this->zendDetectUnicode = filter_var(ini_get('zend.detect_unicode'), \FILTER_VALIDATE_BOOLEAN); } /** @@ -44,14 +44,14 @@ class PhpArrayCache implements CacheInterface, PruneableInterface, ResettableInt * stores arrays in its latest versions. This factory method decorates the given * fallback pool with this adapter only if the current PHP version is supported. * - * @param string $file The PHP file were values are cached + * @param string $file The PHP file were values are cached + * @param CacheInterface $fallbackPool A pool to fallback on when an item is not hit * * @return CacheInterface */ public static function create($file, CacheInterface $fallbackPool) { - // Shared memory is available in PHP 7.0+ with OPCache enabled and in HHVM - if ((\PHP_VERSION_ID >= 70000 && ini_get('opcache.enable')) || defined('HHVM_VERSION')) { + if (\PHP_VERSION_ID >= 70000) { return new static($file, $fallbackPool); } @@ -63,8 +63,8 @@ class PhpArrayCache implements CacheInterface, PruneableInterface, ResettableInt */ public function get($key, $default = null) { - if (!is_string($key)) { - throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', is_object($key) ? get_class($key) : gettype($key))); + if (!\is_string($key)) { + throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key))); } if (null === $this->values) { $this->initialize(); @@ -77,7 +77,7 @@ class PhpArrayCache implements CacheInterface, PruneableInterface, ResettableInt if ('N;' === $value) { $value = null; - } elseif (is_string($value) && isset($value[2]) && ':' === $value[1]) { + } elseif (\is_string($value) && isset($value[2]) && ':' === $value[1]) { try { $e = null; $value = unserialize($value); @@ -99,12 +99,12 @@ class PhpArrayCache implements CacheInterface, PruneableInterface, ResettableInt { if ($keys instanceof \Traversable) { $keys = iterator_to_array($keys, false); - } elseif (!is_array($keys)) { - throw new InvalidArgumentException(sprintf('Cache keys must be array or Traversable, "%s" given', is_object($keys) ? get_class($keys) : gettype($keys))); + } elseif (!\is_array($keys)) { + throw new InvalidArgumentException(sprintf('Cache keys must be array or Traversable, "%s" given.', \is_object($keys) ? \get_class($keys) : \gettype($keys))); } foreach ($keys as $key) { - if (!is_string($key)) { - throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', is_object($key) ? get_class($key) : gettype($key))); + if (!\is_string($key)) { + throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key))); } } if (null === $this->values) { @@ -119,8 +119,8 @@ class PhpArrayCache implements CacheInterface, PruneableInterface, ResettableInt */ public function has($key) { - if (!is_string($key)) { - throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', is_object($key) ? get_class($key) : gettype($key))); + if (!\is_string($key)) { + throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key))); } if (null === $this->values) { $this->initialize(); @@ -134,8 +134,8 @@ class PhpArrayCache implements CacheInterface, PruneableInterface, ResettableInt */ public function delete($key) { - if (!is_string($key)) { - throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', is_object($key) ? get_class($key) : gettype($key))); + if (!\is_string($key)) { + throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key))); } if (null === $this->values) { $this->initialize(); @@ -149,16 +149,16 @@ class PhpArrayCache implements CacheInterface, PruneableInterface, ResettableInt */ public function deleteMultiple($keys) { - if (!is_array($keys) && !$keys instanceof \Traversable) { - throw new InvalidArgumentException(sprintf('Cache keys must be array or Traversable, "%s" given', is_object($keys) ? get_class($keys) : gettype($keys))); + if (!\is_array($keys) && !$keys instanceof \Traversable) { + throw new InvalidArgumentException(sprintf('Cache keys must be array or Traversable, "%s" given.', \is_object($keys) ? \get_class($keys) : \gettype($keys))); } $deleted = true; - $fallbackKeys = array(); + $fallbackKeys = []; foreach ($keys as $key) { - if (!is_string($key)) { - throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', is_object($key) ? get_class($key) : gettype($key))); + if (!\is_string($key)) { + throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key))); } if (isset($this->values[$key])) { @@ -183,8 +183,8 @@ class PhpArrayCache implements CacheInterface, PruneableInterface, ResettableInt */ public function set($key, $value, $ttl = null) { - if (!is_string($key)) { - throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', is_object($key) ? get_class($key) : gettype($key))); + if (!\is_string($key)) { + throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key))); } if (null === $this->values) { $this->initialize(); @@ -198,16 +198,16 @@ class PhpArrayCache implements CacheInterface, PruneableInterface, ResettableInt */ public function setMultiple($values, $ttl = null) { - if (!is_array($values) && !$values instanceof \Traversable) { - throw new InvalidArgumentException(sprintf('Cache values must be array or Traversable, "%s" given', is_object($values) ? get_class($values) : gettype($values))); + if (!\is_array($values) && !$values instanceof \Traversable) { + throw new InvalidArgumentException(sprintf('Cache values must be array or Traversable, "%s" given.', \is_object($values) ? \get_class($values) : \gettype($values))); } $saved = true; - $fallbackValues = array(); + $fallbackValues = []; foreach ($values as $key => $value) { - if (!is_string($key) && !is_int($key)) { - throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', is_object($key) ? get_class($key) : gettype($key))); + if (!\is_string($key) && !\is_int($key)) { + throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key))); } if (isset($this->values[$key])) { @@ -226,7 +226,7 @@ class PhpArrayCache implements CacheInterface, PruneableInterface, ResettableInt private function generateItems(array $keys, $default) { - $fallbackKeys = array(); + $fallbackKeys = []; foreach ($keys as $key) { if (isset($this->values[$key])) { @@ -234,7 +234,7 @@ class PhpArrayCache implements CacheInterface, PruneableInterface, ResettableInt if ('N;' === $value) { yield $key => null; - } elseif (is_string($value) && isset($value[2]) && ':' === $value[1]) { + } elseif (\is_string($value) && isset($value[2]) && ':' === $value[1]) { try { yield $key => unserialize($value); } catch (\Error $e) { diff --git a/advancedcontentfilter/vendor/symfony/cache/Simple/PhpFilesCache.php b/advancedcontentfilter/vendor/symfony/cache/Simple/PhpFilesCache.php index 9231c8cd3..50c19034a 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Simple/PhpFilesCache.php +++ b/advancedcontentfilter/vendor/symfony/cache/Simple/PhpFilesCache.php @@ -29,13 +29,13 @@ class PhpFilesCache extends AbstractCache implements PruneableInterface public function __construct($namespace = '', $defaultLifetime = 0, $directory = null) { if (!static::isSupported()) { - throw new CacheException('OPcache is not enabled'); + throw new CacheException('OPcache is not enabled.'); } parent::__construct('', $defaultLifetime); $this->init($namespace, $directory); $e = new \Exception(); $this->includeHandler = function () use ($e) { throw $e; }; - $this->zendDetectUnicode = ini_get('zend.detect_unicode'); + $this->zendDetectUnicode = filter_var(ini_get('zend.detect_unicode'), \FILTER_VALIDATE_BOOLEAN); } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Simple/Psr6Cache.php b/advancedcontentfilter/vendor/symfony/cache/Simple/Psr6Cache.php index 81f14d4a7..6b3de2059 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Simple/Psr6Cache.php +++ b/advancedcontentfilter/vendor/symfony/cache/Simple/Psr6Cache.php @@ -11,11 +11,11 @@ namespace Symfony\Component\Cache\Simple; -use Psr\Cache\CacheItemPoolInterface; use Psr\Cache\CacheException as Psr6CacheException; -use Psr\SimpleCache\CacheInterface; +use Psr\Cache\CacheItemPoolInterface; use Psr\SimpleCache\CacheException as SimpleCacheException; -use Symfony\Component\Cache\Adapter\AbstractAdapter; +use Psr\SimpleCache\CacheInterface; +use Symfony\Component\Cache\Adapter\AdapterInterface; use Symfony\Component\Cache\CacheItem; use Symfony\Component\Cache\Exception\InvalidArgumentException; use Symfony\Component\Cache\PruneableInterface; @@ -30,27 +30,36 @@ class Psr6Cache implements CacheInterface, PruneableInterface, ResettableInterfa use ProxyTrait; private $createCacheItem; + private $cacheItemPrototype; public function __construct(CacheItemPoolInterface $pool) { $this->pool = $pool; - if ($pool instanceof AbstractAdapter) { - $this->createCacheItem = \Closure::bind( - function ($key, $value, $allowInt = false) { - if ($allowInt && is_int($key)) { - $key = (string) $key; - } else { - CacheItem::validateKey($key); - } - $f = $this->createCacheItem; - - return $f($key, $value, false); - }, - $pool, - AbstractAdapter::class - ); + if (!$pool instanceof AdapterInterface) { + return; } + $cacheItemPrototype = &$this->cacheItemPrototype; + $createCacheItem = \Closure::bind( + static function ($key, $value, $allowInt = false) use (&$cacheItemPrototype) { + $item = clone $cacheItemPrototype; + $item->key = $allowInt && \is_int($key) ? (string) $key : CacheItem::validateKey($key); + $item->value = $value; + $item->isHit = false; + + return $item; + }, + null, + CacheItem::class + ); + $this->createCacheItem = function ($key, $value, $allowInt = false) use ($createCacheItem) { + if (null === $this->cacheItemPrototype) { + $this->get($allowInt && \is_int($key) ? (string) $key : $key); + } + $this->createCacheItem = $createCacheItem; + + return $createCacheItem($key, $value, $allowInt); + }; } /** @@ -65,6 +74,10 @@ class Psr6Cache implements CacheInterface, PruneableInterface, ResettableInterfa } catch (Psr6CacheException $e) { throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); } + if (null === $this->cacheItemPrototype) { + $this->cacheItemPrototype = clone $item; + $this->cacheItemPrototype->set(null); + } return $item->isHit() ? $item->get() : $default; } @@ -121,8 +134,8 @@ class Psr6Cache implements CacheInterface, PruneableInterface, ResettableInterfa { if ($keys instanceof \Traversable) { $keys = iterator_to_array($keys, false); - } elseif (!is_array($keys)) { - throw new InvalidArgumentException(sprintf('Cache keys must be array or Traversable, "%s" given', is_object($keys) ? get_class($keys) : gettype($keys))); + } elseif (!\is_array($keys)) { + throw new InvalidArgumentException(sprintf('Cache keys must be array or Traversable, "%s" given.', \is_object($keys) ? \get_class($keys) : \gettype($keys))); } try { @@ -132,7 +145,7 @@ class Psr6Cache implements CacheInterface, PruneableInterface, ResettableInterfa } catch (Psr6CacheException $e) { throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); } - $values = array(); + $values = []; foreach ($items as $key => $item) { $values[$key] = $item->isHit() ? $item->get() : $default; @@ -146,11 +159,11 @@ class Psr6Cache implements CacheInterface, PruneableInterface, ResettableInterfa */ public function setMultiple($values, $ttl = null) { - $valuesIsArray = is_array($values); + $valuesIsArray = \is_array($values); if (!$valuesIsArray && !$values instanceof \Traversable) { - throw new InvalidArgumentException(sprintf('Cache values must be array or Traversable, "%s" given', is_object($values) ? get_class($values) : gettype($values))); + throw new InvalidArgumentException(sprintf('Cache values must be array or Traversable, "%s" given.', \is_object($values) ? \get_class($values) : \gettype($values))); } - $items = array(); + $items = []; try { if (null !== $f = $this->createCacheItem) { @@ -159,14 +172,14 @@ class Psr6Cache implements CacheInterface, PruneableInterface, ResettableInterfa $items[$key] = $f($key, $value, true); } } elseif ($valuesIsArray) { - $items = array(); + $items = []; foreach ($values as $key => $value) { $items[] = (string) $key; } $items = $this->pool->getItems($items); } else { foreach ($values as $key => $value) { - if (is_int($key)) { + if (\is_int($key)) { $key = (string) $key; } $items[$key] = $this->pool->getItem($key)->set($value); @@ -199,8 +212,8 @@ class Psr6Cache implements CacheInterface, PruneableInterface, ResettableInterfa { if ($keys instanceof \Traversable) { $keys = iterator_to_array($keys, false); - } elseif (!is_array($keys)) { - throw new InvalidArgumentException(sprintf('Cache keys must be array or Traversable, "%s" given', is_object($keys) ? get_class($keys) : gettype($keys))); + } elseif (!\is_array($keys)) { + throw new InvalidArgumentException(sprintf('Cache keys must be array or Traversable, "%s" given.', \is_object($keys) ? \get_class($keys) : \gettype($keys))); } try { diff --git a/advancedcontentfilter/vendor/symfony/cache/Simple/TraceableCache.php b/advancedcontentfilter/vendor/symfony/cache/Simple/TraceableCache.php index 756403bf1..61b22963e 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Simple/TraceableCache.php +++ b/advancedcontentfilter/vendor/symfony/cache/Simple/TraceableCache.php @@ -24,7 +24,7 @@ class TraceableCache implements CacheInterface, PruneableInterface, ResettableIn { private $pool; private $miss; - private $calls = array(); + private $calls = []; public function __construct(CacheInterface $pool) { @@ -37,7 +37,7 @@ class TraceableCache implements CacheInterface, PruneableInterface, ResettableIn */ public function get($key, $default = null) { - $miss = null !== $default && is_object($default) ? $default : $this->miss; + $miss = null !== $default && \is_object($default) ? $default : $this->miss; $event = $this->start(__FUNCTION__); try { $value = $this->pool->get($key, $miss); @@ -99,7 +99,7 @@ class TraceableCache implements CacheInterface, PruneableInterface, ResettableIn public function setMultiple($values, $ttl = null) { $event = $this->start(__FUNCTION__); - $event->result['keys'] = array(); + $event->result['keys'] = []; if ($values instanceof \Traversable) { $values = function () use ($values, $event) { @@ -109,7 +109,7 @@ class TraceableCache implements CacheInterface, PruneableInterface, ResettableIn } }; $values = $values(); - } elseif (is_array($values)) { + } elseif (\is_array($values)) { $event->result['keys'] = array_keys($values); } @@ -125,7 +125,7 @@ class TraceableCache implements CacheInterface, PruneableInterface, ResettableIn */ public function getMultiple($keys, $default = null) { - $miss = null !== $default && is_object($default) ? $default : $this->miss; + $miss = null !== $default && \is_object($default) ? $default : $this->miss; $event = $this->start(__FUNCTION__); try { $result = $this->pool->getMultiple($keys, $miss); @@ -133,7 +133,7 @@ class TraceableCache implements CacheInterface, PruneableInterface, ResettableIn $event->end = microtime(true); } $f = function () use ($result, $event, $miss, $default) { - $event->result = array(); + $event->result = []; foreach ($result as $key => $value) { if ($event->result[$key] = $miss !== $value) { ++$event->hits; @@ -216,7 +216,7 @@ class TraceableCache implements CacheInterface, PruneableInterface, ResettableIn try { return $this->calls; } finally { - $this->calls = array(); + $this->calls = []; } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/AbstractRedisAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/AbstractRedisAdapterTest.php index d9353821a..0e8ed0012 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/AbstractRedisAdapterTest.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/AbstractRedisAdapterTest.php @@ -15,11 +15,11 @@ use Symfony\Component\Cache\Adapter\RedisAdapter; abstract class AbstractRedisAdapterTest extends AdapterTestCase { - protected $skippedTests = array( + protected $skippedTests = [ 'testExpiration' => 'Testing expiration slows down the test suite', 'testHasItemReturnsFalseWhenDeferredItemIsExpired' => 'Testing expiration slows down the test suite', 'testDefaultLifeTime' => 'Testing expiration slows down the test suite', - ); + ]; protected static $redis; @@ -28,14 +28,15 @@ abstract class AbstractRedisAdapterTest extends AdapterTestCase return new RedisAdapter(self::$redis, str_replace('\\', '.', __CLASS__), $defaultLifetime); } - public static function setupBeforeClass() + public static function setUpBeforeClass() { - if (!extension_loaded('redis')) { + if (!\extension_loaded('redis')) { self::markTestSkipped('Extension redis required.'); } - if (!@((new \Redis())->connect(getenv('REDIS_HOST')))) { - $e = error_get_last(); - self::markTestSkipped($e['message']); + try { + (new \Redis())->connect(getenv('REDIS_HOST')); + } catch (\Exception $e) { + self::markTestSkipped($e->getMessage()); } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/AdapterTestCase.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/AdapterTestCase.php index a0b74b474..5758a2861 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/AdapterTestCase.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/AdapterTestCase.php @@ -21,11 +21,11 @@ abstract class AdapterTestCase extends CachePoolTest { parent::setUp(); - if (!array_key_exists('testDeferredSaveWithoutCommit', $this->skippedTests) && defined('HHVM_VERSION')) { + if (!\array_key_exists('testDeferredSaveWithoutCommit', $this->skippedTests) && \defined('HHVM_VERSION')) { $this->skippedTests['testDeferredSaveWithoutCommit'] = 'Destructors are called late on HHVM.'; } - if (!array_key_exists('testPrune', $this->skippedTests) && !$this->createCachePool() instanceof PruneableInterface) { + if (!\array_key_exists('testPrune', $this->skippedTests) && !$this->createCachePool() instanceof PruneableInterface) { $this->skippedTests['testPrune'] = 'Not a pruneable cache pool.'; } } @@ -85,11 +85,11 @@ abstract class AdapterTestCase extends CachePoolTest $item = $cache->getItem('foo'); $this->assertFalse($item->isHit()); - foreach ($cache->getItems(array('foo')) as $item) { + foreach ($cache->getItems(['foo']) as $item) { } $cache->save($item->set(new NotUnserializable())); - foreach ($cache->getItems(array('foo')) as $item) { + foreach ($cache->getItems(['foo']) as $item) { } $this->assertFalse($item->isHit()); } diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ApcuAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ApcuAdapterTest.php index 72df12e4b..f55a1b9b8 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ApcuAdapterTest.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ApcuAdapterTest.php @@ -16,23 +16,23 @@ use Symfony\Component\Cache\Adapter\ApcuAdapter; class ApcuAdapterTest extends AdapterTestCase { - protected $skippedTests = array( + protected $skippedTests = [ 'testExpiration' => 'Testing expiration slows down the test suite', 'testHasItemReturnsFalseWhenDeferredItemIsExpired' => 'Testing expiration slows down the test suite', 'testDefaultLifeTime' => 'Testing expiration slows down the test suite', - ); + ]; public function createCachePool($defaultLifetime = 0) { - if (!function_exists('apcu_fetch') || !ini_get('apc.enabled')) { + if (!\function_exists('apcu_fetch') || !filter_var(ini_get('apc.enabled'), \FILTER_VALIDATE_BOOLEAN)) { $this->markTestSkipped('APCu extension is required.'); } - if ('cli' === PHP_SAPI && !ini_get('apc.enable_cli')) { + if ('cli' === \PHP_SAPI && !filter_var(ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOLEAN)) { if ('testWithCliSapi' !== $this->getName()) { $this->markTestSkipped('apc.enable_cli=1 is required.'); } } - if ('\\' === DIRECTORY_SEPARATOR) { + if ('\\' === \DIRECTORY_SEPARATOR) { $this->markTestSkipped('Fails transiently on Windows.'); } @@ -54,7 +54,7 @@ class ApcuAdapterTest extends AdapterTestCase public function testVersion() { - $namespace = str_replace('\\', '.', get_class($this)); + $namespace = str_replace('\\', '.', static::class); $pool1 = new ApcuAdapter($namespace, 0, 'p1'); @@ -79,7 +79,7 @@ class ApcuAdapterTest extends AdapterTestCase public function testNamespace() { - $namespace = str_replace('\\', '.', get_class($this)); + $namespace = str_replace('\\', '.', static::class); $pool1 = new ApcuAdapter($namespace.'_1', 0, 'p1'); diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ArrayAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ArrayAdapterTest.php index 725d79015..e6adc9d01 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ArrayAdapterTest.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ArrayAdapterTest.php @@ -18,10 +18,10 @@ use Symfony\Component\Cache\Adapter\ArrayAdapter; */ class ArrayAdapterTest extends AdapterTestCase { - protected $skippedTests = array( + protected $skippedTests = [ 'testDeferredSaveWithoutCommit' => 'Assumes a shared cache which ArrayAdapter is not.', 'testSaveWithoutExpire' => 'Assumes a shared cache which ArrayAdapter is not.', - ); + ]; public function createCachePool($defaultLifetime = 0) { diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ChainAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ChainAdapterTest.php index 293a90cc8..be811d6fd 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ChainAdapterTest.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ChainAdapterTest.php @@ -11,10 +11,11 @@ namespace Symfony\Component\Cache\Tests\Adapter; +use PHPUnit\Framework\MockObject\MockObject; use Symfony\Component\Cache\Adapter\AdapterInterface; -use Symfony\Component\Cache\Adapter\FilesystemAdapter; use Symfony\Component\Cache\Adapter\ArrayAdapter; use Symfony\Component\Cache\Adapter\ChainAdapter; +use Symfony\Component\Cache\Adapter\FilesystemAdapter; use Symfony\Component\Cache\PruneableInterface; use Symfony\Component\Cache\Tests\Fixtures\ExternalAdapter; @@ -26,25 +27,21 @@ class ChainAdapterTest extends AdapterTestCase { public function createCachePool($defaultLifetime = 0) { - return new ChainAdapter(array(new ArrayAdapter($defaultLifetime), new ExternalAdapter(), new FilesystemAdapter('', $defaultLifetime)), $defaultLifetime); + return new ChainAdapter([new ArrayAdapter($defaultLifetime), new ExternalAdapter($defaultLifetime), new FilesystemAdapter('', $defaultLifetime)], $defaultLifetime); } - /** - * @expectedException \Symfony\Component\Cache\Exception\InvalidArgumentException - * @expectedExceptionMessage At least one adapter must be specified. - */ public function testEmptyAdaptersException() { - new ChainAdapter(array()); + $this->expectException('Symfony\Component\Cache\Exception\InvalidArgumentException'); + $this->expectExceptionMessage('At least one adapter must be specified.'); + new ChainAdapter([]); } - /** - * @expectedException \Symfony\Component\Cache\Exception\InvalidArgumentException - * @expectedExceptionMessage The class "stdClass" does not implement - */ public function testInvalidAdapterException() { - new ChainAdapter(array(new \stdClass())); + $this->expectException('Symfony\Component\Cache\Exception\InvalidArgumentException'); + $this->expectExceptionMessage('The class "stdClass" does not implement'); + new ChainAdapter([new \stdClass()]); } public function testPrune() @@ -53,23 +50,141 @@ class ChainAdapterTest extends AdapterTestCase $this->markTestSkipped($this->skippedTests[__FUNCTION__]); } - $cache = new ChainAdapter(array( + $cache = new ChainAdapter([ $this->getPruneableMock(), $this->getNonPruneableMock(), $this->getPruneableMock(), - )); + ]); $this->assertTrue($cache->prune()); - $cache = new ChainAdapter(array( + $cache = new ChainAdapter([ $this->getPruneableMock(), $this->getFailingPruneableMock(), $this->getPruneableMock(), - )); + ]); $this->assertFalse($cache->prune()); } + public function testMultipleCachesExpirationWhenCommonTtlIsNotSet() + { + if (isset($this->skippedTests[__FUNCTION__])) { + $this->markTestSkipped($this->skippedTests[__FUNCTION__]); + } + + $adapter1 = new ArrayAdapter(4); + $adapter2 = new ArrayAdapter(2); + + $cache = new ChainAdapter([$adapter1, $adapter2]); + + $cache->save($cache->getItem('key')->set('value')); + + $item = $adapter1->getItem('key'); + $this->assertTrue($item->isHit()); + $this->assertEquals('value', $item->get()); + + $item = $adapter2->getItem('key'); + $this->assertTrue($item->isHit()); + $this->assertEquals('value', $item->get()); + + sleep(2); + + $item = $adapter1->getItem('key'); + $this->assertTrue($item->isHit()); + $this->assertEquals('value', $item->get()); + + $item = $adapter2->getItem('key'); + $this->assertFalse($item->isHit()); + + sleep(2); + + $item = $adapter1->getItem('key'); + $this->assertFalse($item->isHit()); + + $adapter2->save($adapter2->getItem('key1')->set('value1')); + + $item = $cache->getItem('key1'); + $this->assertTrue($item->isHit()); + $this->assertEquals('value1', $item->get()); + + sleep(2); + + $item = $adapter1->getItem('key1'); + $this->assertTrue($item->isHit()); + $this->assertEquals('value1', $item->get()); + + $item = $adapter2->getItem('key1'); + $this->assertFalse($item->isHit()); + + sleep(2); + + $item = $adapter1->getItem('key1'); + $this->assertFalse($item->isHit()); + } + + public function testMultipleCachesExpirationWhenCommonTtlIsSet() + { + if (isset($this->skippedTests[__FUNCTION__])) { + $this->markTestSkipped($this->skippedTests[__FUNCTION__]); + } + + $adapter1 = new ArrayAdapter(4); + $adapter2 = new ArrayAdapter(2); + + $cache = new ChainAdapter([$adapter1, $adapter2], 6); + + $cache->save($cache->getItem('key')->set('value')); + + $item = $adapter1->getItem('key'); + $this->assertTrue($item->isHit()); + $this->assertEquals('value', $item->get()); + + $item = $adapter2->getItem('key'); + $this->assertTrue($item->isHit()); + $this->assertEquals('value', $item->get()); + + sleep(2); + + $item = $adapter1->getItem('key'); + $this->assertTrue($item->isHit()); + $this->assertEquals('value', $item->get()); + + $item = $adapter2->getItem('key'); + $this->assertFalse($item->isHit()); + + sleep(2); + + $item = $adapter1->getItem('key'); + $this->assertFalse($item->isHit()); + + $adapter2->save($adapter2->getItem('key1')->set('value1')); + + $item = $cache->getItem('key1'); + $this->assertTrue($item->isHit()); + $this->assertEquals('value1', $item->get()); + + sleep(2); + + $item = $adapter1->getItem('key1'); + $this->assertTrue($item->isHit()); + $this->assertEquals('value1', $item->get()); + + $item = $adapter2->getItem('key1'); + $this->assertFalse($item->isHit()); + + sleep(2); + + $item = $adapter1->getItem('key1'); + $this->assertTrue($item->isHit()); + $this->assertEquals('value1', $item->get()); + + sleep(2); + + $item = $adapter1->getItem('key1'); + $this->assertFalse($item->isHit()); + } + /** - * @return \PHPUnit_Framework_MockObject_MockObject|PruneableCacheInterface + * @return MockObject|PruneableCacheInterface */ private function getPruneableMock() { @@ -80,13 +195,13 @@ class ChainAdapterTest extends AdapterTestCase $pruneable ->expects($this->atLeastOnce()) ->method('prune') - ->will($this->returnValue(true)); + ->willReturn(true); return $pruneable; } /** - * @return \PHPUnit_Framework_MockObject_MockObject|PruneableCacheInterface + * @return MockObject|PruneableCacheInterface */ private function getFailingPruneableMock() { @@ -97,13 +212,13 @@ class ChainAdapterTest extends AdapterTestCase $pruneable ->expects($this->atLeastOnce()) ->method('prune') - ->will($this->returnValue(false)); + ->willReturn(false); return $pruneable; } /** - * @return \PHPUnit_Framework_MockObject_MockObject|AdapterInterface + * @return MockObject|AdapterInterface */ private function getNonPruneableMock() { diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/DoctrineAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/DoctrineAdapterTest.php index 8d4dfe285..8f520cb59 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/DoctrineAdapterTest.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/DoctrineAdapterTest.php @@ -19,11 +19,11 @@ use Symfony\Component\Cache\Tests\Fixtures\ArrayCache; */ class DoctrineAdapterTest extends AdapterTestCase { - protected $skippedTests = array( + protected $skippedTests = [ 'testDeferredSaveWithoutCommit' => 'Assumes a shared cache which ArrayCache is not.', 'testSaveWithoutExpire' => 'Assumes a shared cache which ArrayCache is not.', 'testNotUnserializable' => 'ArrayCache does not use serialize/unserialize', - ); + ]; public function createCachePool($defaultLifetime = 0) { diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/FilesystemAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/FilesystemAdapterTest.php index b6757514e..fa8306826 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/FilesystemAdapterTest.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/FilesystemAdapterTest.php @@ -34,7 +34,7 @@ class FilesystemAdapterTest extends AdapterTestCase if (!file_exists($dir)) { return; } - if (!$dir || 0 !== strpos(dirname($dir), sys_get_temp_dir())) { + if (!$dir || 0 !== strpos(\dirname($dir), sys_get_temp_dir())) { throw new \Exception(__METHOD__."() operates only on subdirs of system's temp dir"); } $children = new \RecursiveIteratorIterator( diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/MaxIdLengthAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/MaxIdLengthAdapterTest.php index cf2384c5f..536e2c2d4 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/MaxIdLengthAdapterTest.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/MaxIdLengthAdapterTest.php @@ -19,29 +19,59 @@ class MaxIdLengthAdapterTest extends TestCase public function testLongKey() { $cache = $this->getMockBuilder(MaxIdLengthAdapter::class) - ->setConstructorArgs(array(str_repeat('-', 10))) - ->setMethods(array('doHave', 'doFetch', 'doDelete', 'doSave', 'doClear')) + ->setConstructorArgs([str_repeat('-', 10)]) + ->setMethods(['doHave', 'doFetch', 'doDelete', 'doSave', 'doClear']) ->getMock(); $cache->expects($this->exactly(2)) ->method('doHave') ->withConsecutive( - array($this->equalTo('----------:0GTYWa9n4ed8vqNlOT2iEr:')), - array($this->equalTo('----------:---------------------------------------')) + [$this->equalTo('----------:0GTYWa9n4ed8vqNlOT2iEr:')], + [$this->equalTo('----------:---------------------------------------')] ); $cache->hasItem(str_repeat('-', 40)); $cache->hasItem(str_repeat('-', 39)); } - /** - * @expectedException \Symfony\Component\Cache\Exception\InvalidArgumentException - * @expectedExceptionMessage Namespace must be 26 chars max, 40 given ("----------------------------------------") - */ - public function testTooLongNamespace() + public function testLongKeyVersioning() { $cache = $this->getMockBuilder(MaxIdLengthAdapter::class) - ->setConstructorArgs(array(str_repeat('-', 40))) + ->setConstructorArgs([str_repeat('-', 26)]) + ->getMock(); + + $cache + ->method('doFetch') + ->willReturn(['2:']); + + $reflectionClass = new \ReflectionClass(AbstractAdapter::class); + + $reflectionMethod = $reflectionClass->getMethod('getId'); + $reflectionMethod->setAccessible(true); + + // No versioning enabled + $this->assertEquals('--------------------------:------------', $reflectionMethod->invokeArgs($cache, [str_repeat('-', 12)])); + $this->assertLessThanOrEqual(50, \strlen($reflectionMethod->invokeArgs($cache, [str_repeat('-', 12)]))); + $this->assertLessThanOrEqual(50, \strlen($reflectionMethod->invokeArgs($cache, [str_repeat('-', 23)]))); + $this->assertLessThanOrEqual(50, \strlen($reflectionMethod->invokeArgs($cache, [str_repeat('-', 40)]))); + + $reflectionProperty = $reflectionClass->getProperty('versioningIsEnabled'); + $reflectionProperty->setAccessible(true); + $reflectionProperty->setValue($cache, true); + + // Versioning enabled + $this->assertEquals('--------------------------:2:------------', $reflectionMethod->invokeArgs($cache, [str_repeat('-', 12)])); + $this->assertLessThanOrEqual(50, \strlen($reflectionMethod->invokeArgs($cache, [str_repeat('-', 12)]))); + $this->assertLessThanOrEqual(50, \strlen($reflectionMethod->invokeArgs($cache, [str_repeat('-', 23)]))); + $this->assertLessThanOrEqual(50, \strlen($reflectionMethod->invokeArgs($cache, [str_repeat('-', 40)]))); + } + + public function testTooLongNamespace() + { + $this->expectException('Symfony\Component\Cache\Exception\InvalidArgumentException'); + $this->expectExceptionMessage('Namespace must be 26 chars max, 40 given ("----------------------------------------")'); + $this->getMockBuilder(MaxIdLengthAdapter::class) + ->setConstructorArgs([str_repeat('-', 40)]) ->getMock(); } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/MemcachedAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/MemcachedAdapterTest.php index 76e060800..a9a397dd4 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/MemcachedAdapterTest.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/MemcachedAdapterTest.php @@ -16,19 +16,19 @@ use Symfony\Component\Cache\Adapter\MemcachedAdapter; class MemcachedAdapterTest extends AdapterTestCase { - protected $skippedTests = array( + protected $skippedTests = [ 'testHasItemReturnsFalseWhenDeferredItemIsExpired' => 'Testing expiration slows down the test suite', 'testDefaultLifeTime' => 'Testing expiration slows down the test suite', - ); + ]; protected static $client; - public static function setupBeforeClass() + public static function setUpBeforeClass() { if (!MemcachedAdapter::isSupported()) { self::markTestSkipped('Extension memcached >=2.2.0 required.'); } - self::$client = AbstractAdapter::createConnection('memcached://'.getenv('MEMCACHED_HOST'), array('binary_protocol' => false)); + self::$client = AbstractAdapter::createConnection('memcached://'.getenv('MEMCACHED_HOST'), ['binary_protocol' => false]); self::$client->get('foo'); $code = self::$client->getResultCode(); @@ -46,13 +46,13 @@ class MemcachedAdapterTest extends AdapterTestCase public function testOptions() { - $client = MemcachedAdapter::createConnection(array(), array( + $client = MemcachedAdapter::createConnection([], [ 'libketama_compatible' => false, 'distribution' => 'modula', 'compression' => true, 'serializer' => 'php', 'hash' => 'md5', - )); + ]); $this->assertSame(\Memcached::SERIALIZER_PHP, $client->getOption(\Memcached::OPT_SERIALIZER)); $this->assertSame(\Memcached::HASH_MD5, $client->getOption(\Memcached::OPT_HASH)); @@ -63,46 +63,51 @@ class MemcachedAdapterTest extends AdapterTestCase /** * @dataProvider provideBadOptions - * @expectedException \ErrorException - * @expectedExceptionMessage constant(): Couldn't find constant Memcached:: */ public function testBadOptions($name, $value) { - MemcachedAdapter::createConnection(array(), array($name => $value)); + if (\PHP_VERSION_ID < 80000) { + $this->expectException('ErrorException'); + $this->expectExceptionMessage('constant(): Couldn\'t find constant Memcached::'); + } else { + $this->expectException('Error'); + $this->expectExceptionMessage('Undefined constant Memcached::'); + } + + MemcachedAdapter::createConnection([], [$name => $value]); } public function provideBadOptions() { - return array( - array('foo', 'bar'), - array('hash', 'zyx'), - array('serializer', 'zyx'), - array('distribution', 'zyx'), - ); + return [ + ['foo', 'bar'], + ['hash', 'zyx'], + ['serializer', 'zyx'], + ['distribution', 'zyx'], + ]; } public function testDefaultOptions() { $this->assertTrue(MemcachedAdapter::isSupported()); - $client = MemcachedAdapter::createConnection(array()); + $client = MemcachedAdapter::createConnection([]); $this->assertTrue($client->getOption(\Memcached::OPT_COMPRESSION)); $this->assertSame(1, $client->getOption(\Memcached::OPT_BINARY_PROTOCOL)); + $this->assertSame(1, $client->getOption(\Memcached::OPT_TCP_NODELAY)); $this->assertSame(1, $client->getOption(\Memcached::OPT_LIBKETAMA_COMPATIBLE)); } - /** - * @expectedException \Symfony\Component\Cache\Exception\CacheException - * @expectedExceptionMessage MemcachedAdapter: "serializer" option must be "php" or "igbinary". - */ public function testOptionSerializer() { + $this->expectException('Symfony\Component\Cache\Exception\CacheException'); + $this->expectExceptionMessage('MemcachedAdapter: "serializer" option must be "php" or "igbinary".'); if (!\Memcached::HAVE_JSON) { $this->markTestSkipped('Memcached::HAVE_JSON required'); } - new MemcachedAdapter(MemcachedAdapter::createConnection(array(), array('serializer' => 'json'))); + new MemcachedAdapter(MemcachedAdapter::createConnection([], ['serializer' => 'json'])); } /** @@ -111,54 +116,54 @@ class MemcachedAdapterTest extends AdapterTestCase public function testServersSetting($dsn, $host, $port) { $client1 = MemcachedAdapter::createConnection($dsn); - $client2 = MemcachedAdapter::createConnection(array($dsn)); - $client3 = MemcachedAdapter::createConnection(array(array($host, $port))); - $expect = array( + $client2 = MemcachedAdapter::createConnection([$dsn]); + $client3 = MemcachedAdapter::createConnection([[$host, $port]]); + $expect = [ 'host' => $host, 'port' => $port, - ); + ]; - $f = function ($s) { return array('host' => $s['host'], 'port' => $s['port']); }; - $this->assertSame(array($expect), array_map($f, $client1->getServerList())); - $this->assertSame(array($expect), array_map($f, $client2->getServerList())); - $this->assertSame(array($expect), array_map($f, $client3->getServerList())); + $f = function ($s) { return ['host' => $s['host'], 'port' => $s['port']]; }; + $this->assertSame([$expect], array_map($f, $client1->getServerList())); + $this->assertSame([$expect], array_map($f, $client2->getServerList())); + $this->assertSame([$expect], array_map($f, $client3->getServerList())); } public function provideServersSetting() { - yield array( + yield [ 'memcached://127.0.0.1/50', '127.0.0.1', 11211, - ); - yield array( + ]; + yield [ 'memcached://localhost:11222?weight=25', 'localhost', 11222, - ); - if (ini_get('memcached.use_sasl')) { - yield array( + ]; + if (filter_var(ini_get('memcached.use_sasl'), \FILTER_VALIDATE_BOOLEAN)) { + yield [ 'memcached://user:password@127.0.0.1?weight=50', '127.0.0.1', 11211, - ); + ]; } - yield array( + yield [ 'memcached:///var/run/memcached.sock?weight=25', '/var/run/memcached.sock', 0, - ); - yield array( + ]; + yield [ 'memcached:///var/local/run/memcached.socket?weight=25', '/var/local/run/memcached.socket', 0, - ); - if (ini_get('memcached.use_sasl')) { - yield array( + ]; + if (filter_var(ini_get('memcached.use_sasl'), \FILTER_VALIDATE_BOOLEAN)) { + yield [ 'memcached://user:password@/var/local/run/memcached.socket?weight=25', '/var/local/run/memcached.socket', 0, - ); + ]; } } @@ -180,15 +185,20 @@ class MemcachedAdapterTest extends AdapterTestCase self::markTestSkipped('Extension memcached required.'); } - yield array( + yield [ 'memcached://localhost:11222?retry_timeout=10', - array(\Memcached::OPT_RETRY_TIMEOUT => 8), - array(\Memcached::OPT_RETRY_TIMEOUT => 10), - ); - yield array( + [\Memcached::OPT_RETRY_TIMEOUT => 8], + [\Memcached::OPT_RETRY_TIMEOUT => 10], + ]; + yield [ 'memcached://localhost:11222?socket_recv_size=1&socket_send_size=2', - array(\Memcached::OPT_RETRY_TIMEOUT => 8), - array(\Memcached::OPT_SOCKET_RECV_SIZE => 1, \Memcached::OPT_SOCKET_SEND_SIZE => 2, \Memcached::OPT_RETRY_TIMEOUT => 8), - ); + [\Memcached::OPT_RETRY_TIMEOUT => 8], + [\Memcached::OPT_SOCKET_RECV_SIZE => 1, \Memcached::OPT_SOCKET_SEND_SIZE => 2, \Memcached::OPT_RETRY_TIMEOUT => 8], + ]; + } + + public function testClear() + { + $this->assertTrue($this->createCachePool()->clear()); } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/NullAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/NullAdapterTest.php index 73e5cad55..b771fa0ed 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/NullAdapterTest.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/NullAdapterTest.php @@ -43,7 +43,7 @@ class NullAdapterTest extends TestCase { $adapter = $this->createCachePool(); - $keys = array('foo', 'bar', 'baz', 'biz'); + $keys = ['foo', 'bar', 'baz', 'biz']; /** @var CacheItemInterface[] $items */ $items = $adapter->getItems($keys); @@ -89,7 +89,7 @@ class NullAdapterTest extends TestCase public function testDeleteItems() { - $this->assertTrue($this->createCachePool()->deleteItems(array('key', 'foo', 'bar'))); + $this->assertTrue($this->createCachePool()->deleteItems(['key', 'foo', 'bar'])); } public function testSave() diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PdoAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PdoAdapterTest.php index 24e3f9bbc..dd2a91185 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PdoAdapterTest.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PdoAdapterTest.php @@ -23,9 +23,9 @@ class PdoAdapterTest extends AdapterTestCase protected static $dbFile; - public static function setupBeforeClass() + public static function setUpBeforeClass() { - if (!extension_loaded('pdo_sqlite')) { + if (!\extension_loaded('pdo_sqlite')) { self::markTestSkipped('Extension pdo_sqlite required.'); } diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PdoDbalAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PdoDbalAdapterTest.php index 1e8c6155b..aa53958cf 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PdoDbalAdapterTest.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PdoDbalAdapterTest.php @@ -24,15 +24,15 @@ class PdoDbalAdapterTest extends AdapterTestCase protected static $dbFile; - public static function setupBeforeClass() + public static function setUpBeforeClass() { - if (!extension_loaded('pdo_sqlite')) { + if (!\extension_loaded('pdo_sqlite')) { self::markTestSkipped('Extension pdo_sqlite required.'); } self::$dbFile = tempnam(sys_get_temp_dir(), 'sf_sqlite_cache'); - $pool = new PdoAdapter(DriverManager::getConnection(array('driver' => 'pdo_sqlite', 'path' => self::$dbFile))); + $pool = new PdoAdapter(DriverManager::getConnection(['driver' => 'pdo_sqlite', 'path' => self::$dbFile])); $pool->createTable(); } @@ -43,6 +43,6 @@ class PdoDbalAdapterTest extends AdapterTestCase public function createCachePool($defaultLifetime = 0) { - return new PdoAdapter(DriverManager::getConnection(array('driver' => 'pdo_sqlite', 'path' => self::$dbFile)), '', $defaultLifetime); + return new PdoAdapter(DriverManager::getConnection(['driver' => 'pdo_sqlite', 'path' => self::$dbFile]), '', $defaultLifetime); } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PhpArrayAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PhpArrayAdapterTest.php index 14b61263c..f88a71873 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PhpArrayAdapterTest.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PhpArrayAdapterTest.php @@ -20,7 +20,7 @@ use Symfony\Component\Cache\Adapter\PhpArrayAdapter; */ class PhpArrayAdapterTest extends AdapterTestCase { - protected $skippedTests = array( + protected $skippedTests = [ 'testBasicUsage' => 'PhpArrayAdapter is read-only.', 'testBasicUsageWithLongKey' => 'PhpArrayAdapter is read-only.', 'testClear' => 'PhpArrayAdapter is read-only.', @@ -51,17 +51,19 @@ class PhpArrayAdapterTest extends AdapterTestCase 'testDefaultLifeTime' => 'PhpArrayAdapter does not allow configuring a default lifetime.', 'testPrune' => 'PhpArrayAdapter just proxies', - ); + ]; protected static $file; - public static function setupBeforeClass() + public static function setUpBeforeClass() { self::$file = sys_get_temp_dir().'/symfony-cache/php-array-adapter-test.php'; } protected function tearDown() { + $this->createCachePool()->clear(); + if (file_exists(sys_get_temp_dir().'/symfony-cache')) { FilesystemAdapterTest::rmdir(sys_get_temp_dir().'/symfony-cache'); } @@ -74,22 +76,22 @@ class PhpArrayAdapterTest extends AdapterTestCase public function testStore() { - $arrayWithRefs = array(); + $arrayWithRefs = []; $arrayWithRefs[0] = 123; $arrayWithRefs[1] = &$arrayWithRefs[0]; - $object = (object) array( + $object = (object) [ 'foo' => 'bar', 'foo2' => 'bar2', - ); + ]; - $expected = array( + $expected = [ 'null' => null, 'serializedString' => serialize($object), 'arrayWithRefs' => $arrayWithRefs, 'object' => $object, - 'arrayWithObject' => array('bar' => $object), - ); + 'arrayWithObject' => ['bar' => $object], + ]; $adapter = $this->createCachePool(); $adapter->warmUp($expected); @@ -101,13 +103,13 @@ class PhpArrayAdapterTest extends AdapterTestCase public function testStoredFile() { - $expected = array( + $expected = [ 'integer' => 42, 'float' => 42.42, 'boolean' => true, - 'array_simple' => array('foo', 'bar'), - 'array_associative' => array('foo' => 'bar', 'foo2' => 'bar2'), - ); + 'array_simple' => ['foo', 'bar'], + 'array_associative' => ['foo' => 'bar', 'foo2' => 'bar2'], + ]; $adapter = $this->createCachePool(); $adapter->warmUp($expected); @@ -122,7 +124,7 @@ class PhpArrayAdapterWrapper extends PhpArrayAdapter { public function save(CacheItemInterface $item) { - call_user_func(\Closure::bind(function () use ($item) { + \call_user_func(\Closure::bind(function () use ($item) { $this->values[$item->getKey()] = $item->get(); $this->warmUp($this->values); $this->values = eval(substr(file_get_contents($this->file), 6)); diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PhpArrayAdapterWithFallbackTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PhpArrayAdapterWithFallbackTest.php index 1a23198c2..0bfd5c394 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PhpArrayAdapterWithFallbackTest.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PhpArrayAdapterWithFallbackTest.php @@ -19,24 +19,26 @@ use Symfony\Component\Cache\Adapter\PhpArrayAdapter; */ class PhpArrayAdapterWithFallbackTest extends AdapterTestCase { - protected $skippedTests = array( + protected $skippedTests = [ 'testGetItemInvalidKeys' => 'PhpArrayAdapter does not throw exceptions on invalid key.', 'testGetItemsInvalidKeys' => 'PhpArrayAdapter does not throw exceptions on invalid key.', 'testHasItemInvalidKeys' => 'PhpArrayAdapter does not throw exceptions on invalid key.', 'testDeleteItemInvalidKeys' => 'PhpArrayAdapter does not throw exceptions on invalid key.', 'testDeleteItemsInvalidKeys' => 'PhpArrayAdapter does not throw exceptions on invalid key.', 'testPrune' => 'PhpArrayAdapter just proxies', - ); + ]; protected static $file; - public static function setupBeforeClass() + public static function setUpBeforeClass() { self::$file = sys_get_temp_dir().'/symfony-cache/php-array-adapter-test.php'; } protected function tearDown() { + $this->createCachePool()->clear(); + if (file_exists(sys_get_temp_dir().'/symfony-cache')) { FilesystemAdapterTest::rmdir(sys_get_temp_dir().'/symfony-cache'); } diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PhpFilesAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PhpFilesAdapterTest.php index 8e93c937f..247160d53 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PhpFilesAdapterTest.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PhpFilesAdapterTest.php @@ -19,9 +19,9 @@ use Symfony\Component\Cache\Adapter\PhpFilesAdapter; */ class PhpFilesAdapterTest extends AdapterTestCase { - protected $skippedTests = array( + protected $skippedTests = [ 'testDefaultLifeTime' => 'PhpFilesAdapter does not allow configuring a default lifetime.', - ); + ]; public function createCachePool() { diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PredisAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PredisAdapterTest.php index c005d64ab..6aadbf266 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PredisAdapterTest.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PredisAdapterTest.php @@ -16,23 +16,23 @@ use Symfony\Component\Cache\Adapter\RedisAdapter; class PredisAdapterTest extends AbstractRedisAdapterTest { - public static function setupBeforeClass() + public static function setUpBeforeClass() { - parent::setupBeforeClass(); - self::$redis = new \Predis\Client(array('host' => getenv('REDIS_HOST'))); + parent::setUpBeforeClass(); + self::$redis = new \Predis\Client(['host' => getenv('REDIS_HOST')]); } public function testCreateConnection() { $redisHost = getenv('REDIS_HOST'); - $redis = RedisAdapter::createConnection('redis://'.$redisHost.'/1', array('class' => \Predis\Client::class, 'timeout' => 3)); + $redis = RedisAdapter::createConnection('redis://'.$redisHost.'/1', ['class' => \Predis\Client::class, 'timeout' => 3]); $this->assertInstanceOf(\Predis\Client::class, $redis); $connection = $redis->getConnection(); $this->assertInstanceOf(StreamConnection::class, $connection); - $params = array( + $params = [ 'scheme' => 'tcp', 'host' => $redisHost, 'path' => '', @@ -47,7 +47,7 @@ class PredisAdapterTest extends AbstractRedisAdapterTest 'lazy' => false, 'database' => '1', 'password' => null, - ); + ]; $this->assertSame($params, $connection->getParameters()->toArray()); } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PredisClusterAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PredisClusterAdapterTest.php index 38915397d..1afabaf1d 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PredisClusterAdapterTest.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PredisClusterAdapterTest.php @@ -13,10 +13,10 @@ namespace Symfony\Component\Cache\Tests\Adapter; class PredisClusterAdapterTest extends AbstractRedisAdapterTest { - public static function setupBeforeClass() + public static function setUpBeforeClass() { - parent::setupBeforeClass(); - self::$redis = new \Predis\Client(array(array('host' => getenv('REDIS_HOST')))); + parent::setUpBeforeClass(); + self::$redis = new \Predis\Client([['host' => getenv('REDIS_HOST')]]); } public static function tearDownAfterClass() diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PredisRedisClusterAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PredisRedisClusterAdapterTest.php new file mode 100644 index 000000000..5b09919e2 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PredisRedisClusterAdapterTest.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Tests\Adapter; + +class PredisRedisClusterAdapterTest extends AbstractRedisAdapterTest +{ + public static function setUpBeforeClass() + { + if (!$hosts = getenv('REDIS_CLUSTER_HOSTS')) { + self::markTestSkipped('REDIS_CLUSTER_HOSTS env var is not defined.'); + } + self::$redis = new \Predis\Client(explode(' ', $hosts), ['cluster' => 'redis']); + } + + public static function tearDownAfterClass() + { + self::$redis = null; + } +} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ProxyAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ProxyAdapterTest.php index ff4b9d34b..810cb31a2 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ProxyAdapterTest.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ProxyAdapterTest.php @@ -21,23 +21,21 @@ use Symfony\Component\Cache\CacheItem; */ class ProxyAdapterTest extends AdapterTestCase { - protected $skippedTests = array( + protected $skippedTests = [ 'testDeferredSaveWithoutCommit' => 'Assumes a shared cache which ArrayAdapter is not.', 'testSaveWithoutExpire' => 'Assumes a shared cache which ArrayAdapter is not.', 'testPrune' => 'ProxyAdapter just proxies', - ); + ]; public function createCachePool($defaultLifetime = 0) { return new ProxyAdapter(new ArrayAdapter(), '', $defaultLifetime); } - /** - * @expectedException \Exception - * @expectedExceptionMessage OK bar - */ public function testProxyfiedItem() { + $this->expectException('Exception'); + $this->expectExceptionMessage('OK bar'); $item = new CacheItem(); $pool = new ProxyAdapter(new TestingArrayAdapter($item)); diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/RedisAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/RedisAdapterTest.php index 28c310fb1..6ec6321a3 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/RedisAdapterTest.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/RedisAdapterTest.php @@ -17,10 +17,10 @@ use Symfony\Component\Cache\Traits\RedisProxy; class RedisAdapterTest extends AbstractRedisAdapterTest { - public static function setupBeforeClass() + public static function setUpBeforeClass() { - parent::setupBeforeClass(); - self::$redis = AbstractAdapter::createConnection('redis://'.getenv('REDIS_HOST'), array('lazy' => true)); + parent::setUpBeforeClass(); + self::$redis = AbstractAdapter::createConnection('redis://'.getenv('REDIS_HOST'), ['lazy' => true]); } public function createCachePool($defaultLifetime = 0) @@ -43,50 +43,50 @@ class RedisAdapterTest extends AbstractRedisAdapterTest $redis = RedisAdapter::createConnection('redis://'.$redisHost.'/2'); $this->assertSame(2, $redis->getDbNum()); - $redis = RedisAdapter::createConnection('redis://'.$redisHost, array('timeout' => 3)); + $redis = RedisAdapter::createConnection('redis://'.$redisHost, ['timeout' => 3]); $this->assertEquals(3, $redis->getTimeout()); $redis = RedisAdapter::createConnection('redis://'.$redisHost.'?timeout=4'); $this->assertEquals(4, $redis->getTimeout()); - $redis = RedisAdapter::createConnection('redis://'.$redisHost, array('read_timeout' => 5)); + $redis = RedisAdapter::createConnection('redis://'.$redisHost, ['read_timeout' => 5]); $this->assertEquals(5, $redis->getReadTimeout()); } /** * @dataProvider provideFailedCreateConnection - * @expectedException \Symfony\Component\Cache\Exception\InvalidArgumentException - * @expectedExceptionMessage Redis connection failed */ public function testFailedCreateConnection($dsn) { + $this->expectException('Symfony\Component\Cache\Exception\InvalidArgumentException'); + $this->expectExceptionMessage('Redis connection '); RedisAdapter::createConnection($dsn); } public function provideFailedCreateConnection() { - return array( - array('redis://localhost:1234'), - array('redis://foo@localhost'), - array('redis://localhost/123'), - ); + return [ + ['redis://localhost:1234'], + ['redis://foo@localhost'], + ['redis://localhost/123'], + ]; } /** * @dataProvider provideInvalidCreateConnection - * @expectedException \Symfony\Component\Cache\Exception\InvalidArgumentException - * @expectedExceptionMessage Invalid Redis DSN */ public function testInvalidCreateConnection($dsn) { + $this->expectException('Symfony\Component\Cache\Exception\InvalidArgumentException'); + $this->expectExceptionMessage('Invalid Redis DSN'); RedisAdapter::createConnection($dsn); } public function provideInvalidCreateConnection() { - return array( - array('foo://localhost'), - array('redis://'), - ); + return [ + ['foo://localhost'], + ['redis://'], + ]; } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/RedisArrayAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/RedisArrayAdapterTest.php index bef3eb887..bd9def326 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/RedisArrayAdapterTest.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/RedisArrayAdapterTest.php @@ -13,12 +13,12 @@ namespace Symfony\Component\Cache\Tests\Adapter; class RedisArrayAdapterTest extends AbstractRedisAdapterTest { - public static function setupBeforeClass() + public static function setUpBeforeClass() { parent::setupBeforeClass(); if (!class_exists('RedisArray')) { self::markTestSkipped('The RedisArray class is required.'); } - self::$redis = new \RedisArray(array(getenv('REDIS_HOST')), array('lazy_connect' => true)); + self::$redis = new \RedisArray([getenv('REDIS_HOST')], ['lazy_connect' => true]); } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/RedisClusterAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/RedisClusterAdapterTest.php new file mode 100644 index 000000000..9c339d2dd --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/RedisClusterAdapterTest.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Tests\Adapter; + +class RedisClusterAdapterTest extends AbstractRedisAdapterTest +{ + public static function setUpBeforeClass() + { + if (!class_exists('RedisCluster')) { + self::markTestSkipped('The RedisCluster class is required.'); + } + if (!$hosts = getenv('REDIS_CLUSTER_HOSTS')) { + self::markTestSkipped('REDIS_CLUSTER_HOSTS env var is not defined.'); + } + + self::$redis = new \RedisCluster(null, explode(' ', $hosts)); + } +} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/SimpleCacheAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/SimpleCacheAdapterTest.php index d5795d52e..d8470a2e7 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/SimpleCacheAdapterTest.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/SimpleCacheAdapterTest.php @@ -11,20 +11,31 @@ namespace Symfony\Component\Cache\Tests\Adapter; -use Symfony\Component\Cache\Simple\FilesystemCache; use Symfony\Component\Cache\Adapter\SimpleCacheAdapter; +use Symfony\Component\Cache\Simple\ArrayCache; +use Symfony\Component\Cache\Simple\FilesystemCache; /** * @group time-sensitive */ class SimpleCacheAdapterTest extends AdapterTestCase { - protected $skippedTests = array( + protected $skippedTests = [ 'testPrune' => 'SimpleCache just proxies', - ); + ]; public function createCachePool($defaultLifetime = 0) { return new SimpleCacheAdapter(new FilesystemCache(), '', $defaultLifetime); } + + public function testValidCacheKeyWithNamespace() + { + $cache = new SimpleCacheAdapter(new ArrayCache(), 'some_namespace', 0); + $item = $cache->getItem('my_key'); + $item->set('someValue'); + $cache->save($item); + + $this->assertTrue($cache->getItem('my_key')->isHit(), 'Stored item is successfully retrieved.'); + } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TagAwareAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TagAwareAdapterTest.php index 0e4e07a16..11907a031 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TagAwareAdapterTest.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TagAwareAdapterTest.php @@ -11,7 +11,10 @@ namespace Symfony\Component\Cache\Tests\Adapter; +use PHPUnit\Framework\MockObject\MockObject; +use Psr\Cache\CacheItemInterface; use Symfony\Component\Cache\Adapter\AdapterInterface; +use Symfony\Component\Cache\Adapter\ArrayAdapter; use Symfony\Component\Cache\Adapter\FilesystemAdapter; use Symfony\Component\Cache\Adapter\TagAwareAdapter; @@ -30,11 +33,9 @@ class TagAwareAdapterTest extends AdapterTestCase FilesystemAdapterTest::rmdir(sys_get_temp_dir().'/symfony-cache'); } - /** - * @expectedException \Psr\Cache\InvalidArgumentException - */ public function testInvalidTag() { + $this->expectException('Psr\Cache\InvalidArgumentException'); $pool = $this->createCachePool(); $item = $pool->getItem('foo'); $item->tag(':'); @@ -56,7 +57,7 @@ class TagAwareAdapterTest extends AdapterTestCase $pool->save($i3->tag('foo')->tag('baz')); $pool->save($foo); - $pool->invalidateTags(array('bar')); + $pool->invalidateTags(['bar']); $this->assertFalse($pool->getItem('i0')->isHit()); $this->assertTrue($pool->getItem('i1')->isHit()); @@ -64,11 +65,33 @@ class TagAwareAdapterTest extends AdapterTestCase $this->assertTrue($pool->getItem('i3')->isHit()); $this->assertTrue($pool->getItem('foo')->isHit()); - $pool->invalidateTags(array('foo')); + $pool->invalidateTags(['foo']); $this->assertFalse($pool->getItem('i1')->isHit()); $this->assertFalse($pool->getItem('i3')->isHit()); $this->assertTrue($pool->getItem('foo')->isHit()); + + $anotherPoolInstance = $this->createCachePool(); + + $this->assertFalse($anotherPoolInstance->getItem('i1')->isHit()); + $this->assertFalse($anotherPoolInstance->getItem('i3')->isHit()); + $this->assertTrue($anotherPoolInstance->getItem('foo')->isHit()); + } + + public function testInvalidateCommits() + { + $pool1 = $this->createCachePool(); + + $foo = $pool1->getItem('foo'); + $foo->tag('tag'); + + $pool1->saveDeferred($foo->set('foo')); + $pool1->invalidateTags(['tag']); + + $pool2 = $this->createCachePool(); + $foo = $pool2->getItem('foo'); + + $this->assertTrue($foo->isHit()); } public function testTagsAreCleanedOnSave() @@ -81,7 +104,7 @@ class TagAwareAdapterTest extends AdapterTestCase $i = $pool->getItem('k'); $pool->save($i->tag('bar')); - $pool->invalidateTags(array('foo')); + $pool->invalidateTags(['foo']); $this->assertTrue($pool->getItem('k')->isHit()); } @@ -94,7 +117,7 @@ class TagAwareAdapterTest extends AdapterTestCase $pool->deleteItem('k'); $pool->save($pool->getItem('k')); - $pool->invalidateTags(array('foo')); + $pool->invalidateTags(['foo']); $this->assertTrue($pool->getItem('k')->isHit()); } @@ -104,11 +127,11 @@ class TagAwareAdapterTest extends AdapterTestCase $pool = $this->createCachePool(10); $item = $pool->getItem('foo'); - $item->tag(array('baz')); + $item->tag(['baz']); $item->expiresAfter(100); $pool->save($item); - $pool->invalidateTags(array('baz')); + $pool->invalidateTags(['baz']); $this->assertFalse($pool->getItem('foo')->isHit()); sleep(20); @@ -124,7 +147,7 @@ class TagAwareAdapterTest extends AdapterTestCase $pool->save($i->tag('foo')); $i = $pool->getItem('k'); - $this->assertSame(array('foo' => 'foo'), $i->getPreviousTags()); + $this->assertSame(['foo' => 'foo'], $i->getPreviousTags()); } public function testPrune() @@ -139,8 +162,138 @@ class TagAwareAdapterTest extends AdapterTestCase $this->assertFalse($cache->prune()); } + public function testKnownTagVersionsTtl() + { + $itemsPool = new FilesystemAdapter('', 10); + $tagsPool = $this + ->getMockBuilder(AdapterInterface::class) + ->getMock(); + + $pool = new TagAwareAdapter($itemsPool, $tagsPool, 10); + + $item = $pool->getItem('foo'); + $item->tag(['baz']); + $item->expiresAfter(100); + + $tag = $this->getMockBuilder(CacheItemInterface::class)->getMock(); + $tag->expects(self::exactly(2))->method('get')->willReturn(10); + + $tagsPool->expects(self::exactly(2))->method('getItems')->willReturn([ + 'baz'.TagAwareAdapter::TAGS_PREFIX => $tag, + ]); + + $pool->save($item); + $this->assertTrue($pool->getItem('foo')->isHit()); + $this->assertTrue($pool->getItem('foo')->isHit()); + + sleep(20); + + $this->assertTrue($pool->getItem('foo')->isHit()); + + sleep(5); + + $this->assertTrue($pool->getItem('foo')->isHit()); + } + + public function testTagEntryIsCreatedForItemWithoutTags() + { + $pool = $this->createCachePool(); + + $itemKey = 'foo'; + $item = $pool->getItem($itemKey); + $pool->save($item); + + $adapter = new FilesystemAdapter(); + $this->assertTrue($adapter->hasItem(TagAwareAdapter::TAGS_PREFIX.$itemKey)); + } + + public function testHasItemReturnsFalseWhenPoolDoesNotHaveItemTags() + { + $pool = $this->createCachePool(); + + $itemKey = 'foo'; + $item = $pool->getItem($itemKey); + $pool->save($item); + + $anotherPool = $this->createCachePool(); + + $adapter = new FilesystemAdapter(); + $adapter->deleteItem(TagAwareAdapter::TAGS_PREFIX.$itemKey); //simulate item losing tags pair + + $this->assertFalse($anotherPool->hasItem($itemKey)); + } + + public function testGetItemReturnsCacheMissWhenPoolDoesNotHaveItemTags() + { + $pool = $this->createCachePool(); + + $itemKey = 'foo'; + $item = $pool->getItem($itemKey); + $pool->save($item); + + $anotherPool = $this->createCachePool(); + + $adapter = new FilesystemAdapter(); + $adapter->deleteItem(TagAwareAdapter::TAGS_PREFIX.$itemKey); //simulate item losing tags pair + + $item = $anotherPool->getItem($itemKey); + $this->assertFalse($item->isHit()); + } + + public function testHasItemReturnsFalseWhenPoolDoesNotHaveItemAndOnlyHasTags() + { + $pool = $this->createCachePool(); + + $itemKey = 'foo'; + $item = $pool->getItem($itemKey); + $pool->save($item); + + $anotherPool = $this->createCachePool(); + + $adapter = new FilesystemAdapter(); + $adapter->deleteItem($itemKey); //simulate losing item but keeping tags + + $this->assertFalse($anotherPool->hasItem($itemKey)); + } + + public function testInvalidateTagsWithArrayAdapter() + { + $adapter = new TagAwareAdapter(new ArrayAdapter()); + + $item = $adapter->getItem('foo'); + + $this->assertFalse($item->isHit()); + + $item->tag('bar'); + $item->expiresAfter(100); + $adapter->save($item); + + $this->assertTrue($adapter->getItem('foo')->isHit()); + + $adapter->invalidateTags(['bar']); + + $this->assertFalse($adapter->getItem('foo')->isHit()); + } + + public function testGetItemReturnsCacheMissWhenPoolDoesNotHaveItemAndOnlyHasTags() + { + $pool = $this->createCachePool(); + + $itemKey = 'foo'; + $item = $pool->getItem($itemKey); + $pool->save($item); + + $anotherPool = $this->createCachePool(); + + $adapter = new FilesystemAdapter(); + $adapter->deleteItem($itemKey); //simulate losing item but keeping tags + + $item = $anotherPool->getItem($itemKey); + $this->assertFalse($item->isHit()); + } + /** - * @return \PHPUnit_Framework_MockObject_MockObject|PruneableCacheInterface + * @return MockObject|PruneableCacheInterface */ private function getPruneableMock() { @@ -151,13 +304,13 @@ class TagAwareAdapterTest extends AdapterTestCase $pruneable ->expects($this->atLeastOnce()) ->method('prune') - ->will($this->returnValue(true)); + ->willReturn(true); return $pruneable; } /** - * @return \PHPUnit_Framework_MockObject_MockObject|PruneableCacheInterface + * @return MockObject|PruneableCacheInterface */ private function getFailingPruneableMock() { @@ -168,13 +321,13 @@ class TagAwareAdapterTest extends AdapterTestCase $pruneable ->expects($this->atLeastOnce()) ->method('prune') - ->will($this->returnValue(false)); + ->willReturn(false); return $pruneable; } /** - * @return \PHPUnit_Framework_MockObject_MockObject|AdapterInterface + * @return MockObject|AdapterInterface */ private function getNonPruneableMock() { diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TagAwareAndProxyAdapterIntegrationTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TagAwareAndProxyAdapterIntegrationTest.php new file mode 100644 index 000000000..b11c1f287 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TagAwareAndProxyAdapterIntegrationTest.php @@ -0,0 +1,38 @@ +getItem('foo'); + $item->tag(['tag1', 'tag2']); + $item->set('bar'); + $cache->save($item); + + $this->assertSame('bar', $cache->getItem('foo')->get()); + } + + public function dataProvider() + { + return [ + [new ArrayAdapter()], + // also testing with a non-AdapterInterface implementation + // because the ProxyAdapter behaves slightly different for those + [new ExternalAdapter()], + ]; + } +} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TraceableAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TraceableAdapterTest.php index 3755e88db..35eba7d77 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TraceableAdapterTest.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TraceableAdapterTest.php @@ -19,9 +19,9 @@ use Symfony\Component\Cache\Adapter\TraceableAdapter; */ class TraceableAdapterTest extends AdapterTestCase { - protected $skippedTests = array( + protected $skippedTests = [ 'testPrune' => 'TraceableAdapter just proxies', - ); + ]; public function createCachePool($defaultLifetime = 0) { @@ -37,7 +37,7 @@ class TraceableAdapterTest extends AdapterTestCase $call = $calls[0]; $this->assertSame('getItem', $call->name); - $this->assertSame(array('k' => false), $call->result); + $this->assertSame(['k' => false], $call->result); $this->assertSame(0, $call->hits); $this->assertSame(1, $call->misses); $this->assertNotEmpty($call->start); @@ -61,7 +61,7 @@ class TraceableAdapterTest extends AdapterTestCase public function testGetItemsMissTrace() { $pool = $this->createCachePool(); - $arg = array('k0', 'k1'); + $arg = ['k0', 'k1']; $items = $pool->getItems($arg); foreach ($items as $item) { } @@ -70,7 +70,7 @@ class TraceableAdapterTest extends AdapterTestCase $call = $calls[0]; $this->assertSame('getItems', $call->name); - $this->assertSame(array('k0' => false, 'k1' => false), $call->result); + $this->assertSame(['k0' => false, 'k1' => false], $call->result); $this->assertSame(2, $call->misses); $this->assertNotEmpty($call->start); $this->assertNotEmpty($call->end); @@ -85,7 +85,7 @@ class TraceableAdapterTest extends AdapterTestCase $call = $calls[0]; $this->assertSame('hasItem', $call->name); - $this->assertSame(array('k' => false), $call->result); + $this->assertSame(['k' => false], $call->result); $this->assertNotEmpty($call->start); $this->assertNotEmpty($call->end); } @@ -101,7 +101,7 @@ class TraceableAdapterTest extends AdapterTestCase $call = $calls[2]; $this->assertSame('hasItem', $call->name); - $this->assertSame(array('k' => true), $call->result); + $this->assertSame(['k' => true], $call->result); $this->assertNotEmpty($call->start); $this->assertNotEmpty($call->end); } @@ -115,7 +115,7 @@ class TraceableAdapterTest extends AdapterTestCase $call = $calls[0]; $this->assertSame('deleteItem', $call->name); - $this->assertSame(array('k' => true), $call->result); + $this->assertSame(['k' => true], $call->result); $this->assertSame(0, $call->hits); $this->assertSame(0, $call->misses); $this->assertNotEmpty($call->start); @@ -125,14 +125,14 @@ class TraceableAdapterTest extends AdapterTestCase public function testDeleteItemsTrace() { $pool = $this->createCachePool(); - $arg = array('k0', 'k1'); + $arg = ['k0', 'k1']; $pool->deleteItems($arg); $calls = $pool->getCalls(); $this->assertCount(1, $calls); $call = $calls[0]; $this->assertSame('deleteItems', $call->name); - $this->assertSame(array('keys' => $arg, 'result' => true), $call->result); + $this->assertSame(['keys' => $arg, 'result' => true], $call->result); $this->assertSame(0, $call->hits); $this->assertSame(0, $call->misses); $this->assertNotEmpty($call->start); @@ -149,7 +149,7 @@ class TraceableAdapterTest extends AdapterTestCase $call = $calls[1]; $this->assertSame('save', $call->name); - $this->assertSame(array('k' => true), $call->result); + $this->assertSame(['k' => true], $call->result); $this->assertSame(0, $call->hits); $this->assertSame(0, $call->misses); $this->assertNotEmpty($call->start); @@ -166,7 +166,7 @@ class TraceableAdapterTest extends AdapterTestCase $call = $calls[1]; $this->assertSame('saveDeferred', $call->name); - $this->assertSame(array('k' => true), $call->result); + $this->assertSame(['k' => true], $call->result); $this->assertSame(0, $call->hits); $this->assertSame(0, $call->misses); $this->assertNotEmpty($call->start); diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TraceableTagAwareAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TraceableTagAwareAdapterTest.php index 9b50bfabe..5cd4185cb 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TraceableTagAwareAdapterTest.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TraceableTagAwareAdapterTest.php @@ -23,7 +23,7 @@ class TraceableTagAwareAdapterTest extends TraceableAdapterTest public function testInvalidateTags() { $pool = new TraceableTagAwareAdapter(new TagAwareAdapter(new FilesystemAdapter())); - $pool->invalidateTags(array('foo')); + $pool->invalidateTags(['foo']); $calls = $pool->getCalls(); $this->assertCount(1, $calls); diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/CacheItemTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/CacheItemTest.php index daca925fd..28c681d15 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/CacheItemTest.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/CacheItemTest.php @@ -23,33 +23,33 @@ class CacheItemTest extends TestCase /** * @dataProvider provideInvalidKey - * @expectedException \Symfony\Component\Cache\Exception\InvalidArgumentException - * @expectedExceptionMessage Cache key */ public function testInvalidKey($key) { + $this->expectException('Symfony\Component\Cache\Exception\InvalidArgumentException'); + $this->expectExceptionMessage('Cache key'); CacheItem::validateKey($key); } public function provideInvalidKey() { - return array( - array(''), - array('{'), - array('}'), - array('('), - array(')'), - array('/'), - array('\\'), - array('@'), - array(':'), - array(true), - array(null), - array(1), - array(1.1), - array(array(array())), - array(new \Exception('foo')), - ); + return [ + [''], + ['{'], + ['}'], + ['('], + [')'], + ['/'], + ['\\'], + ['@'], + [':'], + [true], + [null], + [1], + [1.1], + [[[]]], + [new \Exception('foo')], + ]; } public function testTag() @@ -57,20 +57,20 @@ class CacheItemTest extends TestCase $item = new CacheItem(); $this->assertSame($item, $item->tag('foo')); - $this->assertSame($item, $item->tag(array('bar', 'baz'))); + $this->assertSame($item, $item->tag(['bar', 'baz'])); - call_user_func(\Closure::bind(function () use ($item) { - $this->assertSame(array('foo' => 'foo', 'bar' => 'bar', 'baz' => 'baz'), $item->tags); + \call_user_func(\Closure::bind(function () use ($item) { + $this->assertSame(['foo' => 'foo', 'bar' => 'bar', 'baz' => 'baz'], $item->tags); }, $this, CacheItem::class)); } /** * @dataProvider provideInvalidKey - * @expectedException \Symfony\Component\Cache\Exception\InvalidArgumentException - * @expectedExceptionMessage Cache tag */ public function testInvalidTag($tag) { + $this->expectException('Symfony\Component\Cache\Exception\InvalidArgumentException'); + $this->expectExceptionMessage('Cache tag'); $item = new CacheItem(); $item->tag($tag); } diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Fixtures/ArrayCache.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Fixtures/ArrayCache.php index 1a6157e82..13b4f3306 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Fixtures/ArrayCache.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Fixtures/ArrayCache.php @@ -6,7 +6,7 @@ use Doctrine\Common\Cache\CacheProvider; class ArrayCache extends CacheProvider { - private $data = array(); + private $data = []; protected function doFetch($id) { @@ -21,12 +21,12 @@ class ArrayCache extends CacheProvider $expiry = $this->data[$id][1]; - return !$expiry || time() <= $expiry || !$this->doDelete($id); + return !$expiry || time() < $expiry || !$this->doDelete($id); } protected function doSave($id, $data, $lifeTime = 0) { - $this->data[$id] = array($data, $lifeTime ? time() + $lifeTime : false); + $this->data[$id] = [$data, $lifeTime ? time() + $lifeTime : false]; return true; } @@ -40,7 +40,7 @@ class ArrayCache extends CacheProvider protected function doFlush() { - $this->data = array(); + $this->data = []; return true; } diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Fixtures/ExternalAdapter.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Fixtures/ExternalAdapter.php index 493906ea0..be1f99012 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Fixtures/ExternalAdapter.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Fixtures/ExternalAdapter.php @@ -24,9 +24,9 @@ class ExternalAdapter implements CacheItemPoolInterface { private $cache; - public function __construct() + public function __construct($defaultLifetime = 0) { - $this->cache = new ArrayAdapter(); + $this->cache = new ArrayAdapter($defaultLifetime); } public function getItem($key) @@ -34,7 +34,7 @@ class ExternalAdapter implements CacheItemPoolInterface return $this->cache->getItem($key); } - public function getItems(array $keys = array()) + public function getItems(array $keys = []) { return $this->cache->getItems($keys); } diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/AbstractRedisCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/AbstractRedisCacheTest.php index f70f49d5d..7a6cabe8c 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/AbstractRedisCacheTest.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/AbstractRedisCacheTest.php @@ -15,11 +15,11 @@ use Symfony\Component\Cache\Simple\RedisCache; abstract class AbstractRedisCacheTest extends CacheTestCase { - protected $skippedTests = array( + protected $skippedTests = [ 'testSetTtl' => 'Testing expiration slows down the test suite', 'testSetMultipleTtl' => 'Testing expiration slows down the test suite', 'testDefaultLifeTime' => 'Testing expiration slows down the test suite', - ); + ]; protected static $redis; @@ -28,14 +28,15 @@ abstract class AbstractRedisCacheTest extends CacheTestCase return new RedisCache(self::$redis, str_replace('\\', '.', __CLASS__), $defaultLifetime); } - public static function setupBeforeClass() + public static function setUpBeforeClass() { - if (!extension_loaded('redis')) { + if (!\extension_loaded('redis')) { self::markTestSkipped('Extension redis required.'); } - if (!@((new \Redis())->connect(getenv('REDIS_HOST')))) { - $e = error_get_last(); - self::markTestSkipped($e['message']); + try { + (new \Redis())->connect(getenv('REDIS_HOST')); + } catch (\Exception $e) { + self::markTestSkipped($e->getMessage()); } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/ApcuCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/ApcuCacheTest.php index 297a41756..fad0c0432 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/ApcuCacheTest.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/ApcuCacheTest.php @@ -15,18 +15,18 @@ use Symfony\Component\Cache\Simple\ApcuCache; class ApcuCacheTest extends CacheTestCase { - protected $skippedTests = array( + protected $skippedTests = [ 'testSetTtl' => 'Testing expiration slows down the test suite', 'testSetMultipleTtl' => 'Testing expiration slows down the test suite', 'testDefaultLifeTime' => 'Testing expiration slows down the test suite', - ); + ]; public function createSimpleCache($defaultLifetime = 0) { - if (!function_exists('apcu_fetch') || !ini_get('apc.enabled') || ('cli' === PHP_SAPI && !ini_get('apc.enable_cli'))) { + if (!\function_exists('apcu_fetch') || !filter_var(ini_get('apc.enabled'), \FILTER_VALIDATE_BOOLEAN) || ('cli' === \PHP_SAPI && !filter_var(ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOLEAN))) { $this->markTestSkipped('APCu extension is required.'); } - if ('\\' === DIRECTORY_SEPARATOR) { + if ('\\' === \DIRECTORY_SEPARATOR) { $this->markTestSkipped('Fails transiently on Windows.'); } diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/CacheTestCase.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/CacheTestCase.php index 48b972824..ff9944a34 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/CacheTestCase.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/CacheTestCase.php @@ -21,18 +21,18 @@ abstract class CacheTestCase extends SimpleCacheTest { parent::setUp(); - if (!array_key_exists('testPrune', $this->skippedTests) && !$this->createSimpleCache() instanceof PruneableInterface) { + if (!\array_key_exists('testPrune', $this->skippedTests) && !$this->createSimpleCache() instanceof PruneableInterface) { $this->skippedTests['testPrune'] = 'Not a pruneable cache pool.'; } } public static function validKeys() { - if (defined('HHVM_VERSION')) { + if (\defined('HHVM_VERSION')) { return parent::validKeys(); } - return array_merge(parent::validKeys(), array(array("a\0b"))); + return array_merge(parent::validKeys(), [["a\0b"]]); } public function testDefaultLifeTime() @@ -42,6 +42,7 @@ abstract class CacheTestCase extends SimpleCacheTest } $cache = $this->createSimpleCache(2); + $cache->clear(); $cache->set('key.dlt', 'value'); sleep(1); @@ -50,6 +51,8 @@ abstract class CacheTestCase extends SimpleCacheTest sleep(2); $this->assertNull($cache->get('key.dlt')); + + $cache->clear(); } public function testNotUnserializable() @@ -59,16 +62,19 @@ abstract class CacheTestCase extends SimpleCacheTest } $cache = $this->createSimpleCache(); + $cache->clear(); $cache->set('foo', new NotUnserializable()); $this->assertNull($cache->get('foo')); - $cache->setMultiple(array('foo' => new NotUnserializable())); + $cache->setMultiple(['foo' => new NotUnserializable()]); - foreach ($cache->getMultiple(array('foo')) as $value) { + foreach ($cache->getMultiple(['foo']) as $value) { } $this->assertNull($value); + + $cache->clear(); } public function testPrune() @@ -83,6 +89,7 @@ abstract class CacheTestCase extends SimpleCacheTest /** @var PruneableInterface|CacheInterface $cache */ $cache = $this->createSimpleCache(); + $cache->clear(); $cache->set('foo', 'foo-val', new \DateInterval('PT05S')); $cache->set('bar', 'bar-val', new \DateInterval('PT10S')); @@ -124,6 +131,8 @@ abstract class CacheTestCase extends SimpleCacheTest $cache->prune(); $this->assertFalse($this->isPruned($cache, 'foo')); $this->assertTrue($this->isPruned($cache, 'qux')); + + $cache->clear(); } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/ChainCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/ChainCacheTest.php index ab28e3bce..f216bc1f3 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/ChainCacheTest.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/ChainCacheTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Cache\Tests\Simple; +use PHPUnit\Framework\MockObject\MockObject; use Psr\SimpleCache\CacheInterface; use Symfony\Component\Cache\PruneableInterface; use Symfony\Component\Cache\Simple\ArrayCache; @@ -24,25 +25,21 @@ class ChainCacheTest extends CacheTestCase { public function createSimpleCache($defaultLifetime = 0) { - return new ChainCache(array(new ArrayCache($defaultLifetime), new FilesystemCache('', $defaultLifetime)), $defaultLifetime); + return new ChainCache([new ArrayCache($defaultLifetime), new FilesystemCache('', $defaultLifetime)], $defaultLifetime); } - /** - * @expectedException \Symfony\Component\Cache\Exception\InvalidArgumentException - * @expectedExceptionMessage At least one cache must be specified. - */ public function testEmptyCachesException() { - new ChainCache(array()); + $this->expectException('Symfony\Component\Cache\Exception\InvalidArgumentException'); + $this->expectExceptionMessage('At least one cache must be specified.'); + new ChainCache([]); } - /** - * @expectedException \Symfony\Component\Cache\Exception\InvalidArgumentException - * @expectedExceptionMessage The class "stdClass" does not implement - */ public function testInvalidCacheException() { - new ChainCache(array(new \stdClass())); + $this->expectException('Symfony\Component\Cache\Exception\InvalidArgumentException'); + $this->expectExceptionMessage('The class "stdClass" does not implement'); + new ChainCache([new \stdClass()]); } public function testPrune() @@ -51,23 +48,23 @@ class ChainCacheTest extends CacheTestCase $this->markTestSkipped($this->skippedTests[__FUNCTION__]); } - $cache = new ChainCache(array( + $cache = new ChainCache([ $this->getPruneableMock(), $this->getNonPruneableMock(), $this->getPruneableMock(), - )); + ]); $this->assertTrue($cache->prune()); - $cache = new ChainCache(array( + $cache = new ChainCache([ $this->getPruneableMock(), $this->getFailingPruneableMock(), $this->getPruneableMock(), - )); + ]); $this->assertFalse($cache->prune()); } /** - * @return \PHPUnit_Framework_MockObject_MockObject|PruneableCacheInterface + * @return MockObject|PruneableCacheInterface */ private function getPruneableMock() { @@ -78,13 +75,13 @@ class ChainCacheTest extends CacheTestCase $pruneable ->expects($this->atLeastOnce()) ->method('prune') - ->will($this->returnValue(true)); + ->willReturn(true); return $pruneable; } /** - * @return \PHPUnit_Framework_MockObject_MockObject|PruneableCacheInterface + * @return MockObject|PruneableCacheInterface */ private function getFailingPruneableMock() { @@ -95,13 +92,13 @@ class ChainCacheTest extends CacheTestCase $pruneable ->expects($this->atLeastOnce()) ->method('prune') - ->will($this->returnValue(false)); + ->willReturn(false); return $pruneable; } /** - * @return \PHPUnit_Framework_MockObject_MockObject|CacheInterface + * @return MockObject|CacheInterface */ private function getNonPruneableMock() { diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/DoctrineCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/DoctrineCacheTest.php index 127c96858..af4331d69 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/DoctrineCacheTest.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/DoctrineCacheTest.php @@ -19,10 +19,10 @@ use Symfony\Component\Cache\Tests\Fixtures\ArrayCache; */ class DoctrineCacheTest extends CacheTestCase { - protected $skippedTests = array( + protected $skippedTests = [ 'testObjectDoesNotChangeInCache' => 'ArrayCache does not use serialize/unserialize', 'testNotUnserializable' => 'ArrayCache does not use serialize/unserialize', - ); + ]; public function createSimpleCache($defaultLifetime = 0) { diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/MemcachedCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/MemcachedCacheTest.php index c4af891af..6df682e9f 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/MemcachedCacheTest.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/MemcachedCacheTest.php @@ -16,15 +16,15 @@ use Symfony\Component\Cache\Simple\MemcachedCache; class MemcachedCacheTest extends CacheTestCase { - protected $skippedTests = array( + protected $skippedTests = [ 'testSetTtl' => 'Testing expiration slows down the test suite', 'testSetMultipleTtl' => 'Testing expiration slows down the test suite', 'testDefaultLifeTime' => 'Testing expiration slows down the test suite', - ); + ]; protected static $client; - public static function setupBeforeClass() + public static function setUpBeforeClass() { if (!MemcachedCache::isSupported()) { self::markTestSkipped('Extension memcached >=2.2.0 required.'); @@ -40,20 +40,29 @@ class MemcachedCacheTest extends CacheTestCase public function createSimpleCache($defaultLifetime = 0) { - $client = $defaultLifetime ? AbstractAdapter::createConnection('memcached://'.getenv('MEMCACHED_HOST'), array('binary_protocol' => false)) : self::$client; + $client = $defaultLifetime ? AbstractAdapter::createConnection('memcached://'.getenv('MEMCACHED_HOST'), ['binary_protocol' => false]) : self::$client; return new MemcachedCache($client, str_replace('\\', '.', __CLASS__), $defaultLifetime); } + public function testCreatePersistentConnectionShouldNotDupServerList() + { + $instance = MemcachedCache::createConnection('memcached://'.getenv('MEMCACHED_HOST'), ['persistent_id' => 'persistent']); + $this->assertCount(1, $instance->getServerList()); + + $instance = MemcachedCache::createConnection('memcached://'.getenv('MEMCACHED_HOST'), ['persistent_id' => 'persistent']); + $this->assertCount(1, $instance->getServerList()); + } + public function testOptions() { - $client = MemcachedCache::createConnection(array(), array( + $client = MemcachedCache::createConnection([], [ 'libketama_compatible' => false, 'distribution' => 'modula', 'compression' => true, 'serializer' => 'php', 'hash' => 'md5', - )); + ]); $this->assertSame(\Memcached::SERIALIZER_PHP, $client->getOption(\Memcached::OPT_SERIALIZER)); $this->assertSame(\Memcached::HASH_MD5, $client->getOption(\Memcached::OPT_HASH)); @@ -64,46 +73,50 @@ class MemcachedCacheTest extends CacheTestCase /** * @dataProvider provideBadOptions - * @expectedException \ErrorException - * @expectedExceptionMessage constant(): Couldn't find constant Memcached:: */ public function testBadOptions($name, $value) { - MemcachedCache::createConnection(array(), array($name => $value)); + if (\PHP_VERSION_ID < 80000) { + $this->expectException('ErrorException'); + $this->expectExceptionMessage('constant(): Couldn\'t find constant Memcached::'); + } else { + $this->expectException('Error'); + $this->expectExceptionMessage('Undefined constant Memcached::'); + } + + MemcachedCache::createConnection([], [$name => $value]); } public function provideBadOptions() { - return array( - array('foo', 'bar'), - array('hash', 'zyx'), - array('serializer', 'zyx'), - array('distribution', 'zyx'), - ); + return [ + ['foo', 'bar'], + ['hash', 'zyx'], + ['serializer', 'zyx'], + ['distribution', 'zyx'], + ]; } public function testDefaultOptions() { $this->assertTrue(MemcachedCache::isSupported()); - $client = MemcachedCache::createConnection(array()); + $client = MemcachedCache::createConnection([]); $this->assertTrue($client->getOption(\Memcached::OPT_COMPRESSION)); $this->assertSame(1, $client->getOption(\Memcached::OPT_BINARY_PROTOCOL)); $this->assertSame(1, $client->getOption(\Memcached::OPT_LIBKETAMA_COMPATIBLE)); } - /** - * @expectedException \Symfony\Component\Cache\Exception\CacheException - * @expectedExceptionMessage MemcachedAdapter: "serializer" option must be "php" or "igbinary". - */ public function testOptionSerializer() { + $this->expectException('Symfony\Component\Cache\Exception\CacheException'); + $this->expectExceptionMessage('MemcachedAdapter: "serializer" option must be "php" or "igbinary".'); if (!\Memcached::HAVE_JSON) { $this->markTestSkipped('Memcached::HAVE_JSON required'); } - new MemcachedCache(MemcachedCache::createConnection(array(), array('serializer' => 'json'))); + new MemcachedCache(MemcachedCache::createConnection([], ['serializer' => 'json'])); } /** @@ -112,54 +125,54 @@ class MemcachedCacheTest extends CacheTestCase public function testServersSetting($dsn, $host, $port) { $client1 = MemcachedCache::createConnection($dsn); - $client2 = MemcachedCache::createConnection(array($dsn)); - $client3 = MemcachedCache::createConnection(array(array($host, $port))); - $expect = array( + $client2 = MemcachedCache::createConnection([$dsn]); + $client3 = MemcachedCache::createConnection([[$host, $port]]); + $expect = [ 'host' => $host, 'port' => $port, - ); + ]; - $f = function ($s) { return array('host' => $s['host'], 'port' => $s['port']); }; - $this->assertSame(array($expect), array_map($f, $client1->getServerList())); - $this->assertSame(array($expect), array_map($f, $client2->getServerList())); - $this->assertSame(array($expect), array_map($f, $client3->getServerList())); + $f = function ($s) { return ['host' => $s['host'], 'port' => $s['port']]; }; + $this->assertSame([$expect], array_map($f, $client1->getServerList())); + $this->assertSame([$expect], array_map($f, $client2->getServerList())); + $this->assertSame([$expect], array_map($f, $client3->getServerList())); } public function provideServersSetting() { - yield array( + yield [ 'memcached://127.0.0.1/50', '127.0.0.1', 11211, - ); - yield array( + ]; + yield [ 'memcached://localhost:11222?weight=25', 'localhost', 11222, - ); - if (ini_get('memcached.use_sasl')) { - yield array( + ]; + if (filter_var(ini_get('memcached.use_sasl'), \FILTER_VALIDATE_BOOLEAN)) { + yield [ 'memcached://user:password@127.0.0.1?weight=50', '127.0.0.1', 11211, - ); + ]; } - yield array( + yield [ 'memcached:///var/run/memcached.sock?weight=25', '/var/run/memcached.sock', 0, - ); - yield array( + ]; + yield [ 'memcached:///var/local/run/memcached.socket?weight=25', '/var/local/run/memcached.socket', 0, - ); - if (ini_get('memcached.use_sasl')) { - yield array( + ]; + if (filter_var(ini_get('memcached.use_sasl'), \FILTER_VALIDATE_BOOLEAN)) { + yield [ 'memcached://user:password@/var/local/run/memcached.socket?weight=25', '/var/local/run/memcached.socket', 0, - ); + ]; } } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/MemcachedCacheTextModeTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/MemcachedCacheTextModeTest.php new file mode 100644 index 000000000..13865a609 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/MemcachedCacheTextModeTest.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Tests\Simple; + +use Symfony\Component\Cache\Adapter\AbstractAdapter; +use Symfony\Component\Cache\Simple\MemcachedCache; + +class MemcachedCacheTextModeTest extends MemcachedCacheTest +{ + public function createSimpleCache($defaultLifetime = 0) + { + $client = AbstractAdapter::createConnection('memcached://'.getenv('MEMCACHED_HOST'), ['binary_protocol' => false]); + + return new MemcachedCache($client, str_replace('\\', '.', __CLASS__), $defaultLifetime); + } +} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/NullCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/NullCacheTest.php index 7b760fd3b..31f42c32b 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/NullCacheTest.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/NullCacheTest.php @@ -40,7 +40,7 @@ class NullCacheTest extends TestCase { $cache = $this->createCachePool(); - $keys = array('foo', 'bar', 'baz', 'biz'); + $keys = ['foo', 'bar', 'baz', 'biz']; $default = new \stdClass(); $items = $cache->getMultiple($keys, $default); @@ -75,7 +75,7 @@ class NullCacheTest extends TestCase public function testDeleteMultiple() { - $this->assertTrue($this->createCachePool()->deleteMultiple(array('key', 'foo', 'bar'))); + $this->assertTrue($this->createCachePool()->deleteMultiple(['key', 'foo', 'bar'])); } public function testSet() @@ -90,7 +90,7 @@ class NullCacheTest extends TestCase { $cache = $this->createCachePool(); - $this->assertFalse($cache->setMultiple(array('key' => 'val'))); + $this->assertFalse($cache->setMultiple(['key' => 'val'])); $this->assertNull($cache->get('key')); } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PdoCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PdoCacheTest.php index cf5730952..f5a26341f 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PdoCacheTest.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PdoCacheTest.php @@ -23,9 +23,9 @@ class PdoCacheTest extends CacheTestCase protected static $dbFile; - public static function setupBeforeClass() + public static function setUpBeforeClass() { - if (!extension_loaded('pdo_sqlite')) { + if (!\extension_loaded('pdo_sqlite')) { self::markTestSkipped('Extension pdo_sqlite required.'); } diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PdoDbalCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PdoDbalCacheTest.php index 0c40c04a2..4da2b603c 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PdoDbalCacheTest.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PdoDbalCacheTest.php @@ -24,15 +24,15 @@ class PdoDbalCacheTest extends CacheTestCase protected static $dbFile; - public static function setupBeforeClass() + public static function setUpBeforeClass() { - if (!extension_loaded('pdo_sqlite')) { + if (!\extension_loaded('pdo_sqlite')) { self::markTestSkipped('Extension pdo_sqlite required.'); } self::$dbFile = tempnam(sys_get_temp_dir(), 'sf_sqlite_cache'); - $pool = new PdoCache(DriverManager::getConnection(array('driver' => 'pdo_sqlite', 'path' => self::$dbFile))); + $pool = new PdoCache(DriverManager::getConnection(['driver' => 'pdo_sqlite', 'path' => self::$dbFile])); $pool->createTable(); } @@ -43,6 +43,6 @@ class PdoDbalCacheTest extends CacheTestCase public function createSimpleCache($defaultLifetime = 0) { - return new PdoCache(DriverManager::getConnection(array('driver' => 'pdo_sqlite', 'path' => self::$dbFile)), '', $defaultLifetime); + return new PdoCache(DriverManager::getConnection(['driver' => 'pdo_sqlite', 'path' => self::$dbFile]), '', $defaultLifetime); } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PhpArrayCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PhpArrayCacheTest.php index 1bd0ca277..bcd7dea55 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PhpArrayCacheTest.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PhpArrayCacheTest.php @@ -11,16 +11,16 @@ namespace Symfony\Component\Cache\Tests\Simple; -use Symfony\Component\Cache\Tests\Adapter\FilesystemAdapterTest; use Symfony\Component\Cache\Simple\NullCache; use Symfony\Component\Cache\Simple\PhpArrayCache; +use Symfony\Component\Cache\Tests\Adapter\FilesystemAdapterTest; /** * @group time-sensitive */ class PhpArrayCacheTest extends CacheTestCase { - protected $skippedTests = array( + protected $skippedTests = [ 'testBasicUsageWithLongKey' => 'PhpArrayCache does no writes', 'testDelete' => 'PhpArrayCache does no writes', @@ -45,17 +45,19 @@ class PhpArrayCacheTest extends CacheTestCase 'testDefaultLifeTime' => 'PhpArrayCache does not allow configuring a default lifetime.', 'testPrune' => 'PhpArrayCache just proxies', - ); + ]; protected static $file; - public static function setupBeforeClass() + public static function setUpBeforeClass() { self::$file = sys_get_temp_dir().'/symfony-cache/php-array-adapter-test.php'; } protected function tearDown() { + $this->createSimpleCache()->clear(); + if (file_exists(sys_get_temp_dir().'/symfony-cache')) { FilesystemAdapterTest::rmdir(sys_get_temp_dir().'/symfony-cache'); } @@ -68,22 +70,22 @@ class PhpArrayCacheTest extends CacheTestCase public function testStore() { - $arrayWithRefs = array(); + $arrayWithRefs = []; $arrayWithRefs[0] = 123; $arrayWithRefs[1] = &$arrayWithRefs[0]; - $object = (object) array( + $object = (object) [ 'foo' => 'bar', 'foo2' => 'bar2', - ); + ]; - $expected = array( + $expected = [ 'null' => null, 'serializedString' => serialize($object), 'arrayWithRefs' => $arrayWithRefs, 'object' => $object, - 'arrayWithObject' => array('bar' => $object), - ); + 'arrayWithObject' => ['bar' => $object], + ]; $cache = new PhpArrayCache(self::$file, new NullCache()); $cache->warmUp($expected); @@ -95,13 +97,13 @@ class PhpArrayCacheTest extends CacheTestCase public function testStoredFile() { - $expected = array( + $expected = [ 'integer' => 42, 'float' => 42.42, 'boolean' => true, - 'array_simple' => array('foo', 'bar'), - 'array_associative' => array('foo' => 'bar', 'foo2' => 'bar2'), - ); + 'array_simple' => ['foo', 'bar'], + 'array_associative' => ['foo' => 'bar', 'foo2' => 'bar2'], + ]; $cache = new PhpArrayCache(self::$file, new NullCache()); $cache->warmUp($expected); @@ -116,7 +118,7 @@ class PhpArrayCacheWrapper extends PhpArrayCache { public function set($key, $value, $ttl = null) { - call_user_func(\Closure::bind(function () use ($key, $value) { + \call_user_func(\Closure::bind(function () use ($key, $value) { $this->values[$key] = $value; $this->warmUp($this->values); $this->values = eval(substr(file_get_contents($this->file), 6)); @@ -127,10 +129,10 @@ class PhpArrayCacheWrapper extends PhpArrayCache public function setMultiple($values, $ttl = null) { - if (!is_array($values) && !$values instanceof \Traversable) { + if (!\is_array($values) && !$values instanceof \Traversable) { return parent::setMultiple($values, $ttl); } - call_user_func(\Closure::bind(function () use ($values) { + \call_user_func(\Closure::bind(function () use ($values) { foreach ($values as $key => $value) { $this->values[$key] = $value; } diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PhpArrayCacheWithFallbackTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PhpArrayCacheWithFallbackTest.php index 4b6a94f70..b08c16043 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PhpArrayCacheWithFallbackTest.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PhpArrayCacheWithFallbackTest.php @@ -20,7 +20,7 @@ use Symfony\Component\Cache\Tests\Adapter\FilesystemAdapterTest; */ class PhpArrayCacheWithFallbackTest extends CacheTestCase { - protected $skippedTests = array( + protected $skippedTests = [ 'testGetInvalidKeys' => 'PhpArrayCache does no validation', 'testGetMultipleInvalidKeys' => 'PhpArrayCache does no validation', 'testDeleteInvalidKeys' => 'PhpArrayCache does no validation', @@ -32,17 +32,19 @@ class PhpArrayCacheWithFallbackTest extends CacheTestCase 'testSetMultipleInvalidTtl' => 'PhpArrayCache does no validation', 'testHasInvalidKeys' => 'PhpArrayCache does no validation', 'testPrune' => 'PhpArrayCache just proxies', - ); + ]; protected static $file; - public static function setupBeforeClass() + public static function setUpBeforeClass() { self::$file = sys_get_temp_dir().'/symfony-cache/php-array-adapter-test.php'; } protected function tearDown() { + $this->createSimpleCache()->clear(); + if (file_exists(sys_get_temp_dir().'/symfony-cache')) { FilesystemAdapterTest::rmdir(sys_get_temp_dir().'/symfony-cache'); } diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PhpFilesCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PhpFilesCacheTest.php index 7a402682a..936f29a43 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PhpFilesCacheTest.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PhpFilesCacheTest.php @@ -19,9 +19,9 @@ use Symfony\Component\Cache\Simple\PhpFilesCache; */ class PhpFilesCacheTest extends CacheTestCase { - protected $skippedTests = array( + protected $skippedTests = [ 'testDefaultLifeTime' => 'PhpFilesCache does not allow configuring a default lifetime.', - ); + ]; public function createSimpleCache() { diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/Psr6CacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/Psr6CacheTest.php index 78582894f..1bc75c906 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/Psr6CacheTest.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/Psr6CacheTest.php @@ -19,9 +19,9 @@ use Symfony\Component\Cache\Simple\Psr6Cache; */ class Psr6CacheTest extends CacheTestCase { - protected $skippedTests = array( + protected $skippedTests = [ 'testPrune' => 'Psr6Cache just proxies', - ); + ]; public function createSimpleCache($defaultLifetime = 0) { diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/RedisArrayCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/RedisArrayCacheTest.php index 3c903c8a9..ec5e4c06e 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/RedisArrayCacheTest.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/RedisArrayCacheTest.php @@ -13,12 +13,12 @@ namespace Symfony\Component\Cache\Tests\Simple; class RedisArrayCacheTest extends AbstractRedisCacheTest { - public static function setupBeforeClass() + public static function setUpBeforeClass() { parent::setupBeforeClass(); if (!class_exists('RedisArray')) { self::markTestSkipped('The RedisArray class is required.'); } - self::$redis = new \RedisArray(array(getenv('REDIS_HOST')), array('lazy_connect' => true)); + self::$redis = new \RedisArray([getenv('REDIS_HOST')], ['lazy_connect' => true]); } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/RedisCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/RedisCacheTest.php index d33421f9a..8e3f60883 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/RedisCacheTest.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/RedisCacheTest.php @@ -15,7 +15,7 @@ use Symfony\Component\Cache\Simple\RedisCache; class RedisCacheTest extends AbstractRedisCacheTest { - public static function setupBeforeClass() + public static function setUpBeforeClass() { parent::setupBeforeClass(); self::$redis = RedisCache::createConnection('redis://'.getenv('REDIS_HOST')); @@ -33,50 +33,50 @@ class RedisCacheTest extends AbstractRedisCacheTest $redis = RedisCache::createConnection('redis://'.$redisHost.'/2'); $this->assertSame(2, $redis->getDbNum()); - $redis = RedisCache::createConnection('redis://'.$redisHost, array('timeout' => 3)); + $redis = RedisCache::createConnection('redis://'.$redisHost, ['timeout' => 3]); $this->assertEquals(3, $redis->getTimeout()); $redis = RedisCache::createConnection('redis://'.$redisHost.'?timeout=4'); $this->assertEquals(4, $redis->getTimeout()); - $redis = RedisCache::createConnection('redis://'.$redisHost, array('read_timeout' => 5)); + $redis = RedisCache::createConnection('redis://'.$redisHost, ['read_timeout' => 5]); $this->assertEquals(5, $redis->getReadTimeout()); } /** * @dataProvider provideFailedCreateConnection - * @expectedException \Symfony\Component\Cache\Exception\InvalidArgumentException - * @expectedExceptionMessage Redis connection failed */ public function testFailedCreateConnection($dsn) { + $this->expectException('Symfony\Component\Cache\Exception\InvalidArgumentException'); + $this->expectExceptionMessage('Redis connection '); RedisCache::createConnection($dsn); } public function provideFailedCreateConnection() { - return array( - array('redis://localhost:1234'), - array('redis://foo@localhost'), - array('redis://localhost/123'), - ); + return [ + ['redis://localhost:1234'], + ['redis://foo@localhost'], + ['redis://localhost/123'], + ]; } /** * @dataProvider provideInvalidCreateConnection - * @expectedException \Symfony\Component\Cache\Exception\InvalidArgumentException - * @expectedExceptionMessage Invalid Redis DSN */ public function testInvalidCreateConnection($dsn) { + $this->expectException('Symfony\Component\Cache\Exception\InvalidArgumentException'); + $this->expectExceptionMessage('Invalid Redis DSN'); RedisCache::createConnection($dsn); } public function provideInvalidCreateConnection() { - return array( - array('foo://localhost'), - array('redis://'), - ); + return [ + ['foo://localhost'], + ['redis://'], + ]; } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/RedisClusterCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/RedisClusterCacheTest.php new file mode 100644 index 000000000..6b7f8039d --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/RedisClusterCacheTest.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Tests\Simple; + +class RedisClusterCacheTest extends AbstractRedisCacheTest +{ + public static function setUpBeforeClass() + { + if (!class_exists('RedisCluster')) { + self::markTestSkipped('The RedisCluster class is required.'); + } + if (!$hosts = getenv('REDIS_CLUSTER_HOSTS')) { + self::markTestSkipped('REDIS_CLUSTER_HOSTS env var is not defined.'); + } + + self::$redis = new \RedisCluster(null, explode(' ', $hosts)); + } +} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/TraceableCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/TraceableCacheTest.php index 535f93da4..e684caf36 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/TraceableCacheTest.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/TraceableCacheTest.php @@ -19,9 +19,9 @@ use Symfony\Component\Cache\Simple\TraceableCache; */ class TraceableCacheTest extends CacheTestCase { - protected $skippedTests = array( + protected $skippedTests = [ 'testPrune' => 'TraceableCache just proxies', - ); + ]; public function createSimpleCache($defaultLifetime = 0) { @@ -37,7 +37,7 @@ class TraceableCacheTest extends CacheTestCase $call = $calls[0]; $this->assertSame('get', $call->name); - $this->assertSame(array('k' => false), $call->result); + $this->assertSame(['k' => false], $call->result); $this->assertSame(0, $call->hits); $this->assertSame(1, $call->misses); $this->assertNotEmpty($call->start); @@ -61,7 +61,7 @@ class TraceableCacheTest extends CacheTestCase { $pool = $this->createSimpleCache(); $pool->set('k1', 123); - $values = $pool->getMultiple(array('k0', 'k1')); + $values = $pool->getMultiple(['k0', 'k1']); foreach ($values as $value) { } $calls = $pool->getCalls(); @@ -69,7 +69,7 @@ class TraceableCacheTest extends CacheTestCase $call = $calls[1]; $this->assertSame('getMultiple', $call->name); - $this->assertSame(array('k1' => true, 'k0' => false), $call->result); + $this->assertSame(['k1' => true, 'k0' => false], $call->result); $this->assertSame(1, $call->misses); $this->assertNotEmpty($call->start); $this->assertNotEmpty($call->end); @@ -84,7 +84,7 @@ class TraceableCacheTest extends CacheTestCase $call = $calls[0]; $this->assertSame('has', $call->name); - $this->assertSame(array('k' => false), $call->result); + $this->assertSame(['k' => false], $call->result); $this->assertNotEmpty($call->start); $this->assertNotEmpty($call->end); } @@ -99,7 +99,7 @@ class TraceableCacheTest extends CacheTestCase $call = $calls[1]; $this->assertSame('has', $call->name); - $this->assertSame(array('k' => true), $call->result); + $this->assertSame(['k' => true], $call->result); $this->assertNotEmpty($call->start); $this->assertNotEmpty($call->end); } @@ -113,7 +113,7 @@ class TraceableCacheTest extends CacheTestCase $call = $calls[0]; $this->assertSame('delete', $call->name); - $this->assertSame(array('k' => true), $call->result); + $this->assertSame(['k' => true], $call->result); $this->assertSame(0, $call->hits); $this->assertSame(0, $call->misses); $this->assertNotEmpty($call->start); @@ -123,14 +123,14 @@ class TraceableCacheTest extends CacheTestCase public function testDeleteMultipleTrace() { $pool = $this->createSimpleCache(); - $arg = array('k0', 'k1'); + $arg = ['k0', 'k1']; $pool->deleteMultiple($arg); $calls = $pool->getCalls(); $this->assertCount(1, $calls); $call = $calls[0]; $this->assertSame('deleteMultiple', $call->name); - $this->assertSame(array('keys' => $arg, 'result' => true), $call->result); + $this->assertSame(['keys' => $arg, 'result' => true], $call->result); $this->assertSame(0, $call->hits); $this->assertSame(0, $call->misses); $this->assertNotEmpty($call->start); @@ -146,7 +146,7 @@ class TraceableCacheTest extends CacheTestCase $call = $calls[0]; $this->assertSame('set', $call->name); - $this->assertSame(array('k' => true), $call->result); + $this->assertSame(['k' => true], $call->result); $this->assertSame(0, $call->hits); $this->assertSame(0, $call->misses); $this->assertNotEmpty($call->start); @@ -156,13 +156,13 @@ class TraceableCacheTest extends CacheTestCase public function testSetMultipleTrace() { $pool = $this->createSimpleCache(); - $pool->setMultiple(array('k' => 'foo')); + $pool->setMultiple(['k' => 'foo']); $calls = $pool->getCalls(); $this->assertCount(1, $calls); $call = $calls[0]; $this->assertSame('setMultiple', $call->name); - $this->assertSame(array('keys' => array('k'), 'result' => true), $call->result); + $this->assertSame(['keys' => ['k'], 'result' => true], $call->result); $this->assertSame(0, $call->hits); $this->assertSame(0, $call->misses); $this->assertNotEmpty($call->start); diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Traits/PdoPruneableTrait.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Traits/PdoPruneableTrait.php index a9c459fb8..c405de703 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Traits/PdoPruneableTrait.php +++ b/advancedcontentfilter/vendor/symfony/cache/Tests/Traits/PdoPruneableTrait.php @@ -24,11 +24,11 @@ trait PdoPruneableTrait $getPdoConn = $o->getMethod('getConnection'); $getPdoConn->setAccessible(true); - /** @var \Doctrine\DBAL\Statement $select */ + /** @var \Doctrine\DBAL\Statement|\PDOStatement $select */ $select = $getPdoConn->invoke($cache)->prepare('SELECT 1 FROM cache_items WHERE item_id LIKE :id'); $select->bindValue(':id', sprintf('%%%s', $name)); - $select->execute(); + $result = $select->execute(); - return 0 === count($select->fetchAll(\PDO::FETCH_COLUMN)); + return 1 !== (int) (\is_object($result) ? $result->fetchOne() : $select->fetch(\PDO::FETCH_COLUMN)); } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Traits/AbstractTrait.php b/advancedcontentfilter/vendor/symfony/cache/Traits/AbstractTrait.php index d7af3b559..dc291e103 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Traits/AbstractTrait.php +++ b/advancedcontentfilter/vendor/symfony/cache/Traits/AbstractTrait.php @@ -26,7 +26,7 @@ trait AbstractTrait private $namespace; private $namespaceVersion = ''; private $versioningIsEnabled = false; - private $deferred = array(); + private $deferred = []; /** * @var int|null The maximum length to enforce for identifiers or null when no limit applies @@ -54,7 +54,7 @@ trait AbstractTrait /** * Deletes all items in the pool. * - * @param string The prefix used for all identifiers managed by this pool + * @param string $namespace The prefix used for all identifiers managed by this pool * * @return bool True if the pool was successfully cleared, false otherwise */ @@ -93,7 +93,7 @@ trait AbstractTrait try { return $this->doHave($id); } catch (\Exception $e) { - CacheItem::log($this->logger, 'Failed to check if key "{key}" is cached', array('key' => $key, 'exception' => $e)); + CacheItem::log($this->logger, 'Failed to check if key "{key}" is cached', ['key' => $key, 'exception' => $e]); return false; } @@ -104,20 +104,23 @@ trait AbstractTrait */ public function clear() { + $this->deferred = []; if ($cleared = $this->versioningIsEnabled) { - $this->namespaceVersion = 2; - foreach ($this->doFetch(array('@'.$this->namespace)) as $v) { - $this->namespaceVersion = 1 + (int) $v; + $namespaceVersion = substr_replace(base64_encode(pack('V', mt_rand())), static::NS_SEPARATOR, 5); + try { + $cleared = $this->doSave([static::NS_SEPARATOR.$this->namespace => $namespaceVersion], 0); + } catch (\Exception $e) { + $cleared = false; + } + if ($cleared = true === $cleared || [] === $cleared) { + $this->namespaceVersion = $namespaceVersion; } - $this->namespaceVersion .= ':'; - $cleared = $this->doSave(array('@'.$this->namespace => $this->namespaceVersion), 0); } - $this->deferred = array(); try { return $this->doClear($this->namespace) || $cleared; } catch (\Exception $e) { - CacheItem::log($this->logger, 'Failed to clear the cache', array('exception' => $e)); + CacheItem::log($this->logger, 'Failed to clear the cache', ['exception' => $e]); return false; } @@ -128,7 +131,7 @@ trait AbstractTrait */ public function deleteItem($key) { - return $this->deleteItems(array($key)); + return $this->deleteItems([$key]); } /** @@ -136,7 +139,7 @@ trait AbstractTrait */ public function deleteItems(array $keys) { - $ids = array(); + $ids = []; foreach ($keys as $key) { $ids[$key] = $this->getId($key); @@ -156,12 +159,12 @@ trait AbstractTrait foreach ($ids as $key => $id) { try { $e = null; - if ($this->doDelete(array($id))) { + if ($this->doDelete([$id])) { continue; } } catch (\Exception $e) { } - CacheItem::log($this->logger, 'Failed to delete key "{key}"', array('key' => $key, 'exception' => $e)); + CacheItem::log($this->logger, 'Failed to delete key "{key}"', ['key' => $key, 'exception' => $e]); $ok = false; } @@ -219,9 +222,9 @@ trait AbstractTrait if (false !== $value = unserialize($value)) { return $value; } - throw new \DomainException('Failed to unserialize cached value'); + throw new \DomainException('Failed to unserialize cached value.'); } catch (\Error $e) { - throw new \ErrorException($e->getMessage(), $e->getCode(), E_ERROR, $e->getFile(), $e->getLine()); + throw new \ErrorException($e->getMessage(), $e->getCode(), \E_ERROR, $e->getFile(), $e->getLine()); } finally { ini_set('unserialize_callback_func', $unserializeCallbackHandler); } @@ -232,17 +235,24 @@ trait AbstractTrait CacheItem::validateKey($key); if ($this->versioningIsEnabled && '' === $this->namespaceVersion) { - $this->namespaceVersion = '1:'; - foreach ($this->doFetch(array('@'.$this->namespace)) as $v) { - $this->namespaceVersion = $v; + $this->namespaceVersion = '1'.static::NS_SEPARATOR; + try { + foreach ($this->doFetch([static::NS_SEPARATOR.$this->namespace]) as $v) { + $this->namespaceVersion = $v; + } + if ('1'.static::NS_SEPARATOR === $this->namespaceVersion) { + $this->namespaceVersion = substr_replace(base64_encode(pack('V', time())), static::NS_SEPARATOR, 5); + $this->doSave([static::NS_SEPARATOR.$this->namespace => $this->namespaceVersion], 0); + } + } catch (\Exception $e) { } } if (null === $this->maxIdLength) { return $this->namespace.$this->namespaceVersion.$key; } - if (strlen($id = $this->namespace.$this->namespaceVersion.$key) > $this->maxIdLength) { - $id = $this->namespace.$this->namespaceVersion.substr_replace(base64_encode(hash('sha256', $key, true)), ':', -22); + if (\strlen($id = $this->namespace.$this->namespaceVersion.$key) > $this->maxIdLength) { + $id = $this->namespace.$this->namespaceVersion.substr_replace(base64_encode(hash('sha256', $key, true)), static::NS_SEPARATOR, -(\strlen($this->namespaceVersion) + 22)); } return $id; diff --git a/advancedcontentfilter/vendor/symfony/cache/Traits/ApcuTrait.php b/advancedcontentfilter/vendor/symfony/cache/Traits/ApcuTrait.php index fe7dfbab7..2f47f8e6d 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Traits/ApcuTrait.php +++ b/advancedcontentfilter/vendor/symfony/cache/Traits/ApcuTrait.php @@ -23,15 +23,15 @@ trait ApcuTrait { public static function isSupported() { - return function_exists('apcu_fetch') && ini_get('apc.enabled'); + return \function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), \FILTER_VALIDATE_BOOLEAN); } private function init($namespace, $defaultLifetime, $version) { if (!static::isSupported()) { - throw new CacheException('APCu is not enabled'); + throw new CacheException('APCu is not enabled.'); } - if ('cli' === PHP_SAPI) { + if ('cli' === \PHP_SAPI) { ini_set('apc.use_request_time', 0); } parent::__construct($namespace, $defaultLifetime); @@ -52,13 +52,13 @@ trait ApcuTrait protected function doFetch(array $ids) { try { - foreach (apcu_fetch($ids, $ok) ?: array() as $k => $v) { + foreach (apcu_fetch($ids, $ok) ?: [] as $k => $v) { if (null !== $v || $ok) { yield $k => $v; } } } catch (\Error $e) { - throw new \ErrorException($e->getMessage(), $e->getCode(), E_ERROR, $e->getFile(), $e->getLine()); + throw new \ErrorException($e->getMessage(), $e->getCode(), \E_ERROR, $e->getFile(), $e->getLine()); } } @@ -75,8 +75,8 @@ trait ApcuTrait */ protected function doClear($namespace) { - return isset($namespace[0]) && class_exists('APCuIterator', false) && ('cli' !== PHP_SAPI || ini_get('apc.enable_cli')) - ? apcu_delete(new \APCuIterator(sprintf('/^%s/', preg_quote($namespace, '/')), APC_ITER_KEY)) + return isset($namespace[0]) && class_exists('APCuIterator', false) && ('cli' !== \PHP_SAPI || filter_var(ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOLEAN)) + ? apcu_delete(new \APCuIterator(sprintf('/^%s/', preg_quote($namespace, '/')), \APC_ITER_KEY)) : apcu_clear_cache(); } @@ -107,7 +107,7 @@ trait ApcuTrait } catch (\Exception $e) { } - if (1 === count($values)) { + if (1 === \count($values)) { // Workaround https://github.com/krakjoe/apcu/issues/170 apcu_delete(key($values)); } diff --git a/advancedcontentfilter/vendor/symfony/cache/Traits/ArrayTrait.php b/advancedcontentfilter/vendor/symfony/cache/Traits/ArrayTrait.php index b7d2ad6d6..0a60968e9 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Traits/ArrayTrait.php +++ b/advancedcontentfilter/vendor/symfony/cache/Traits/ArrayTrait.php @@ -24,8 +24,8 @@ trait ArrayTrait use LoggerAwareTrait; private $storeSerialized; - private $values = array(); - private $expiries = array(); + private $values = []; + private $expiries = []; /** * Returns all cached values, with cache miss as null. @@ -44,7 +44,7 @@ trait ArrayTrait { CacheItem::validateKey($key); - return isset($this->expiries[$key]) && ($this->expiries[$key] >= time() || !$this->deleteItem($key)); + return isset($this->expiries[$key]) && ($this->expiries[$key] > time() || !$this->deleteItem($key)); } /** @@ -52,7 +52,7 @@ trait ArrayTrait */ public function clear() { - $this->values = $this->expiries = array(); + $this->values = $this->expiries = []; return true; } @@ -81,7 +81,7 @@ trait ArrayTrait { foreach ($keys as $i => $key) { try { - if (!$isHit = isset($this->expiries[$key]) && ($this->expiries[$key] >= $now || !$this->deleteItem($key))) { + if (!$isHit = isset($this->expiries[$key]) && ($this->expiries[$key] > $now || !$this->deleteItem($key))) { $this->values[$key] = $value = null; } elseif (!$this->storeSerialized) { $value = $this->values[$key]; @@ -92,7 +92,7 @@ trait ArrayTrait $isHit = false; } } catch (\Exception $e) { - CacheItem::log($this->logger, 'Failed to unserialize key "{key}"', array('key' => $key, 'exception' => $e)); + CacheItem::log($this->logger, 'Failed to unserialize key "{key}"', ['key' => $key, 'exception' => $e]); $this->values[$key] = $value = null; $isHit = false; } diff --git a/advancedcontentfilter/vendor/symfony/cache/Traits/DoctrineTrait.php b/advancedcontentfilter/vendor/symfony/cache/Traits/DoctrineTrait.php index c87ecabaf..48623e67c 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Traits/DoctrineTrait.php +++ b/advancedcontentfilter/vendor/symfony/cache/Traits/DoctrineTrait.php @@ -45,7 +45,7 @@ trait DoctrineTrait case 'unserialize': case 'apcu_fetch': case 'apc_fetch': - throw new \ErrorException($e->getMessage(), $e->getCode(), E_ERROR, $e->getFile(), $e->getLine()); + throw new \ErrorException($e->getMessage(), $e->getCode(), \E_ERROR, $e->getFile(), $e->getLine()); } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Traits/FilesystemCommonTrait.php b/advancedcontentfilter/vendor/symfony/cache/Traits/FilesystemCommonTrait.php index b0f495e4d..8071a382b 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Traits/FilesystemCommonTrait.php +++ b/advancedcontentfilter/vendor/symfony/cache/Traits/FilesystemCommonTrait.php @@ -34,15 +34,15 @@ trait FilesystemCommonTrait if (preg_match('#[^-+_.A-Za-z0-9]#', $namespace, $match)) { throw new InvalidArgumentException(sprintf('Namespace contains "%s" but only characters in [-+_.A-Za-z0-9] are allowed.', $match[0])); } - $directory .= DIRECTORY_SEPARATOR.$namespace; + $directory .= \DIRECTORY_SEPARATOR.$namespace; } if (!file_exists($directory)) { @mkdir($directory, 0777, true); } - $directory .= DIRECTORY_SEPARATOR; + $directory .= \DIRECTORY_SEPARATOR; // On Windows the whole path is limited to 258 chars - if ('\\' === DIRECTORY_SEPARATOR && strlen($directory) > 234) { - throw new InvalidArgumentException(sprintf('Cache directory too long (%s)', $directory)); + if ('\\' === \DIRECTORY_SEPARATOR && \strlen($directory) > 234) { + throw new InvalidArgumentException(sprintf('Cache directory too long (%s).', $directory)); } $this->directory = $directory; @@ -99,7 +99,7 @@ trait FilesystemCommonTrait private function getFile($id, $mkdir = false) { $hash = str_replace('/', '-', base64_encode(hash('sha256', static::class.$id, true))); - $dir = $this->directory.strtoupper($hash[0].DIRECTORY_SEPARATOR.$hash[1].DIRECTORY_SEPARATOR); + $dir = $this->directory.strtoupper($hash[0].\DIRECTORY_SEPARATOR.$hash[1].\DIRECTORY_SEPARATOR); if ($mkdir && !file_exists($dir)) { @mkdir($dir, 0777, true); @@ -116,6 +116,16 @@ trait FilesystemCommonTrait throw new \ErrorException($message, 0, $type, $file, $line); } + public function __sleep() + { + throw new \BadMethodCallException('Cannot serialize '.__CLASS__); + } + + public function __wakeup() + { + throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); + } + public function __destruct() { if (method_exists(parent::class, '__destruct')) { diff --git a/advancedcontentfilter/vendor/symfony/cache/Traits/FilesystemTrait.php b/advancedcontentfilter/vendor/symfony/cache/Traits/FilesystemTrait.php index 23974b3bc..9d7f55784 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Traits/FilesystemTrait.php +++ b/advancedcontentfilter/vendor/symfony/cache/Traits/FilesystemTrait.php @@ -52,7 +52,7 @@ trait FilesystemTrait */ protected function doFetch(array $ids) { - $values = array(); + $values = []; $now = time(); foreach ($ids as $id) { @@ -83,7 +83,7 @@ trait FilesystemTrait { $file = $this->getFile($id); - return file_exists($file) && (@filemtime($file) > time() || $this->doFetch(array($id))); + return file_exists($file) && (@filemtime($file) > time() || $this->doFetch([$id])); } /** @@ -99,7 +99,7 @@ trait FilesystemTrait } if (!$ok && !is_writable($this->directory)) { - throw new CacheException(sprintf('Cache directory is not writable (%s)', $this->directory)); + throw new CacheException(sprintf('Cache directory is not writable (%s).', $this->directory)); } return $ok; diff --git a/advancedcontentfilter/vendor/symfony/cache/Traits/MemcachedTrait.php b/advancedcontentfilter/vendor/symfony/cache/Traits/MemcachedTrait.php index 9b877efb0..34d0208ef 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Traits/MemcachedTrait.php +++ b/advancedcontentfilter/vendor/symfony/cache/Traits/MemcachedTrait.php @@ -22,32 +22,32 @@ use Symfony\Component\Cache\Exception\InvalidArgumentException; */ trait MemcachedTrait { - private static $defaultClientOptions = array( + private static $defaultClientOptions = [ 'persistent_id' => null, 'username' => null, 'password' => null, - 'serializer' => 'php', - ); + \Memcached::OPT_SERIALIZER => \Memcached::SERIALIZER_PHP, + ]; private $client; private $lazyClient; public static function isSupported() { - return extension_loaded('memcached') && version_compare(phpversion('memcached'), '2.2.0', '>='); + return \extension_loaded('memcached') && version_compare(phpversion('memcached'), '2.2.0', '>='); } private function init(\Memcached $client, $namespace, $defaultLifetime) { if (!static::isSupported()) { - throw new CacheException('Memcached >= 2.2.0 is required'); + throw new CacheException('Memcached >= 2.2.0 is required.'); } - if ('Memcached' === get_class($client)) { + if ('Memcached' === \get_class($client)) { $opt = $client->getOption(\Memcached::OPT_SERIALIZER); if (\Memcached::SERIALIZER_PHP !== $opt && \Memcached::SERIALIZER_IGBINARY !== $opt) { throw new CacheException('MemcachedAdapter: "serializer" option must be "php" or "igbinary".'); } - $this->maxIdLength -= strlen($client->getOption(\Memcached::OPT_PREFIX_KEY)); + $this->maxIdLength -= \strlen($client->getOption(\Memcached::OPT_PREFIX_KEY)); $this->client = $client; } else { $this->lazyClient = $client; @@ -64,24 +64,24 @@ trait MemcachedTrait * * Examples for servers: * - 'memcached://user:pass@localhost?weight=33' - * - array(array('localhost', 11211, 33)) + * - [['localhost', 11211, 33]] * - * @param array[]|string|string[] An array of servers, a DSN, or an array of DSNs - * @param array An array of options + * @param array[]|string|string[] $servers An array of servers, a DSN, or an array of DSNs + * @param array $options An array of options * * @return \Memcached * * @throws \ErrorException When invalid options or servers are provided */ - public static function createConnection($servers, array $options = array()) + public static function createConnection($servers, array $options = []) { - if (is_string($servers)) { - $servers = array($servers); - } elseif (!is_array($servers)) { - throw new InvalidArgumentException(sprintf('MemcachedAdapter::createClient() expects array or string as first argument, %s given.', gettype($servers))); + if (\is_string($servers)) { + $servers = [$servers]; + } elseif (!\is_array($servers)) { + throw new InvalidArgumentException(sprintf('MemcachedAdapter::createClient() expects array or string as first argument, "%s" given.', \gettype($servers))); } if (!static::isSupported()) { - throw new CacheException('Memcached >= 2.2.0 is required'); + throw new CacheException('Memcached >= 2.2.0 is required.'); } set_error_handler(function ($type, $msg, $file, $line) { throw new \ErrorException($msg, 0, $type, $file, $line); }); try { @@ -92,59 +92,60 @@ trait MemcachedTrait // parse any DSN in $servers foreach ($servers as $i => $dsn) { - if (is_array($dsn)) { + if (\is_array($dsn)) { continue; } if (0 !== strpos($dsn, 'memcached://')) { - throw new InvalidArgumentException(sprintf('Invalid Memcached DSN: %s does not start with "memcached://"', $dsn)); + throw new InvalidArgumentException(sprintf('Invalid Memcached DSN: "%s" does not start with "memcached://".', $dsn)); } $params = preg_replace_callback('#^memcached://(?:([^@]*+)@)?#', function ($m) use (&$username, &$password) { if (!empty($m[1])) { - list($username, $password) = explode(':', $m[1], 2) + array(1 => null); + list($username, $password) = explode(':', $m[1], 2) + [1 => null]; } return 'file://'; }, $dsn); if (false === $params = parse_url($params)) { - throw new InvalidArgumentException(sprintf('Invalid Memcached DSN: %s', $dsn)); + throw new InvalidArgumentException(sprintf('Invalid Memcached DSN: "%s".', $dsn)); } if (!isset($params['host']) && !isset($params['path'])) { - throw new InvalidArgumentException(sprintf('Invalid Memcached DSN: %s', $dsn)); + throw new InvalidArgumentException(sprintf('Invalid Memcached DSN: "%s".', $dsn)); } if (isset($params['path']) && preg_match('#/(\d+)$#', $params['path'], $m)) { $params['weight'] = $m[1]; - $params['path'] = substr($params['path'], 0, -strlen($m[0])); + $params['path'] = substr($params['path'], 0, -\strlen($m[0])); } - $params += array( + $params += [ 'host' => isset($params['host']) ? $params['host'] : $params['path'], 'port' => isset($params['host']) ? 11211 : null, 'weight' => 0, - ); + ]; if (isset($params['query'])) { parse_str($params['query'], $query); $params += $query; $options = $query + $options; } - $servers[$i] = array($params['host'], $params['port'], $params['weight']); + $servers[$i] = [$params['host'], $params['port'], $params['weight']]; } // set client's options unset($options['persistent_id'], $options['username'], $options['password'], $options['weight'], $options['lazy']); - $options = array_change_key_case($options, CASE_UPPER); + $options = array_change_key_case($options, \CASE_UPPER); $client->setOption(\Memcached::OPT_BINARY_PROTOCOL, true); $client->setOption(\Memcached::OPT_NO_BLOCK, true); - if (!array_key_exists('LIBKETAMA_COMPATIBLE', $options) && !array_key_exists(\Memcached::OPT_LIBKETAMA_COMPATIBLE, $options)) { + $client->setOption(\Memcached::OPT_TCP_NODELAY, true); + if (!\array_key_exists('LIBKETAMA_COMPATIBLE', $options) && !\array_key_exists(\Memcached::OPT_LIBKETAMA_COMPATIBLE, $options)) { $client->setOption(\Memcached::OPT_LIBKETAMA_COMPATIBLE, true); } foreach ($options as $name => $value) { - if (is_int($name)) { + if (\is_int($name)) { continue; } if ('HASH' === $name || 'SERIALIZER' === $name || 'DISTRIBUTION' === $name) { - $value = constant('Memcached::'.$name.'_'.strtoupper($value)); + $value = \constant('Memcached::'.$name.'_'.strtoupper($value)); } - $opt = constant('Memcached::OPT_'.$name); + $opt = \constant('Memcached::OPT_'.$name); unset($options[$name]); $options[$opt] = $value; @@ -153,14 +154,14 @@ trait MemcachedTrait // set client's servers, taking care of persistent connections if (!$client->isPristine()) { - $oldServers = array(); + $oldServers = []; foreach ($client->getServerList() as $server) { - $oldServers[] = array($server['host'], $server['port']); + $oldServers[] = [$server['host'], $server['port']]; } - $newServers = array(); + $newServers = []; foreach ($servers as $server) { - if (1 < count($server)) { + if (1 < \count($server)) { $server = array_values($server); unset($server[2]); $server[1] = (int) $server[1]; @@ -169,12 +170,12 @@ trait MemcachedTrait } if ($oldServers !== $newServers) { - // before resetting, ensure $servers is valid - $client->addServers($servers); $client->resetServerList(); + $client->addServers($servers); } + } else { + $client->addServers($servers); } - $client->addServers($servers); if (null !== $username || null !== $password) { if (!method_exists($client, 'setSaslAuthData')) { @@ -198,7 +199,12 @@ trait MemcachedTrait $lifetime += time(); } - return $this->checkResultCode($this->getClient()->setMulti($values, $lifetime)); + $encodedValues = []; + foreach ($values as $key => $value) { + $encodedValues[rawurlencode($key)] = $value; + } + + return $this->checkResultCode($this->getClient()->setMulti($encodedValues, $lifetime)); } /** @@ -208,9 +214,18 @@ trait MemcachedTrait { $unserializeCallbackHandler = ini_set('unserialize_callback_func', __CLASS__.'::handleUnserializeCallback'); try { - return $this->checkResultCode($this->getClient()->getMulti($ids)); + $encodedIds = array_map('rawurlencode', $ids); + + $encodedResult = $this->checkResultCode($this->getClient()->getMulti($encodedIds)); + + $result = []; + foreach ($encodedResult as $key => $value) { + $result[rawurldecode($key)] = $value; + } + + return $result; } catch (\Error $e) { - throw new \ErrorException($e->getMessage(), $e->getCode(), E_ERROR, $e->getFile(), $e->getLine()); + throw new \ErrorException($e->getMessage(), $e->getCode(), \E_ERROR, $e->getFile(), $e->getLine()); } finally { ini_set('unserialize_callback_func', $unserializeCallbackHandler); } @@ -221,7 +236,7 @@ trait MemcachedTrait */ protected function doHave($id) { - return false !== $this->getClient()->get($id) || $this->checkResultCode(\Memcached::RES_SUCCESS === $this->client->getResultCode()); + return false !== $this->getClient()->get(rawurlencode($id)) || $this->checkResultCode(\Memcached::RES_SUCCESS === $this->client->getResultCode()); } /** @@ -230,9 +245,11 @@ trait MemcachedTrait protected function doDelete(array $ids) { $ok = true; - foreach ($this->checkResultCode($this->getClient()->deleteMulti($ids)) as $result) { + $encodedIds = array_map('rawurlencode', $ids); + foreach ($this->checkResultCode($this->getClient()->deleteMulti($encodedIds)) as $result) { if (\Memcached::RES_SUCCESS !== $result && \Memcached::RES_NOTFOUND !== $result) { $ok = false; + break; } } @@ -244,7 +261,7 @@ trait MemcachedTrait */ protected function doClear($namespace) { - return false; + return '' === $namespace && $this->getClient()->flush(); } private function checkResultCode($result) @@ -255,7 +272,7 @@ trait MemcachedTrait return $result; } - throw new CacheException(sprintf('MemcachedAdapter client error: %s.', strtolower($this->client->getResultMessage()))); + throw new CacheException('MemcachedAdapter client error: '.strtolower($this->client->getResultMessage())); } /** diff --git a/advancedcontentfilter/vendor/symfony/cache/Traits/PdoTrait.php b/advancedcontentfilter/vendor/symfony/cache/Traits/PdoTrait.php index a88099ecb..917e8dd13 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Traits/PdoTrait.php +++ b/advancedcontentfilter/vendor/symfony/cache/Traits/PdoTrait.php @@ -12,8 +12,8 @@ namespace Symfony\Component\Cache\Traits; use Doctrine\DBAL\Connection; -use Doctrine\DBAL\Driver\ServerInfoAwareConnection; use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Driver\ServerInfoAwareConnection; use Doctrine\DBAL\Schema\Schema; use Symfony\Component\Cache\Exception\InvalidArgumentException; @@ -33,7 +33,7 @@ trait PdoTrait private $timeCol = 'item_time'; private $username = ''; private $password = ''; - private $connectionOptions = array(); + private $connectionOptions = []; private $namespace; private function init($connOrDsn, $namespace, $defaultLifetime, array $options) @@ -44,16 +44,16 @@ trait PdoTrait if ($connOrDsn instanceof \PDO) { if (\PDO::ERRMODE_EXCEPTION !== $connOrDsn->getAttribute(\PDO::ATTR_ERRMODE)) { - throw new InvalidArgumentException(sprintf('"%s" requires PDO error mode attribute be set to throw Exceptions (i.e. $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION))', __CLASS__)); + throw new InvalidArgumentException(sprintf('"%s" requires PDO error mode attribute be set to throw Exceptions (i.e. $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)).', __CLASS__)); } $this->conn = $connOrDsn; } elseif ($connOrDsn instanceof Connection) { $this->conn = $connOrDsn; - } elseif (is_string($connOrDsn)) { + } elseif (\is_string($connOrDsn)) { $this->dsn = $connOrDsn; } else { - throw new InvalidArgumentException(sprintf('"%s" requires PDO or Doctrine\DBAL\Connection instance or DSN string as first argument, "%s" given.', __CLASS__, is_object($connOrDsn) ? get_class($connOrDsn) : gettype($connOrDsn))); + throw new InvalidArgumentException(sprintf('"%s" requires PDO or Doctrine\DBAL\Connection instance or DSN string as first argument, "%s" given.', __CLASS__, \is_object($connOrDsn) ? \get_class($connOrDsn) : \gettype($connOrDsn))); } $this->table = isset($options['db_table']) ? $options['db_table'] : $this->table; @@ -85,27 +85,31 @@ trait PdoTrait $conn = $this->getConnection(); if ($conn instanceof Connection) { - $types = array( + $types = [ 'mysql' => 'binary', 'sqlite' => 'text', 'pgsql' => 'string', 'oci' => 'string', 'sqlsrv' => 'string', - ); + ]; if (!isset($types[$this->driver])) { throw new \DomainException(sprintf('Creating the cache table is currently not implemented for PDO driver "%s".', $this->driver)); } $schema = new Schema(); $table = $schema->createTable($this->table); - $table->addColumn($this->idCol, $types[$this->driver], array('length' => 255)); - $table->addColumn($this->dataCol, 'blob', array('length' => 16777215)); - $table->addColumn($this->lifetimeCol, 'integer', array('unsigned' => true, 'notnull' => false)); - $table->addColumn($this->timeCol, 'integer', array('unsigned' => true)); - $table->setPrimaryKey(array($this->idCol)); + $table->addColumn($this->idCol, $types[$this->driver], ['length' => 255]); + $table->addColumn($this->dataCol, 'blob', ['length' => 16777215]); + $table->addColumn($this->lifetimeCol, 'integer', ['unsigned' => true, 'notnull' => false]); + $table->addColumn($this->timeCol, 'integer', ['unsigned' => true]); + $table->setPrimaryKey([$this->idCol]); foreach ($schema->toSql($conn->getDatabasePlatform()) as $sql) { - $conn->exec($sql); + if (method_exists($conn, 'executeStatement')) { + $conn->executeStatement($sql); + } else { + $conn->exec($sql); + } } return; @@ -136,7 +140,11 @@ trait PdoTrait throw new \DomainException(sprintf('Creating the cache table is currently not implemented for PDO driver "%s".', $this->driver)); } - $conn->exec($sql); + if (method_exists($conn, 'executeStatement')) { + $conn->executeStatement($sql); + } else { + $conn->exec($sql); + } } /** @@ -166,27 +174,34 @@ trait PdoTrait protected function doFetch(array $ids) { $now = time(); - $expired = array(); + $expired = []; - $sql = str_pad('', (count($ids) << 1) - 1, '?,'); + $sql = str_pad('', (\count($ids) << 1) - 1, '?,'); $sql = "SELECT $this->idCol, CASE WHEN $this->lifetimeCol IS NULL OR $this->lifetimeCol + $this->timeCol > ? THEN $this->dataCol ELSE NULL END FROM $this->table WHERE $this->idCol IN ($sql)"; $stmt = $this->getConnection()->prepare($sql); $stmt->bindValue($i = 1, $now, \PDO::PARAM_INT); foreach ($ids as $id) { $stmt->bindValue(++$i, $id); } - $stmt->execute(); + $result = $stmt->execute(); - while ($row = $stmt->fetch(\PDO::FETCH_NUM)) { + if (\is_object($result)) { + $result = $result->iterateNumeric(); + } else { + $stmt->setFetchMode(\PDO::FETCH_NUM); + $result = $stmt; + } + + foreach ($result as $row) { if (null === $row[1]) { $expired[] = $row[0]; } else { - yield $row[0] => parent::unserialize(is_resource($row[1]) ? stream_get_contents($row[1]) : $row[1]); + yield $row[0] => parent::unserialize(\is_resource($row[1]) ? stream_get_contents($row[1]) : $row[1]); } } if ($expired) { - $sql = str_pad('', (count($expired) << 1) - 1, '?,'); + $sql = str_pad('', (\count($expired) << 1) - 1, '?,'); $sql = "DELETE FROM $this->table WHERE $this->lifetimeCol + $this->timeCol <= ? AND $this->idCol IN ($sql)"; $stmt = $this->getConnection()->prepare($sql); $stmt->bindValue($i = 1, $now, \PDO::PARAM_INT); @@ -207,9 +222,9 @@ trait PdoTrait $stmt->bindValue(':id', $id); $stmt->bindValue(':time', time(), \PDO::PARAM_INT); - $stmt->execute(); + $result = $stmt->execute(); - return (bool) $stmt->fetchColumn(); + return (bool) (\is_object($result) ? $result->fetchOne() : $stmt->fetchColumn()); } /** @@ -229,7 +244,11 @@ trait PdoTrait $sql = "DELETE FROM $this->table WHERE $this->idCol LIKE '$namespace%'"; } - $conn->exec($sql); + if (method_exists($conn, 'executeStatement')) { + $conn->executeStatement($sql); + } else { + $conn->exec($sql); + } return true; } @@ -239,7 +258,7 @@ trait PdoTrait */ protected function doDelete(array $ids) { - $sql = str_pad('', (count($ids) << 1) - 1, '?,'); + $sql = str_pad('', (\count($ids) << 1) - 1, '?,'); $sql = "DELETE FROM $this->table WHERE $this->idCol IN ($sql)"; $stmt = $this->getConnection()->prepare($sql); $stmt->execute(array_values($ids)); @@ -252,8 +271,8 @@ trait PdoTrait */ protected function doSave(array $values, $lifetime) { - $serialized = array(); - $failed = array(); + $serialized = []; + $failed = []; foreach ($values as $id => $value) { try { @@ -329,9 +348,9 @@ trait PdoTrait } foreach ($serialized as $id => $data) { - $stmt->execute(); + $result = $stmt->execute(); - if (null === $driver && !$stmt->rowCount()) { + if (null === $driver && !(\is_object($result) ? $result->rowCount() : $stmt->rowCount())) { try { $insertStmt->execute(); } catch (DBALException $e) { @@ -357,25 +376,37 @@ trait PdoTrait if ($this->conn instanceof \PDO) { $this->driver = $this->conn->getAttribute(\PDO::ATTR_DRIVER_NAME); } else { - switch ($this->driver = $this->conn->getDriver()->getName()) { - case 'mysqli': - case 'pdo_mysql': - case 'drizzle_pdo_mysql': + $driver = $this->conn->getDriver(); + + switch (true) { + case $driver instanceof \Doctrine\DBAL\Driver\AbstractMySQLDriver: + case $driver instanceof \Doctrine\DBAL\Driver\DrizzlePDOMySql\Driver: + case $driver instanceof \Doctrine\DBAL\Driver\Mysqli\Driver: + case $driver instanceof \Doctrine\DBAL\Driver\PDOMySql\Driver: + case $driver instanceof \Doctrine\DBAL\Driver\PDO\MySQL\Driver: $this->driver = 'mysql'; break; - case 'pdo_sqlite': + case $driver instanceof \Doctrine\DBAL\Driver\PDOSqlite\Driver: + case $driver instanceof \Doctrine\DBAL\Driver\PDO\SQLite\Driver: $this->driver = 'sqlite'; break; - case 'pdo_pgsql': + case $driver instanceof \Doctrine\DBAL\Driver\PDOPgSql\Driver: + case $driver instanceof \Doctrine\DBAL\Driver\PDO\PgSQL\Driver: $this->driver = 'pgsql'; break; - case 'oci8': - case 'pdo_oracle': + case $driver instanceof \Doctrine\DBAL\Driver\OCI8\Driver: + case $driver instanceof \Doctrine\DBAL\Driver\PDOOracle\Driver: + case $driver instanceof \Doctrine\DBAL\Driver\PDO\OCI\Driver: $this->driver = 'oci'; break; - case 'pdo_sqlsrv': + case $driver instanceof \Doctrine\DBAL\Driver\SQLSrv\Driver: + case $driver instanceof \Doctrine\DBAL\Driver\PDOSqlsrv\Driver: + case $driver instanceof \Doctrine\DBAL\Driver\PDO\SQLSrv\Driver: $this->driver = 'sqlsrv'; break; + default: + $this->driver = \get_class($driver); + break; } } } diff --git a/advancedcontentfilter/vendor/symfony/cache/Traits/PhpArrayTrait.php b/advancedcontentfilter/vendor/symfony/cache/Traits/PhpArrayTrait.php index ae634d6ba..972c75121 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Traits/PhpArrayTrait.php +++ b/advancedcontentfilter/vendor/symfony/cache/Traits/PhpArrayTrait.php @@ -28,6 +28,8 @@ trait PhpArrayTrait private $values; private $zendDetectUnicode; + private static $valuesCache = []; + /** * Store an array of cached values. * @@ -37,21 +39,21 @@ trait PhpArrayTrait { if (file_exists($this->file)) { if (!is_file($this->file)) { - throw new InvalidArgumentException(sprintf('Cache path exists and is not a file: %s.', $this->file)); + throw new InvalidArgumentException(sprintf('Cache path exists and is not a file: "%s".', $this->file)); } if (!is_writable($this->file)) { - throw new InvalidArgumentException(sprintf('Cache file is not writable: %s.', $this->file)); + throw new InvalidArgumentException(sprintf('Cache file is not writable: "%s".', $this->file)); } } else { - $directory = dirname($this->file); + $directory = \dirname($this->file); if (!is_dir($directory) && !@mkdir($directory, 0777, true)) { - throw new InvalidArgumentException(sprintf('Cache directory does not exist and cannot be created: %s.', $directory)); + throw new InvalidArgumentException(sprintf('Cache directory does not exist and cannot be created: "%s".', $directory)); } if (!is_writable($directory)) { - throw new InvalidArgumentException(sprintf('Cache directory is not writable: %s.', $directory)); + throw new InvalidArgumentException(sprintf('Cache directory is not writable: "%s".', $directory)); } } @@ -60,21 +62,21 @@ trait PhpArrayTrait // This file has been auto-generated by the Symfony Cache Component. -return array( +return [ EOF; foreach ($values as $key => $value) { - CacheItem::validateKey(is_int($key) ? (string) $key : $key); + CacheItem::validateKey(\is_int($key) ? (string) $key : $key); - if (null === $value || is_object($value)) { + if (null === $value || \is_object($value)) { try { $value = serialize($value); } catch (\Exception $e) { - throw new InvalidArgumentException(sprintf('Cache key "%s" has non-serializable %s value.', $key, get_class($value)), 0, $e); + throw new InvalidArgumentException(sprintf('Cache key "%s" has non-serializable "%s" value.', $key, \get_class($value)), 0, $e); } - } elseif (is_array($value)) { + } elseif (\is_array($value)) { try { $serialized = serialize($value); $unserialized = unserialize($serialized); @@ -85,19 +87,19 @@ EOF; if ($unserialized !== $value || (false !== strpos($serialized, ';R:') && preg_match('/;R:[1-9]/', $serialized))) { $value = $serialized; } - } elseif (is_string($value)) { + } elseif (\is_string($value)) { // Serialize strings if they could be confused with serialized objects or arrays if ('N;' === $value || (isset($value[2]) && ':' === $value[1])) { $value = serialize($value); } } elseif (!is_scalar($value)) { - throw new InvalidArgumentException(sprintf('Cache key "%s" has non-serializable %s value.', $key, gettype($value))); + throw new InvalidArgumentException(sprintf('Cache key "%s" has non-serializable "%s" value.', $key, \gettype($value))); } $dump .= var_export($key, true).' => '.var_export($value, true).",\n"; } - $dump .= "\n);\n"; + $dump .= "\n];\n"; $dump = str_replace("' . \"\\0\" . '", "\0", $dump); $tmpFile = uniqid($this->file, true); @@ -107,6 +109,7 @@ EOF; unset($serialized, $unserialized, $value, $dump); @rename($tmpFile, $this->file); + unset(self::$valuesCache[$this->file]); $this->initialize(); } @@ -116,9 +119,10 @@ EOF; */ public function clear() { - $this->values = array(); + $this->values = []; $cleared = @unlink($this->file) || !file_exists($this->file); + unset(self::$valuesCache[$this->file]); return $this->pool->clear() && $cleared; } @@ -128,11 +132,17 @@ EOF; */ private function initialize() { + if (isset(self::$valuesCache[$this->file])) { + $this->values = self::$valuesCache[$this->file]; + + return; + } + if ($this->zendDetectUnicode) { $zmb = ini_set('zend.detect_unicode', 0); } try { - $this->values = file_exists($this->file) ? (include $this->file ?: array()) : array(); + $this->values = self::$valuesCache[$this->file] = file_exists($this->file) ? (include $this->file ?: []) : []; } finally { if ($this->zendDetectUnicode) { ini_set('zend.detect_unicode', $zmb); diff --git a/advancedcontentfilter/vendor/symfony/cache/Traits/PhpFilesTrait.php b/advancedcontentfilter/vendor/symfony/cache/Traits/PhpFilesTrait.php index c800e1a17..2668b26c1 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Traits/PhpFilesTrait.php +++ b/advancedcontentfilter/vendor/symfony/cache/Traits/PhpFilesTrait.php @@ -30,7 +30,7 @@ trait PhpFilesTrait public static function isSupported() { - return function_exists('opcache_invalidate') && ini_get('opcache.enable'); + return \function_exists('opcache_invalidate') && filter_var(ini_get('opcache.enable'), \FILTER_VALIDATE_BOOLEAN); } /** @@ -40,7 +40,7 @@ trait PhpFilesTrait { $time = time(); $pruned = true; - $allowCompile = 'cli' !== PHP_SAPI || ini_get('opcache.enable_cli'); + $allowCompile = 'cli' !== \PHP_SAPI || filter_var(ini_get('opcache.enable_cli'), \FILTER_VALIDATE_BOOLEAN); set_error_handler($this->includeHandler); try { @@ -67,7 +67,7 @@ trait PhpFilesTrait */ protected function doFetch(array $ids) { - $values = array(); + $values = []; $now = time(); if ($this->zendDetectUnicode) { @@ -96,7 +96,7 @@ trait PhpFilesTrait foreach ($values as $id => $value) { if ('N;' === $value) { $values[$id] = null; - } elseif (is_string($value) && isset($value[2]) && ':' === $value[1]) { + } elseif (\is_string($value) && isset($value[2]) && ':' === $value[1]) { $values[$id] = parent::unserialize($value); } } @@ -109,7 +109,7 @@ trait PhpFilesTrait */ protected function doHave($id) { - return (bool) $this->doFetch(array($id)); + return (bool) $this->doFetch([$id]); } /** @@ -118,26 +118,26 @@ trait PhpFilesTrait protected function doSave(array $values, $lifetime) { $ok = true; - $data = array($lifetime ? time() + $lifetime : PHP_INT_MAX, ''); - $allowCompile = 'cli' !== PHP_SAPI || ini_get('opcache.enable_cli'); + $data = [$lifetime ? time() + $lifetime : \PHP_INT_MAX, '']; + $allowCompile = 'cli' !== \PHP_SAPI || filter_var(ini_get('opcache.enable_cli'), \FILTER_VALIDATE_BOOLEAN); foreach ($values as $key => $value) { - if (null === $value || is_object($value)) { + if (null === $value || \is_object($value)) { $value = serialize($value); - } elseif (is_array($value)) { + } elseif (\is_array($value)) { $serialized = serialize($value); $unserialized = parent::unserialize($serialized); // Store arrays serialized if they contain any objects or references if ($unserialized !== $value || (false !== strpos($serialized, ';R:') && preg_match('/;R:[1-9]/', $serialized))) { $value = $serialized; } - } elseif (is_string($value)) { + } elseif (\is_string($value)) { // Serialize strings if they could be confused with serialized objects or arrays if ('N;' === $value || (isset($value[2]) && ':' === $value[1])) { $value = serialize($value); } } elseif (!is_scalar($value)) { - throw new InvalidArgumentException(sprintf('Cache key "%s" has non-serializable %s value.', $key, gettype($value))); + throw new InvalidArgumentException(sprintf('Cache key "%s" has non-serializable "%s" value.', $key, \gettype($value))); } $data[1] = $value; @@ -150,7 +150,7 @@ trait PhpFilesTrait } if (!$ok && !is_writable($this->directory)) { - throw new CacheException(sprintf('Cache directory is not writable (%s)', $this->directory)); + throw new CacheException(sprintf('Cache directory is not writable (%s).', $this->directory)); } return $ok; diff --git a/advancedcontentfilter/vendor/symfony/cache/Traits/ProxyTrait.php b/advancedcontentfilter/vendor/symfony/cache/Traits/ProxyTrait.php index 06dba7e59..d9e085b9e 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Traits/ProxyTrait.php +++ b/advancedcontentfilter/vendor/symfony/cache/Traits/ProxyTrait.php @@ -16,6 +16,8 @@ use Symfony\Component\Cache\ResettableInterface; /** * @author Nicolas Grekas + * + * @internal */ trait ProxyTrait { diff --git a/advancedcontentfilter/vendor/symfony/cache/Traits/RedisProxy.php b/advancedcontentfilter/vendor/symfony/cache/Traits/RedisProxy.php index b328f94cd..98ea3aba7 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Traits/RedisProxy.php +++ b/advancedcontentfilter/vendor/symfony/cache/Traits/RedisProxy.php @@ -32,7 +32,7 @@ class RedisProxy { $this->ready ?: $this->ready = $this->initializer->__invoke($this->redis); - return \call_user_func_array(array($this->redis, $method), $args); + return \call_user_func_array([$this->redis, $method], $args); } public function hscan($strKey, &$iIterator, $strPattern = null, $iCount = null) diff --git a/advancedcontentfilter/vendor/symfony/cache/Traits/RedisTrait.php b/advancedcontentfilter/vendor/symfony/cache/Traits/RedisTrait.php index ac8b5a5fc..a30d6d3fa 100644 --- a/advancedcontentfilter/vendor/symfony/cache/Traits/RedisTrait.php +++ b/advancedcontentfilter/vendor/symfony/cache/Traits/RedisTrait.php @@ -11,10 +11,9 @@ namespace Symfony\Component\Cache\Traits; -use Predis\Connection\Factory; use Predis\Connection\Aggregate\ClusterInterface; -use Predis\Connection\Aggregate\PredisCluster; use Predis\Connection\Aggregate\RedisCluster; +use Predis\Connection\Factory; use Predis\Response\Status; use Symfony\Component\Cache\Exception\CacheException; use Symfony\Component\Cache\Exception\InvalidArgumentException; @@ -27,7 +26,7 @@ use Symfony\Component\Cache\Exception\InvalidArgumentException; */ trait RedisTrait { - private static $defaultConnectionOptions = array( + private static $defaultConnectionOptions = [ 'class' => null, 'persistent' => 0, 'persistent_id' => null, @@ -35,23 +34,21 @@ trait RedisTrait 'read_timeout' => 0, 'retry_interval' => 0, 'lazy' => false, - ); + ]; private $redis; /** * @param \Redis|\RedisArray|\RedisCluster|\Predis\Client $redisClient */ - public function init($redisClient, $namespace = '', $defaultLifetime = 0) + private function init($redisClient, $namespace = '', $defaultLifetime = 0) { parent::__construct($namespace, $defaultLifetime); if (preg_match('#[^-+_.A-Za-z0-9]#', $namespace, $match)) { throw new InvalidArgumentException(sprintf('RedisAdapter namespace contains "%s" but only characters in [-+_.A-Za-z0-9] are allowed.', $match[0])); } - if ($redisClient instanceof \RedisCluster) { - $this->enableVersioning(); - } elseif (!$redisClient instanceof \Redis && !$redisClient instanceof \RedisArray && !$redisClient instanceof \Predis\Client && !$redisClient instanceof RedisProxy) { - throw new InvalidArgumentException(sprintf('%s() expects parameter 1 to be Redis, RedisArray, RedisCluster or Predis\Client, %s given', __METHOD__, is_object($redisClient) ? get_class($redisClient) : gettype($redisClient))); + if (!$redisClient instanceof \Redis && !$redisClient instanceof \RedisArray && !$redisClient instanceof \RedisCluster && !$redisClient instanceof \Predis\Client && !$redisClient instanceof RedisProxy) { + throw new InvalidArgumentException(sprintf('"%s()" expects parameter 1 to be Redis, RedisArray, RedisCluster or Predis\Client, "%s" given.', __METHOD__, \is_object($redisClient) ? \get_class($redisClient) : \gettype($redisClient))); } $this->redis = $redisClient; } @@ -73,10 +70,10 @@ trait RedisTrait * * @return \Redis|\Predis\Client According to the "class" option */ - public static function createConnection($dsn, array $options = array()) + public static function createConnection($dsn, array $options = []) { if (0 !== strpos($dsn, 'redis://')) { - throw new InvalidArgumentException(sprintf('Invalid Redis DSN: %s does not start with "redis://"', $dsn)); + throw new InvalidArgumentException(sprintf('Invalid Redis DSN: "%s" does not start with "redis://".', $dsn)); } $params = preg_replace_callback('#^redis://(?:(?:[^:@]*+:)?([^@]*+)@)?#', function ($m) use (&$auth) { if (isset($m[1])) { @@ -86,34 +83,34 @@ trait RedisTrait return 'file://'; }, $dsn); if (false === $params = parse_url($params)) { - throw new InvalidArgumentException(sprintf('Invalid Redis DSN: %s', $dsn)); + throw new InvalidArgumentException(sprintf('Invalid Redis DSN: "%s".', $dsn)); } if (!isset($params['host']) && !isset($params['path'])) { - throw new InvalidArgumentException(sprintf('Invalid Redis DSN: %s', $dsn)); + throw new InvalidArgumentException(sprintf('Invalid Redis DSN: "%s".', $dsn)); } if (isset($params['path']) && preg_match('#/(\d+)$#', $params['path'], $m)) { $params['dbindex'] = $m[1]; - $params['path'] = substr($params['path'], 0, -strlen($m[0])); + $params['path'] = substr($params['path'], 0, -\strlen($m[0])); } if (isset($params['host'])) { $scheme = 'tcp'; } else { $scheme = 'unix'; } - $params += array( + $params += [ 'host' => isset($params['host']) ? $params['host'] : $params['path'], 'port' => isset($params['host']) ? 6379 : null, 'dbindex' => 0, - ); + ]; if (isset($params['query'])) { parse_str($params['query'], $query); $params += $query; } $params += $options + self::$defaultConnectionOptions; - if (null === $params['class'] && !extension_loaded('redis') && !class_exists(\Predis\Client::class)) { - throw new CacheException(sprintf('Cannot find the "redis" extension, and "predis/predis" is not installed: %s', $dsn)); + if (null === $params['class'] && !\extension_loaded('redis') && !class_exists(\Predis\Client::class)) { + throw new CacheException(sprintf('Cannot find the "redis" extension, and "predis/predis" is not installed: "%s".', $dsn)); } - $class = null === $params['class'] ? (extension_loaded('redis') ? \Redis::class : \Predis\Client::class) : $params['class']; + $class = null === $params['class'] ? (\extension_loaded('redis') ? \Redis::class : \Predis\Client::class) : $params['class']; if (is_a($class, \Redis::class, true)) { $connect = $params['persistent'] || $params['persistent_id'] ? 'pconnect' : 'connect'; @@ -122,21 +119,24 @@ trait RedisTrait $initializer = function ($redis) use ($connect, $params, $dsn, $auth) { try { @$redis->{$connect}($params['host'], $params['port'], $params['timeout'], $params['persistent_id'], $params['retry_interval']); + + set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; }); + $isConnected = $redis->isConnected(); + restore_error_handler(); + if (!$isConnected) { + $error = preg_match('/^Redis::p?connect\(\): (.*)/', $error, $error) ? sprintf(' (%s)', $error[1]) : ''; + throw new InvalidArgumentException(sprintf('Redis connection "%s" failed: ', $dsn).$error.'.'); + } + + if ((null !== $auth && !$redis->auth($auth)) + || ($params['dbindex'] && !$redis->select($params['dbindex'])) + || ($params['read_timeout'] && !$redis->setOption(\Redis::OPT_READ_TIMEOUT, $params['read_timeout'])) + ) { + $e = preg_replace('/^ERR /', '', $redis->getLastError()); + throw new InvalidArgumentException(sprintf('Redis connection "%s" failed: ', $dsn).$e.'.'); + } } catch (\RedisException $e) { - throw new InvalidArgumentException(sprintf('Redis connection failed (%s): %s', $e->getMessage(), $dsn)); - } - - if (@!$redis->isConnected()) { - $e = ($e = error_get_last()) && preg_match('/^Redis::p?connect\(\): (.*)/', $e['message'], $e) ? sprintf(' (%s)', $e[1]) : ''; - throw new InvalidArgumentException(sprintf('Redis connection failed%s: %s', $e, $dsn)); - } - - if ((null !== $auth && !$redis->auth($auth)) - || ($params['dbindex'] && !$redis->select($params['dbindex'])) - || ($params['read_timeout'] && !$redis->setOption(\Redis::OPT_READ_TIMEOUT, $params['read_timeout'])) - ) { - $e = preg_replace('/^ERR /', '', $redis->getLastError()); - throw new InvalidArgumentException(sprintf('Redis connection failed (%s): %s', $e, $dsn)); + throw new InvalidArgumentException(sprintf('Redis connection "%s" failed: ', $dsn).$e->getMessage()); } return true; @@ -153,9 +153,9 @@ trait RedisTrait $params['password'] = $auth; $redis = new $class((new Factory())->create($params)); } elseif (class_exists($class, false)) { - throw new InvalidArgumentException(sprintf('"%s" is not a subclass of "Redis" or "Predis\Client"', $class)); + throw new InvalidArgumentException(sprintf('"%s" is not a subclass of "Redis" or "Predis\Client".', $class)); } else { - throw new InvalidArgumentException(sprintf('Class "%s" does not exist', $class)); + throw new InvalidArgumentException(sprintf('Class "%s" does not exist.', $class)); } return $redis; @@ -166,18 +166,35 @@ trait RedisTrait */ protected function doFetch(array $ids) { - if ($ids) { + if (!$ids) { + return []; + } + + $result = []; + + if ($this->redis instanceof \Predis\Client && $this->redis->getConnection() instanceof ClusterInterface) { $values = $this->pipeline(function () use ($ids) { foreach ($ids as $id) { - yield 'get' => array($id); + yield 'get' => [$id]; } }); - foreach ($values as $id => $v) { - if ($v) { - yield $id => parent::unserialize($v); - } + } else { + $values = $this->redis->mget($ids); + + if (!\is_array($values) || \count($values) !== \count($ids)) { + return []; + } + + $values = array_combine($ids, $values); + } + + foreach ($values as $id => $v) { + if ($v) { + $result[$id] = parent::unserialize($v); } } + + return $result; } /** @@ -193,32 +210,31 @@ trait RedisTrait */ protected function doClear($namespace) { - // When using a native Redis cluster, clearing the cache is done by versioning in AbstractTrait::clear(). - // This means old keys are not really removed until they expire and may need gargage collection. - $cleared = true; - $hosts = array($this->redis); - $evalArgs = array(array($namespace), 0); + $hosts = [$this->redis]; + $evalArgs = [[$namespace], 0]; if ($this->redis instanceof \Predis\Client) { - $evalArgs = array(0, $namespace); + $evalArgs = [0, $namespace]; $connection = $this->redis->getConnection(); - if ($connection instanceof PredisCluster) { - $hosts = array(); + if ($connection instanceof ClusterInterface && $connection instanceof \Traversable) { + $hosts = []; foreach ($connection as $c) { $hosts[] = new \Predis\Client($c); } - } elseif ($connection instanceof RedisCluster) { - return false; } } elseif ($this->redis instanceof \RedisArray) { - $hosts = array(); + $hosts = []; foreach ($this->redis->_hosts() as $host) { $hosts[] = $this->redis->_instance($host); } } elseif ($this->redis instanceof \RedisCluster) { - return false; + $hosts = []; + foreach ($this->redis->_masters() as $host) { + $hosts[] = $h = new \Redis(); + $h->connect($host[0], $host[1]); + } } foreach ($hosts as $host) { if (!isset($namespace[0])) { @@ -240,12 +256,12 @@ trait RedisTrait $cursor = null; do { $keys = $host instanceof \Predis\Client ? $host->scan($cursor, 'MATCH', $namespace.'*', 'COUNT', 1000) : $host->scan($cursor, $namespace.'*', 1000); - if (isset($keys[1]) && is_array($keys[1])) { + if (isset($keys[1]) && \is_array($keys[1])) { $cursor = $keys[0]; $keys = $keys[1]; } if ($keys) { - $host->del($keys); + $this->doDelete($keys); } } while ($cursor = (int) $cursor); } @@ -258,7 +274,17 @@ trait RedisTrait */ protected function doDelete(array $ids) { - if ($ids) { + if (!$ids) { + return true; + } + + if ($this->redis instanceof \Predis\Client && $this->redis->getConnection() instanceof ClusterInterface) { + $this->pipeline(function () use ($ids) { + foreach ($ids as $id) { + yield 'del' => [$id]; + } + })->rewind(); + } else { $this->redis->del($ids); } @@ -270,8 +296,8 @@ trait RedisTrait */ protected function doSave(array $values, $lifetime) { - $serialized = array(); - $failed = array(); + $serialized = []; + $failed = []; foreach ($values as $id => $value) { try { @@ -288,9 +314,9 @@ trait RedisTrait $results = $this->pipeline(function () use ($serialized, $lifetime) { foreach ($serialized as $id => $value) { if (0 >= $lifetime) { - yield 'set' => array($id, $value); + yield 'set' => [$id, $value]; } else { - yield 'setEx' => array($id, $lifetime, $value); + yield 'setEx' => [$id, $lifetime, $value]; } } }); @@ -305,24 +331,33 @@ trait RedisTrait private function pipeline(\Closure $generator) { - $ids = array(); + $ids = []; - if ($this->redis instanceof \Predis\Client && !$this->redis->getConnection() instanceof ClusterInterface) { + if ($this->redis instanceof \RedisCluster || ($this->redis instanceof \Predis\Client && $this->redis->getConnection() instanceof RedisCluster)) { + // phpredis & predis don't support pipelining with RedisCluster + // see https://github.com/phpredis/phpredis/blob/develop/cluster.markdown#pipelining + // see https://github.com/nrk/predis/issues/267#issuecomment-123781423 + $results = []; + foreach ($generator() as $command => $args) { + $results[] = \call_user_func_array([$this->redis, $command], $args); + $ids[] = $args[0]; + } + } elseif ($this->redis instanceof \Predis\Client) { $results = $this->redis->pipeline(function ($redis) use ($generator, &$ids) { foreach ($generator() as $command => $args) { - call_user_func_array(array($redis, $command), $args); + \call_user_func_array([$redis, $command], $args); $ids[] = $args[0]; } }); } elseif ($this->redis instanceof \RedisArray) { - $connections = $results = $ids = array(); + $connections = $results = $ids = []; foreach ($generator() as $command => $args) { if (!isset($connections[$h = $this->redis->_target($args[0])])) { - $connections[$h] = array($this->redis->_instance($h), -1); + $connections[$h] = [$this->redis->_instance($h), -1]; $connections[$h][0]->multi(\Redis::PIPELINE); } - call_user_func_array(array($connections[$h][0], $command), $args); - $results[] = array($h, ++$connections[$h][1]); + \call_user_func_array([$connections[$h][0], $command], $args); + $results[] = [$h, ++$connections[$h][1]]; $ids[] = $args[0]; } foreach ($connections as $h => $c) { @@ -331,19 +366,10 @@ trait RedisTrait foreach ($results as $k => list($h, $c)) { $results[$k] = $connections[$h][$c]; } - } elseif ($this->redis instanceof \RedisCluster || ($this->redis instanceof \Predis\Client && $this->redis->getConnection() instanceof ClusterInterface)) { - // phpredis & predis don't support pipelining with RedisCluster - // see https://github.com/phpredis/phpredis/blob/develop/cluster.markdown#pipelining - // see https://github.com/nrk/predis/issues/267#issuecomment-123781423 - $results = array(); - foreach ($generator() as $command => $args) { - $results[] = call_user_func_array(array($this->redis, $command), $args); - $ids[] = $args[0]; - } } else { $this->redis->multi(\Redis::PIPELINE); foreach ($generator() as $command => $args) { - call_user_func_array(array($this->redis, $command), $args); + \call_user_func_array([$this->redis, $command], $args); $ids[] = $args[0]; } $results = $this->redis->exec(); diff --git a/advancedcontentfilter/vendor/symfony/cache/composer.json b/advancedcontentfilter/vendor/symfony/cache/composer.json index e13cd9675..f412e4f17 100644 --- a/advancedcontentfilter/vendor/symfony/cache/composer.json +++ b/advancedcontentfilter/vendor/symfony/cache/composer.json @@ -28,9 +28,9 @@ }, "require-dev": { "cache/integration-tests": "dev-master", - "doctrine/cache": "~1.6", - "doctrine/dbal": "~2.4", - "predis/predis": "~1.0" + "doctrine/cache": "^1.6", + "doctrine/dbal": "^2.4|^3.0", + "predis/predis": "^1.0" }, "conflict": { "symfony/var-dumper": "<3.3" @@ -41,10 +41,5 @@ "/Tests/" ] }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - } + "minimum-stability": "dev" } diff --git a/advancedcontentfilter/vendor/symfony/cache/phpunit.xml.dist b/advancedcontentfilter/vendor/symfony/cache/phpunit.xml.dist index 9b3c30d76..c35458ca4 100644 --- a/advancedcontentfilter/vendor/symfony/cache/phpunit.xml.dist +++ b/advancedcontentfilter/vendor/symfony/cache/phpunit.xml.dist @@ -1,7 +1,7 @@ - Cache\IntegrationTests - Doctrine\Common\Cache - Symfony\Component\Cache - Symfony\Component\Cache\Tests\Fixtures - Symfony\Component\Cache\Traits + Cache\IntegrationTests + Doctrine\Common\Cache + Symfony\Component\Cache + Symfony\Component\Cache\Tests\Fixtures + Symfony\Component\Cache\Traits diff --git a/advancedcontentfilter/vendor/symfony/expression-language/Compiler.php b/advancedcontentfilter/vendor/symfony/expression-language/Compiler.php index 66d106041..1ae427b94 100644 --- a/advancedcontentfilter/vendor/symfony/expression-language/Compiler.php +++ b/advancedcontentfilter/vendor/symfony/expression-language/Compiler.php @@ -110,22 +110,22 @@ class Compiler */ public function repr($value) { - if (is_int($value) || is_float($value)) { - if (false !== $locale = setlocale(LC_NUMERIC, 0)) { - setlocale(LC_NUMERIC, 'C'); + if (\is_int($value) || \is_float($value)) { + if (false !== $locale = setlocale(\LC_NUMERIC, 0)) { + setlocale(\LC_NUMERIC, 'C'); } $this->raw($value); if (false !== $locale) { - setlocale(LC_NUMERIC, $locale); + setlocale(\LC_NUMERIC, $locale); } } elseif (null === $value) { $this->raw('null'); - } elseif (is_bool($value)) { + } elseif (\is_bool($value)) { $this->raw($value ? 'true' : 'false'); - } elseif (is_array($value)) { - $this->raw('array('); + } elseif (\is_array($value)) { + $this->raw('['); $first = true; foreach ($value as $key => $value) { if (!$first) { @@ -136,7 +136,7 @@ class Compiler $this->raw(' => '); $this->repr($value); } - $this->raw(')'); + $this->raw(']'); } else { $this->string($value); } diff --git a/advancedcontentfilter/vendor/symfony/expression-language/ExpressionFunction.php b/advancedcontentfilter/vendor/symfony/expression-language/ExpressionFunction.php index ad775dbd9..77c88f66d 100644 --- a/advancedcontentfilter/vendor/symfony/expression-language/ExpressionFunction.php +++ b/advancedcontentfilter/vendor/symfony/expression-language/ExpressionFunction.php @@ -76,23 +76,23 @@ class ExpressionFunction public static function fromPhp($phpFunctionName, $expressionFunctionName = null) { $phpFunctionName = ltrim($phpFunctionName, '\\'); - if (!function_exists($phpFunctionName)) { + if (!\function_exists($phpFunctionName)) { throw new \InvalidArgumentException(sprintf('PHP function "%s" does not exist.', $phpFunctionName)); } $parts = explode('\\', $phpFunctionName); - if (!$expressionFunctionName && count($parts) > 1) { + if (!$expressionFunctionName && \count($parts) > 1) { throw new \InvalidArgumentException(sprintf('An expression function name must be defined when PHP function "%s" is namespaced.', $phpFunctionName)); } $compiler = function () use ($phpFunctionName) { - return sprintf('\%s(%s)', $phpFunctionName, implode(', ', func_get_args())); + return sprintf('\%s(%s)', $phpFunctionName, implode(', ', \func_get_args())); }; $evaluator = function () use ($phpFunctionName) { - $args = func_get_args(); + $args = \func_get_args(); - return call_user_func_array($phpFunctionName, array_splice($args, 1)); + return \call_user_func_array($phpFunctionName, array_splice($args, 1)); }; return new self($expressionFunctionName ?: end($parts), $compiler, $evaluator); diff --git a/advancedcontentfilter/vendor/symfony/expression-language/ExpressionLanguage.php b/advancedcontentfilter/vendor/symfony/expression-language/ExpressionLanguage.php index a9cfc4caf..16476669c 100644 --- a/advancedcontentfilter/vendor/symfony/expression-language/ExpressionLanguage.php +++ b/advancedcontentfilter/vendor/symfony/expression-language/ExpressionLanguage.php @@ -28,20 +28,20 @@ class ExpressionLanguage private $parser; private $compiler; - protected $functions = array(); + protected $functions = []; /** * @param CacheItemPoolInterface $cache * @param ExpressionFunctionProviderInterface[] $providers */ - public function __construct($cache = null, array $providers = array()) + public function __construct($cache = null, array $providers = []) { if (null !== $cache) { if ($cache instanceof ParserCacheInterface) { - @trigger_error(sprintf('Passing an instance of %s as constructor argument for %s is deprecated as of 3.2 and will be removed in 4.0. Pass an instance of %s instead.', ParserCacheInterface::class, self::class, CacheItemPoolInterface::class), E_USER_DEPRECATED); + @trigger_error(sprintf('Passing an instance of %s as constructor argument for %s is deprecated as of 3.2 and will be removed in 4.0. Pass an instance of %s instead.', ParserCacheInterface::class, self::class, CacheItemPoolInterface::class), \E_USER_DEPRECATED); $cache = new ParserCacheAdapter($cache); } elseif (!$cache instanceof CacheItemPoolInterface) { - throw new \InvalidArgumentException(sprintf('Cache argument has to implement %s.', CacheItemPoolInterface::class)); + throw new \InvalidArgumentException(sprintf('Cache argument has to implement "%s".', CacheItemPoolInterface::class)); } } @@ -60,7 +60,7 @@ class ExpressionLanguage * * @return string The compiled PHP source code */ - public function compile($expression, $names = array()) + public function compile($expression, $names = []) { return $this->getCompiler()->compile($this->parse($expression, $names)->getNodes())->getSource(); } @@ -71,9 +71,9 @@ class ExpressionLanguage * @param Expression|string $expression The expression to compile * @param array $values An array of values * - * @return string The result of the evaluation of the expression + * @return mixed The result of the evaluation of the expression */ - public function evaluate($expression, $values = array()) + public function evaluate($expression, $values = []) { return $this->parse($expression, array_keys($values))->getNodes()->evaluate($this->functions, $values); } @@ -93,10 +93,10 @@ class ExpressionLanguage } asort($names); - $cacheKeyItems = array(); + $cacheKeyItems = []; foreach ($names as $nameKey => $name) { - $cacheKeyItems[] = is_int($nameKey) ? $name : $nameKey.':'.$name; + $cacheKeyItems[] = \is_int($nameKey) ? $name : $nameKey.':'.$name; } $cacheItem = $this->cache->getItem(rawurlencode($expression.'//'.implode('|', $cacheKeyItems))); @@ -129,7 +129,7 @@ class ExpressionLanguage throw new \LogicException('Registering functions after calling evaluate(), compile() or parse() is not supported.'); } - $this->functions[$name] = array('compiler' => $compiler, 'evaluator' => $evaluator); + $this->functions[$name] = ['compiler' => $compiler, 'evaluator' => $evaluator]; } public function addFunction(ExpressionFunction $function) diff --git a/advancedcontentfilter/vendor/symfony/expression-language/LICENSE b/advancedcontentfilter/vendor/symfony/expression-language/LICENSE index 21d7fb9e2..9e936ec04 100644 --- a/advancedcontentfilter/vendor/symfony/expression-language/LICENSE +++ b/advancedcontentfilter/vendor/symfony/expression-language/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2018 Fabien Potencier +Copyright (c) 2004-2020 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/advancedcontentfilter/vendor/symfony/expression-language/Lexer.php b/advancedcontentfilter/vendor/symfony/expression-language/Lexer.php index aeeda8a85..ace847b0d 100644 --- a/advancedcontentfilter/vendor/symfony/expression-language/Lexer.php +++ b/advancedcontentfilter/vendor/symfony/expression-language/Lexer.php @@ -29,11 +29,11 @@ class Lexer */ public function tokenize($expression) { - $expression = str_replace(array("\r", "\n", "\t", "\v", "\f"), ' ', $expression); + $expression = str_replace(["\r", "\n", "\t", "\v", "\f"], ' ', $expression); $cursor = 0; - $tokens = array(); - $brackets = array(); - $end = strlen($expression); + $tokens = []; + $brackets = []; + $end = \strlen($expression); while ($cursor < $end) { if (' ' == $expression[$cursor]) { @@ -45,26 +45,26 @@ class Lexer if (preg_match('/[0-9]+(?:\.[0-9]+)?/A', $expression, $match, 0, $cursor)) { // numbers $number = (float) $match[0]; // floats - if (preg_match('/^[0-9]+$/', $match[0]) && $number <= PHP_INT_MAX) { + if (preg_match('/^[0-9]+$/', $match[0]) && $number <= \PHP_INT_MAX) { $number = (int) $match[0]; // integers lower than the maximum } $tokens[] = new Token(Token::NUMBER_TYPE, $number, $cursor + 1); - $cursor += strlen($match[0]); + $cursor += \strlen($match[0]); } elseif (false !== strpos('([{', $expression[$cursor])) { // opening bracket - $brackets[] = array($expression[$cursor], $cursor); + $brackets[] = [$expression[$cursor], $cursor]; $tokens[] = new Token(Token::PUNCTUATION_TYPE, $expression[$cursor], $cursor + 1); ++$cursor; } elseif (false !== strpos(')]}', $expression[$cursor])) { // closing bracket if (empty($brackets)) { - throw new SyntaxError(sprintf('Unexpected "%s"', $expression[$cursor]), $cursor, $expression); + throw new SyntaxError(sprintf('Unexpected "%s".', $expression[$cursor]), $cursor, $expression); } list($expect, $cur) = array_pop($brackets); if ($expression[$cursor] != strtr($expect, '([{', ')]}')) { - throw new SyntaxError(sprintf('Unclosed "%s"', $expect), $cur, $expression); + throw new SyntaxError(sprintf('Unclosed "%s".', $expect), $cur, $expression); } $tokens[] = new Token(Token::PUNCTUATION_TYPE, $expression[$cursor], $cursor + 1); @@ -72,11 +72,11 @@ class Lexer } elseif (preg_match('/"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\'/As', $expression, $match, 0, $cursor)) { // strings $tokens[] = new Token(Token::STRING_TYPE, stripcslashes(substr($match[0], 1, -1)), $cursor + 1); - $cursor += strlen($match[0]); - } elseif (preg_match('/not in(?=[\s(])|\!\=\=|not(?=[\s(])|and(?=[\s(])|\=\=\=|\>\=|or(?=[\s(])|\<\=|\*\*|\.\.|in(?=[\s(])|&&|\|\||matches|\=\=|\!\=|\*|~|%|\/|\>|\||\!|\^|&|\+|\<|\-/A', $expression, $match, 0, $cursor)) { + $cursor += \strlen($match[0]); + } elseif (preg_match('/(?<=^|[\s(])not in(?=[\s(])|\!\=\=|(?<=^|[\s(])not(?=[\s(])|(?<=^|[\s(])and(?=[\s(])|\=\=\=|\>\=|(?<=^|[\s(])or(?=[\s(])|\<\=|\*\*|\.\.|(?<=^|[\s(])in(?=[\s(])|&&|\|\||(?<=^|[\s(])matches|\=\=|\!\=|\*|~|%|\/|\>|\||\!|\^|&|\+|\<|\-/A', $expression, $match, 0, $cursor)) { // operators $tokens[] = new Token(Token::OPERATOR_TYPE, $match[0], $cursor + 1); - $cursor += strlen($match[0]); + $cursor += \strlen($match[0]); } elseif (false !== strpos('.,?:', $expression[$cursor])) { // punctuation $tokens[] = new Token(Token::PUNCTUATION_TYPE, $expression[$cursor], $cursor + 1); @@ -84,10 +84,10 @@ class Lexer } elseif (preg_match('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/A', $expression, $match, 0, $cursor)) { // names $tokens[] = new Token(Token::NAME_TYPE, $match[0], $cursor + 1); - $cursor += strlen($match[0]); + $cursor += \strlen($match[0]); } else { // unlexable - throw new SyntaxError(sprintf('Unexpected character "%s"', $expression[$cursor]), $cursor, $expression); + throw new SyntaxError(sprintf('Unexpected character "%s".', $expression[$cursor]), $cursor, $expression); } } @@ -95,7 +95,7 @@ class Lexer if (!empty($brackets)) { list($expect, $cur) = array_pop($brackets); - throw new SyntaxError(sprintf('Unclosed "%s"', $expect), $cur, $expression); + throw new SyntaxError(sprintf('Unclosed "%s".', $expect), $cur, $expression); } return new TokenStream($tokens, $expression); diff --git a/advancedcontentfilter/vendor/symfony/expression-language/Node/ArgumentsNode.php b/advancedcontentfilter/vendor/symfony/expression-language/Node/ArgumentsNode.php index 1c78d8054..e9849a448 100644 --- a/advancedcontentfilter/vendor/symfony/expression-language/Node/ArgumentsNode.php +++ b/advancedcontentfilter/vendor/symfony/expression-language/Node/ArgumentsNode.php @@ -27,7 +27,7 @@ class ArgumentsNode extends ArrayNode public function toArray() { - $array = array(); + $array = []; foreach ($this->getKeyValuePairs() as $pair) { $array[] = $pair['value']; diff --git a/advancedcontentfilter/vendor/symfony/expression-language/Node/ArrayNode.php b/advancedcontentfilter/vendor/symfony/expression-language/Node/ArrayNode.php index e1a2f2e90..921319a74 100644 --- a/advancedcontentfilter/vendor/symfony/expression-language/Node/ArrayNode.php +++ b/advancedcontentfilter/vendor/symfony/expression-language/Node/ArrayNode.php @@ -41,14 +41,14 @@ class ArrayNode extends Node */ public function compile(Compiler $compiler) { - $compiler->raw('array('); + $compiler->raw('['); $this->compileArguments($compiler); - $compiler->raw(')'); + $compiler->raw(']'); } public function evaluate($functions, $values) { - $result = array(); + $result = []; foreach ($this->getKeyValuePairs() as $pair) { $result[$pair['key']->evaluate($functions, $values)] = $pair['value']->evaluate($functions, $values); } @@ -58,12 +58,12 @@ class ArrayNode extends Node public function toArray() { - $value = array(); + $value = []; foreach ($this->getKeyValuePairs() as $pair) { $value[$pair['key']->attributes['value']] = $pair['value']; } - $array = array(); + $array = []; if ($this->isHash($value)) { foreach ($value as $k => $v) { @@ -88,9 +88,9 @@ class ArrayNode extends Node protected function getKeyValuePairs() { - $pairs = array(); + $pairs = []; foreach (array_chunk($this->nodes, 2) as $pair) { - $pairs[] = array('key' => $pair[0], 'value' => $pair[1]); + $pairs[] = ['key' => $pair[0], 'value' => $pair[1]]; } return $pairs; diff --git a/advancedcontentfilter/vendor/symfony/expression-language/Node/BinaryNode.php b/advancedcontentfilter/vendor/symfony/expression-language/Node/BinaryNode.php index 33b4c8f08..549161b37 100644 --- a/advancedcontentfilter/vendor/symfony/expression-language/Node/BinaryNode.php +++ b/advancedcontentfilter/vendor/symfony/expression-language/Node/BinaryNode.php @@ -20,24 +20,24 @@ use Symfony\Component\ExpressionLanguage\Compiler; */ class BinaryNode extends Node { - private static $operators = array( + private static $operators = [ '~' => '.', 'and' => '&&', 'or' => '||', - ); + ]; - private static $functions = array( + private static $functions = [ '**' => 'pow', '..' => 'range', 'in' => 'in_array', 'not in' => '!in_array', - ); + ]; public function __construct($operator, Node $left, Node $right) { parent::__construct( - array('left' => $left, 'right' => $right), - array('operator' => $operator) + ['left' => $left, 'right' => $right], + ['operator' => $operator] ); } @@ -93,7 +93,7 @@ class BinaryNode extends Node $right = $this->nodes['right']->evaluate($functions, $values); if ('not in' === $operator) { - return !in_array($left, $right); + return !\in_array($left, $right); } $f = self::$functions[$operator]; @@ -135,9 +135,9 @@ class BinaryNode extends Node case '<=': return $left <= $right; case 'not in': - return !in_array($left, $right); + return !\in_array($left, $right); case 'in': - return in_array($left, $right); + return \in_array($left, $right); case '+': return $left + $right; case '-': @@ -147,8 +147,16 @@ class BinaryNode extends Node case '*': return $left * $right; case '/': + if (0 == $right) { + throw new \DivisionByZeroError('Division by zero.'); + } + return $left / $right; case '%': + if (0 == $right) { + throw new \DivisionByZeroError('Modulo by zero.'); + } + return $left % $right; case 'matches': return preg_match($right, $left); @@ -157,6 +165,6 @@ class BinaryNode extends Node public function toArray() { - return array('(', $this->nodes['left'], ' '.$this->attributes['operator'].' ', $this->nodes['right'], ')'); + return ['(', $this->nodes['left'], ' '.$this->attributes['operator'].' ', $this->nodes['right'], ')']; } } diff --git a/advancedcontentfilter/vendor/symfony/expression-language/Node/ConditionalNode.php b/advancedcontentfilter/vendor/symfony/expression-language/Node/ConditionalNode.php index 9db0f931a..ca1b484bc 100644 --- a/advancedcontentfilter/vendor/symfony/expression-language/Node/ConditionalNode.php +++ b/advancedcontentfilter/vendor/symfony/expression-language/Node/ConditionalNode.php @@ -23,7 +23,7 @@ class ConditionalNode extends Node public function __construct(Node $expr1, Node $expr2, Node $expr3) { parent::__construct( - array('expr1' => $expr1, 'expr2' => $expr2, 'expr3' => $expr3) + ['expr1' => $expr1, 'expr2' => $expr2, 'expr3' => $expr3] ); } @@ -51,6 +51,6 @@ class ConditionalNode extends Node public function toArray() { - return array('(', $this->nodes['expr1'], ' ? ', $this->nodes['expr2'], ' : ', $this->nodes['expr3'], ')'); + return ['(', $this->nodes['expr1'], ' ? ', $this->nodes['expr2'], ' : ', $this->nodes['expr3'], ')']; } } diff --git a/advancedcontentfilter/vendor/symfony/expression-language/Node/ConstantNode.php b/advancedcontentfilter/vendor/symfony/expression-language/Node/ConstantNode.php index 733d481b2..670e52ed4 100644 --- a/advancedcontentfilter/vendor/symfony/expression-language/Node/ConstantNode.php +++ b/advancedcontentfilter/vendor/symfony/expression-language/Node/ConstantNode.php @@ -26,8 +26,8 @@ class ConstantNode extends Node { $this->isIdentifier = $isIdentifier; parent::__construct( - array(), - array('value' => $value) + [], + ['value' => $value] ); } @@ -43,7 +43,7 @@ class ConstantNode extends Node public function toArray() { - $array = array(); + $array = []; $value = $this->attributes['value']; if ($this->isIdentifier) { @@ -56,7 +56,7 @@ class ConstantNode extends Node $array[] = 'null'; } elseif (is_numeric($value)) { $array[] = $value; - } elseif (!is_array($value)) { + } elseif (!\is_array($value)) { $array[] = $this->dumpString($value); } elseif ($this->isHash($value)) { foreach ($value as $k => $v) { diff --git a/advancedcontentfilter/vendor/symfony/expression-language/Node/FunctionNode.php b/advancedcontentfilter/vendor/symfony/expression-language/Node/FunctionNode.php index 13928c8d4..90008d5d4 100644 --- a/advancedcontentfilter/vendor/symfony/expression-language/Node/FunctionNode.php +++ b/advancedcontentfilter/vendor/symfony/expression-language/Node/FunctionNode.php @@ -23,36 +23,36 @@ class FunctionNode extends Node public function __construct($name, Node $arguments) { parent::__construct( - array('arguments' => $arguments), - array('name' => $name) + ['arguments' => $arguments], + ['name' => $name] ); } public function compile(Compiler $compiler) { - $arguments = array(); + $arguments = []; foreach ($this->nodes['arguments']->nodes as $node) { $arguments[] = $compiler->subcompile($node); } $function = $compiler->getFunction($this->attributes['name']); - $compiler->raw(call_user_func_array($function['compiler'], $arguments)); + $compiler->raw(\call_user_func_array($function['compiler'], $arguments)); } public function evaluate($functions, $values) { - $arguments = array($values); + $arguments = [$values]; foreach ($this->nodes['arguments']->nodes as $node) { $arguments[] = $node->evaluate($functions, $values); } - return call_user_func_array($functions[$this->attributes['name']]['evaluator'], $arguments); + return \call_user_func_array($functions[$this->attributes['name']]['evaluator'], $arguments); } public function toArray() { - $array = array(); + $array = []; $array[] = $this->attributes['name']; foreach ($this->nodes['arguments']->nodes as $node) { diff --git a/advancedcontentfilter/vendor/symfony/expression-language/Node/GetAttrNode.php b/advancedcontentfilter/vendor/symfony/expression-language/Node/GetAttrNode.php index 2ecba97f7..dffe0e30f 100644 --- a/advancedcontentfilter/vendor/symfony/expression-language/Node/GetAttrNode.php +++ b/advancedcontentfilter/vendor/symfony/expression-language/Node/GetAttrNode.php @@ -27,8 +27,8 @@ class GetAttrNode extends Node public function __construct(Node $node, Node $attribute, ArrayNode $arguments, $type) { parent::__construct( - array('node' => $node, 'attribute' => $attribute, 'arguments' => $arguments), - array('type' => $type) + ['node' => $node, 'attribute' => $attribute, 'arguments' => $arguments], + ['type' => $type] ); } @@ -69,7 +69,7 @@ class GetAttrNode extends Node switch ($this->attributes['type']) { case self::PROPERTY_CALL: $obj = $this->nodes['node']->evaluate($functions, $values); - if (!is_object($obj)) { + if (!\is_object($obj)) { throw new \RuntimeException('Unable to get a property on a non-object.'); } @@ -79,18 +79,24 @@ class GetAttrNode extends Node case self::METHOD_CALL: $obj = $this->nodes['node']->evaluate($functions, $values); - if (!is_object($obj)) { + if (!\is_object($obj)) { throw new \RuntimeException('Unable to get a property on a non-object.'); } - if (!is_callable($toCall = array($obj, $this->nodes['attribute']->attributes['value']))) { - throw new \RuntimeException(sprintf('Unable to call method "%s" of object "%s".', $this->nodes['attribute']->attributes['value'], get_class($obj))); + if (!\is_callable($toCall = [$obj, $this->nodes['attribute']->attributes['value']])) { + throw new \RuntimeException(sprintf('Unable to call method "%s" of object "%s".', $this->nodes['attribute']->attributes['value'], \get_class($obj))); } - return call_user_func_array($toCall, $this->nodes['arguments']->evaluate($functions, $values)); + $arguments = $this->nodes['arguments']->evaluate($functions, $values); + + if (\PHP_VERSION_ID >= 80000) { + $arguments = array_values($arguments); + } + + return \call_user_func_array($toCall, $arguments); case self::ARRAY_CALL: $array = $this->nodes['node']->evaluate($functions, $values); - if (!is_array($array) && !$array instanceof \ArrayAccess) { + if (!\is_array($array) && !$array instanceof \ArrayAccess) { throw new \RuntimeException('Unable to get an item on a non-array.'); } @@ -102,13 +108,13 @@ class GetAttrNode extends Node { switch ($this->attributes['type']) { case self::PROPERTY_CALL: - return array($this->nodes['node'], '.', $this->nodes['attribute']); + return [$this->nodes['node'], '.', $this->nodes['attribute']]; case self::METHOD_CALL: - return array($this->nodes['node'], '.', $this->nodes['attribute'], '(', $this->nodes['arguments'], ')'); + return [$this->nodes['node'], '.', $this->nodes['attribute'], '(', $this->nodes['arguments'], ')']; case self::ARRAY_CALL: - return array($this->nodes['node'], '[', $this->nodes['attribute'], ']'); + return [$this->nodes['node'], '[', $this->nodes['attribute'], ']']; } } } diff --git a/advancedcontentfilter/vendor/symfony/expression-language/Node/NameNode.php b/advancedcontentfilter/vendor/symfony/expression-language/Node/NameNode.php index 9e1462f2c..1c9c277b2 100644 --- a/advancedcontentfilter/vendor/symfony/expression-language/Node/NameNode.php +++ b/advancedcontentfilter/vendor/symfony/expression-language/Node/NameNode.php @@ -23,8 +23,8 @@ class NameNode extends Node public function __construct($name) { parent::__construct( - array(), - array('name' => $name) + [], + ['name' => $name] ); } @@ -40,6 +40,6 @@ class NameNode extends Node public function toArray() { - return array($this->attributes['name']); + return [$this->attributes['name']]; } } diff --git a/advancedcontentfilter/vendor/symfony/expression-language/Node/Node.php b/advancedcontentfilter/vendor/symfony/expression-language/Node/Node.php index 1db4e8528..95045902b 100644 --- a/advancedcontentfilter/vendor/symfony/expression-language/Node/Node.php +++ b/advancedcontentfilter/vendor/symfony/expression-language/Node/Node.php @@ -20,14 +20,14 @@ use Symfony\Component\ExpressionLanguage\Compiler; */ class Node { - public $nodes = array(); - public $attributes = array(); + public $nodes = []; + public $attributes = []; /** * @param array $nodes An array of nodes * @param array $attributes An array of attributes */ - public function __construct(array $nodes = array(), array $attributes = array()) + public function __construct(array $nodes = [], array $attributes = []) { $this->nodes = $nodes; $this->attributes = $attributes; @@ -35,14 +35,14 @@ class Node public function __toString() { - $attributes = array(); + $attributes = []; foreach ($this->attributes as $name => $value) { $attributes[] = sprintf('%s: %s', $name, str_replace("\n", '', var_export($value, true))); } - $repr = array(str_replace('Symfony\Component\ExpressionLanguage\Node\\', '', get_class($this)).'('.implode(', ', $attributes)); + $repr = [str_replace('Symfony\Component\ExpressionLanguage\Node\\', '', static::class).'('.implode(', ', $attributes)]; - if (count($this->nodes)) { + if (\count($this->nodes)) { foreach ($this->nodes as $node) { foreach (explode("\n", (string) $node) as $line) { $repr[] = ' '.$line; @@ -66,7 +66,7 @@ class Node public function evaluate($functions, $values) { - $results = array(); + $results = []; foreach ($this->nodes as $node) { $results[] = $node->evaluate($functions, $values); } @@ -76,7 +76,7 @@ class Node public function toArray() { - throw new \BadMethodCallException(sprintf('Dumping a "%s" instance is not supported yet.', get_class($this))); + throw new \BadMethodCallException(sprintf('Dumping a "%s" instance is not supported yet.', static::class)); } public function dump() diff --git a/advancedcontentfilter/vendor/symfony/expression-language/Node/UnaryNode.php b/advancedcontentfilter/vendor/symfony/expression-language/Node/UnaryNode.php index 583103217..497b7fe53 100644 --- a/advancedcontentfilter/vendor/symfony/expression-language/Node/UnaryNode.php +++ b/advancedcontentfilter/vendor/symfony/expression-language/Node/UnaryNode.php @@ -20,18 +20,18 @@ use Symfony\Component\ExpressionLanguage\Compiler; */ class UnaryNode extends Node { - private static $operators = array( + private static $operators = [ '!' => '!', 'not' => '!', '+' => '+', '-' => '-', - ); + ]; public function __construct($operator, Node $node) { parent::__construct( - array('node' => $node), - array('operator' => $operator) + ['node' => $node], + ['operator' => $operator] ); } @@ -61,6 +61,6 @@ class UnaryNode extends Node public function toArray() { - return array('(', $this->attributes['operator'].' ', $this->nodes['node'], ')'); + return ['(', $this->attributes['operator'].' ', $this->nodes['node'], ')']; } } diff --git a/advancedcontentfilter/vendor/symfony/expression-language/Parser.php b/advancedcontentfilter/vendor/symfony/expression-language/Parser.php index 4b1ce8e3a..bfc24395e 100644 --- a/advancedcontentfilter/vendor/symfony/expression-language/Parser.php +++ b/advancedcontentfilter/vendor/symfony/expression-language/Parser.php @@ -36,40 +36,40 @@ class Parser { $this->functions = $functions; - $this->unaryOperators = array( - 'not' => array('precedence' => 50), - '!' => array('precedence' => 50), - '-' => array('precedence' => 500), - '+' => array('precedence' => 500), - ); - $this->binaryOperators = array( - 'or' => array('precedence' => 10, 'associativity' => self::OPERATOR_LEFT), - '||' => array('precedence' => 10, 'associativity' => self::OPERATOR_LEFT), - 'and' => array('precedence' => 15, 'associativity' => self::OPERATOR_LEFT), - '&&' => array('precedence' => 15, 'associativity' => self::OPERATOR_LEFT), - '|' => array('precedence' => 16, 'associativity' => self::OPERATOR_LEFT), - '^' => array('precedence' => 17, 'associativity' => self::OPERATOR_LEFT), - '&' => array('precedence' => 18, 'associativity' => self::OPERATOR_LEFT), - '==' => array('precedence' => 20, 'associativity' => self::OPERATOR_LEFT), - '===' => array('precedence' => 20, 'associativity' => self::OPERATOR_LEFT), - '!=' => array('precedence' => 20, 'associativity' => self::OPERATOR_LEFT), - '!==' => array('precedence' => 20, 'associativity' => self::OPERATOR_LEFT), - '<' => array('precedence' => 20, 'associativity' => self::OPERATOR_LEFT), - '>' => array('precedence' => 20, 'associativity' => self::OPERATOR_LEFT), - '>=' => array('precedence' => 20, 'associativity' => self::OPERATOR_LEFT), - '<=' => array('precedence' => 20, 'associativity' => self::OPERATOR_LEFT), - 'not in' => array('precedence' => 20, 'associativity' => self::OPERATOR_LEFT), - 'in' => array('precedence' => 20, 'associativity' => self::OPERATOR_LEFT), - 'matches' => array('precedence' => 20, 'associativity' => self::OPERATOR_LEFT), - '..' => array('precedence' => 25, 'associativity' => self::OPERATOR_LEFT), - '+' => array('precedence' => 30, 'associativity' => self::OPERATOR_LEFT), - '-' => array('precedence' => 30, 'associativity' => self::OPERATOR_LEFT), - '~' => array('precedence' => 40, 'associativity' => self::OPERATOR_LEFT), - '*' => array('precedence' => 60, 'associativity' => self::OPERATOR_LEFT), - '/' => array('precedence' => 60, 'associativity' => self::OPERATOR_LEFT), - '%' => array('precedence' => 60, 'associativity' => self::OPERATOR_LEFT), - '**' => array('precedence' => 200, 'associativity' => self::OPERATOR_RIGHT), - ); + $this->unaryOperators = [ + 'not' => ['precedence' => 50], + '!' => ['precedence' => 50], + '-' => ['precedence' => 500], + '+' => ['precedence' => 500], + ]; + $this->binaryOperators = [ + 'or' => ['precedence' => 10, 'associativity' => self::OPERATOR_LEFT], + '||' => ['precedence' => 10, 'associativity' => self::OPERATOR_LEFT], + 'and' => ['precedence' => 15, 'associativity' => self::OPERATOR_LEFT], + '&&' => ['precedence' => 15, 'associativity' => self::OPERATOR_LEFT], + '|' => ['precedence' => 16, 'associativity' => self::OPERATOR_LEFT], + '^' => ['precedence' => 17, 'associativity' => self::OPERATOR_LEFT], + '&' => ['precedence' => 18, 'associativity' => self::OPERATOR_LEFT], + '==' => ['precedence' => 20, 'associativity' => self::OPERATOR_LEFT], + '===' => ['precedence' => 20, 'associativity' => self::OPERATOR_LEFT], + '!=' => ['precedence' => 20, 'associativity' => self::OPERATOR_LEFT], + '!==' => ['precedence' => 20, 'associativity' => self::OPERATOR_LEFT], + '<' => ['precedence' => 20, 'associativity' => self::OPERATOR_LEFT], + '>' => ['precedence' => 20, 'associativity' => self::OPERATOR_LEFT], + '>=' => ['precedence' => 20, 'associativity' => self::OPERATOR_LEFT], + '<=' => ['precedence' => 20, 'associativity' => self::OPERATOR_LEFT], + 'not in' => ['precedence' => 20, 'associativity' => self::OPERATOR_LEFT], + 'in' => ['precedence' => 20, 'associativity' => self::OPERATOR_LEFT], + 'matches' => ['precedence' => 20, 'associativity' => self::OPERATOR_LEFT], + '..' => ['precedence' => 25, 'associativity' => self::OPERATOR_LEFT], + '+' => ['precedence' => 30, 'associativity' => self::OPERATOR_LEFT], + '-' => ['precedence' => 30, 'associativity' => self::OPERATOR_LEFT], + '~' => ['precedence' => 40, 'associativity' => self::OPERATOR_LEFT], + '*' => ['precedence' => 60, 'associativity' => self::OPERATOR_LEFT], + '/' => ['precedence' => 60, 'associativity' => self::OPERATOR_LEFT], + '%' => ['precedence' => 60, 'associativity' => self::OPERATOR_LEFT], + '**' => ['precedence' => 200, 'associativity' => self::OPERATOR_RIGHT], + ]; } /** @@ -92,14 +92,14 @@ class Parser * * @throws SyntaxError */ - public function parse(TokenStream $stream, $names = array()) + public function parse(TokenStream $stream, $names = []) { $this->stream = $stream; $this->names = $names; $node = $this->parseExpression(); if (!$stream->isEOF()) { - throw new SyntaxError(sprintf('Unexpected token "%s" of value "%s"', $stream->current->type, $stream->current->value), $stream->current->cursor, $stream->getExpression()); + throw new SyntaxError(sprintf('Unexpected token "%s" of value "%s".', $stream->current->type, $stream->current->value), $stream->current->cursor, $stream->getExpression()); } return $node; @@ -195,18 +195,18 @@ class Parser default: if ('(' === $this->stream->current->value) { if (false === isset($this->functions[$token->value])) { - throw new SyntaxError(sprintf('The function "%s" does not exist', $token->value), $token->cursor, $this->stream->getExpression(), $token->value, array_keys($this->functions)); + throw new SyntaxError(sprintf('The function "%s" does not exist.', $token->value), $token->cursor, $this->stream->getExpression(), $token->value, array_keys($this->functions)); } $node = new Node\FunctionNode($token->value, $this->parseArguments()); } else { - if (!in_array($token->value, $this->names, true)) { - throw new SyntaxError(sprintf('Variable "%s" is not valid', $token->value), $token->cursor, $this->stream->getExpression(), $token->value, $this->names); + if (!\in_array($token->value, $this->names, true)) { + throw new SyntaxError(sprintf('Variable "%s" is not valid.', $token->value), $token->cursor, $this->stream->getExpression(), $token->value, $this->names); } // is the name used in the compiled code different // from the name used in the expression? - if (is_int($name = array_search($token->value, $this->names))) { + if (\is_int($name = array_search($token->value, $this->names))) { $name = $token->value; } @@ -227,7 +227,7 @@ class Parser } elseif ($token->test(Token::PUNCTUATION_TYPE, '{')) { $node = $this->parseHashExpression(); } else { - throw new SyntaxError(sprintf('Unexpected token "%s" of value "%s"', $token->type, $token->value), $token->cursor, $this->stream->getExpression()); + throw new SyntaxError(sprintf('Unexpected token "%s" of value "%s".', $token->type, $token->value), $token->cursor, $this->stream->getExpression()); } } @@ -289,7 +289,7 @@ class Parser } else { $current = $this->stream->current; - throw new SyntaxError(sprintf('A hash key must be a quoted string, a number, a name, or an expression enclosed in parentheses (unexpected token "%s" of value "%s"', $current->type, $current->value), $current->cursor, $this->stream->getExpression()); + throw new SyntaxError(sprintf('A hash key must be a quoted string, a number, a name, or an expression enclosed in parentheses (unexpected token "%s" of value "%s".', $current->type, $current->value), $current->cursor, $this->stream->getExpression()); } $this->stream->expect(Token::PUNCTUATION_TYPE, ':', 'A hash key must be followed by a colon (:)'); @@ -327,7 +327,7 @@ class Parser // As a result, if $token is NOT an operator OR $token->value is NOT a valid property or method name, an exception shall be thrown. (Token::OPERATOR_TYPE !== $token->type || !preg_match('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/A', $token->value)) ) { - throw new SyntaxError('Expected name', $token->cursor, $this->stream->getExpression()); + throw new SyntaxError('Expected name.', $token->cursor, $this->stream->getExpression()); } $arg = new Node\ConstantNode($token->value, true); @@ -364,7 +364,7 @@ class Parser */ public function parseArguments() { - $args = array(); + $args = []; $this->stream->expect(Token::PUNCTUATION_TYPE, '(', 'A list of arguments must begin with an opening parenthesis'); while (!$this->stream->current->test(Token::PUNCTUATION_TYPE, ')')) { if (!empty($args)) { diff --git a/advancedcontentfilter/vendor/symfony/expression-language/ParserCache/ArrayParserCache.php b/advancedcontentfilter/vendor/symfony/expression-language/ParserCache/ArrayParserCache.php index 124962505..f009df73b 100644 --- a/advancedcontentfilter/vendor/symfony/expression-language/ParserCache/ArrayParserCache.php +++ b/advancedcontentfilter/vendor/symfony/expression-language/ParserCache/ArrayParserCache.php @@ -11,7 +11,7 @@ namespace Symfony\Component\ExpressionLanguage\ParserCache; -@trigger_error('The '.__NAMESPACE__.'\ArrayParserCache class is deprecated since Symfony 3.2 and will be removed in 4.0. Use the Symfony\Component\Cache\Adapter\ArrayAdapter class instead.', E_USER_DEPRECATED); +@trigger_error('The '.__NAMESPACE__.'\ArrayParserCache class is deprecated since Symfony 3.2 and will be removed in 4.0. Use the Symfony\Component\Cache\Adapter\ArrayAdapter class instead.', \E_USER_DEPRECATED); use Symfony\Component\ExpressionLanguage\ParsedExpression; @@ -22,7 +22,7 @@ use Symfony\Component\ExpressionLanguage\ParsedExpression; */ class ArrayParserCache implements ParserCacheInterface { - private $cache = array(); + private $cache = []; /** * {@inheritdoc} diff --git a/advancedcontentfilter/vendor/symfony/expression-language/ParserCache/ParserCacheAdapter.php b/advancedcontentfilter/vendor/symfony/expression-language/ParserCache/ParserCacheAdapter.php index a3e227d0a..b9b448dd8 100644 --- a/advancedcontentfilter/vendor/symfony/expression-language/ParserCache/ParserCacheAdapter.php +++ b/advancedcontentfilter/vendor/symfony/expression-language/ParserCache/ParserCacheAdapter.php @@ -30,7 +30,7 @@ class ParserCacheAdapter implements CacheItemPoolInterface $this->pool = $pool; $this->createCacheItem = \Closure::bind( - function ($key, $value, $isHit) { + static function ($key, $value, $isHit) { $item = new CacheItem(); $item->key = $key; $item->value = $value; @@ -65,9 +65,9 @@ class ParserCacheAdapter implements CacheItemPoolInterface /** * {@inheritdoc} */ - public function getItems(array $keys = array()) + public function getItems(array $keys = []) { - throw new \BadMethodCallException('Not implemented'); + throw new \BadMethodCallException('Not implemented.'); } /** @@ -75,7 +75,7 @@ class ParserCacheAdapter implements CacheItemPoolInterface */ public function hasItem($key) { - throw new \BadMethodCallException('Not implemented'); + throw new \BadMethodCallException('Not implemented.'); } /** @@ -83,7 +83,7 @@ class ParserCacheAdapter implements CacheItemPoolInterface */ public function clear() { - throw new \BadMethodCallException('Not implemented'); + throw new \BadMethodCallException('Not implemented.'); } /** @@ -91,7 +91,7 @@ class ParserCacheAdapter implements CacheItemPoolInterface */ public function deleteItem($key) { - throw new \BadMethodCallException('Not implemented'); + throw new \BadMethodCallException('Not implemented.'); } /** @@ -99,7 +99,7 @@ class ParserCacheAdapter implements CacheItemPoolInterface */ public function deleteItems(array $keys) { - throw new \BadMethodCallException('Not implemented'); + throw new \BadMethodCallException('Not implemented.'); } /** @@ -107,7 +107,7 @@ class ParserCacheAdapter implements CacheItemPoolInterface */ public function saveDeferred(CacheItemInterface $item) { - throw new \BadMethodCallException('Not implemented'); + throw new \BadMethodCallException('Not implemented.'); } /** @@ -115,6 +115,6 @@ class ParserCacheAdapter implements CacheItemPoolInterface */ public function commit() { - throw new \BadMethodCallException('Not implemented'); + throw new \BadMethodCallException('Not implemented.'); } } diff --git a/advancedcontentfilter/vendor/symfony/expression-language/ParserCache/ParserCacheInterface.php b/advancedcontentfilter/vendor/symfony/expression-language/ParserCache/ParserCacheInterface.php index ed66b21bf..98a80edd6 100644 --- a/advancedcontentfilter/vendor/symfony/expression-language/ParserCache/ParserCacheInterface.php +++ b/advancedcontentfilter/vendor/symfony/expression-language/ParserCache/ParserCacheInterface.php @@ -11,7 +11,7 @@ namespace Symfony\Component\ExpressionLanguage\ParserCache; -@trigger_error('The '.__NAMESPACE__.'\ParserCacheInterface interface is deprecated since Symfony 3.2 and will be removed in 4.0. Use Psr\Cache\CacheItemPoolInterface instead.', E_USER_DEPRECATED); +@trigger_error('The '.__NAMESPACE__.'\ParserCacheInterface interface is deprecated since Symfony 3.2 and will be removed in 4.0. Use Psr\Cache\CacheItemPoolInterface instead.', \E_USER_DEPRECATED); use Symfony\Component\ExpressionLanguage\ParsedExpression; diff --git a/advancedcontentfilter/vendor/symfony/expression-language/Resources/bin/generate_operator_regex.php b/advancedcontentfilter/vendor/symfony/expression-language/Resources/bin/generate_operator_regex.php index 74a100890..c86e96252 100644 --- a/advancedcontentfilter/vendor/symfony/expression-language/Resources/bin/generate_operator_regex.php +++ b/advancedcontentfilter/vendor/symfony/expression-language/Resources/bin/generate_operator_regex.php @@ -9,15 +9,19 @@ * file that was distributed with this source code. */ -$operators = array('not', '!', 'or', '||', '&&', 'and', '|', '^', '&', '==', '===', '!=', '!==', '<', '>', '>=', '<=', 'not in', 'in', '..', '+', '-', '~', '*', '/', '%', 'matches', '**'); +$operators = ['not', '!', 'or', '||', '&&', 'and', '|', '^', '&', '==', '===', '!=', '!==', '<', '>', '>=', '<=', 'not in', 'in', '..', '+', '-', '~', '*', '/', '%', 'matches', '**']; $operators = array_combine($operators, array_map('strlen', $operators)); arsort($operators); -$regex = array(); +$regex = []; foreach ($operators as $operator => $length) { - // an operator that ends with a character must be followed by - // a whitespace or a parenthesis - $regex[] = preg_quote($operator, '/').(ctype_alpha($operator[$length - 1]) ? '(?=[\s(])' : ''); + // Collisions of character operators: + // - an operator that begins with a character must have a space or a parenthesis before or starting at the beginning of a string + // - an operator that ends with a character must be followed by a whitespace or a parenthesis + $regex[] = + (ctype_alpha($operator[0]) ? '(?<=^|[\s(])' : '') + .preg_quote($operator, '/') + .(ctype_alpha($operator[$length - 1]) ? '(?=[\s(])' : ''); } echo '/'.implode('|', $regex).'/A'; diff --git a/advancedcontentfilter/vendor/symfony/expression-language/SyntaxError.php b/advancedcontentfilter/vendor/symfony/expression-language/SyntaxError.php index 12348e683..a942b8cb7 100644 --- a/advancedcontentfilter/vendor/symfony/expression-language/SyntaxError.php +++ b/advancedcontentfilter/vendor/symfony/expression-language/SyntaxError.php @@ -15,14 +15,14 @@ class SyntaxError extends \LogicException { public function __construct($message, $cursor = 0, $expression = '', $subject = null, array $proposals = null) { - $message = sprintf('%s around position %d', $message, $cursor); + $message = sprintf('%s around position %d', rtrim($message, '.'), $cursor); if ($expression) { $message = sprintf('%s for expression `%s`', $message, $expression); } $message .= '.'; if (null !== $subject && null !== $proposals) { - $minScore = INF; + $minScore = \INF; foreach ($proposals as $proposal) { $distance = levenshtein($subject, $proposal); if ($distance < $minScore) { diff --git a/advancedcontentfilter/vendor/symfony/expression-language/Tests/ExpressionFunctionTest.php b/advancedcontentfilter/vendor/symfony/expression-language/Tests/ExpressionFunctionTest.php index f2710fb1e..d7e23cb41 100644 --- a/advancedcontentfilter/vendor/symfony/expression-language/Tests/ExpressionFunctionTest.php +++ b/advancedcontentfilter/vendor/symfony/expression-language/Tests/ExpressionFunctionTest.php @@ -21,21 +21,17 @@ use Symfony\Component\ExpressionLanguage\ExpressionFunction; */ class ExpressionFunctionTest extends TestCase { - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage PHP function "fn_does_not_exist" does not exist. - */ public function testFunctionDoesNotExist() { + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessage('PHP function "fn_does_not_exist" does not exist.'); ExpressionFunction::fromPhp('fn_does_not_exist'); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage An expression function name must be defined when PHP function "Symfony\Component\ExpressionLanguage\Tests\fn_namespaced" is namespaced. - */ public function testFunctionNamespaced() { + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessage('An expression function name must be defined when PHP function "Symfony\Component\ExpressionLanguage\Tests\fn_namespaced" is namespaced.'); ExpressionFunction::fromPhp('Symfony\Component\ExpressionLanguage\Tests\fn_namespaced'); } } diff --git a/advancedcontentfilter/vendor/symfony/expression-language/Tests/ExpressionLanguageTest.php b/advancedcontentfilter/vendor/symfony/expression-language/Tests/ExpressionLanguageTest.php index 70328c8e5..97e915ac2 100644 --- a/advancedcontentfilter/vendor/symfony/expression-language/Tests/ExpressionLanguageTest.php +++ b/advancedcontentfilter/vendor/symfony/expression-language/Tests/ExpressionLanguageTest.php @@ -11,8 +11,8 @@ namespace Symfony\Component\ExpressionLanguage\Tests; -use Symfony\Component\ExpressionLanguage\ExpressionFunction; use PHPUnit\Framework\TestCase; +use Symfony\Component\ExpressionLanguage\ExpressionFunction; use Symfony\Component\ExpressionLanguage\ExpressionLanguage; use Symfony\Component\ExpressionLanguage\ParsedExpression; use Symfony\Component\ExpressionLanguage\Tests\Fixtures\TestProvider; @@ -36,18 +36,18 @@ class ExpressionLanguageTest extends TestCase $cacheItemMock ->expects($this->exactly(2)) ->method('get') - ->will($this->returnCallback(function () use (&$savedParsedExpression) { + ->willReturnCallback(function () use (&$savedParsedExpression) { return $savedParsedExpression; - })) + }) ; $cacheItemMock ->expects($this->exactly(1)) ->method('set') ->with($this->isInstanceOf(ParsedExpression::class)) - ->will($this->returnCallback(function ($parsedExpression) use (&$savedParsedExpression) { + ->willReturnCallback(function ($parsedExpression) use (&$savedParsedExpression) { $savedParsedExpression = $parsedExpression; - })) + }) ; $cacheMock @@ -56,10 +56,10 @@ class ExpressionLanguageTest extends TestCase ->with($cacheItemMock) ; - $parsedExpression = $expressionLanguage->parse('1 + 1', array()); + $parsedExpression = $expressionLanguage->parse('1 + 1', []); $this->assertSame($savedParsedExpression, $parsedExpression); - $parsedExpression = $expressionLanguage->parse('1 + 1', array()); + $parsedExpression = $expressionLanguage->parse('1 + 1', []); $this->assertSame($savedParsedExpression, $parsedExpression); } @@ -70,7 +70,6 @@ class ExpressionLanguageTest extends TestCase { $cacheMock = $this->getMockBuilder('Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface')->getMock(); - $cacheItemMock = $this->getMockBuilder('Psr\Cache\CacheItemInterface')->getMock(); $savedParsedExpression = null; $expressionLanguage = new ExpressionLanguage($cacheMock); @@ -85,29 +84,27 @@ class ExpressionLanguageTest extends TestCase ->expects($this->exactly(1)) ->method('save') ->with('1%20%2B%201%2F%2F', $this->isInstanceOf(ParsedExpression::class)) - ->will($this->returnCallback(function ($key, $expression) use (&$savedParsedExpression) { + ->willReturnCallback(function ($key, $expression) use (&$savedParsedExpression) { $savedParsedExpression = $expression; - })) + }) ; - $parsedExpression = $expressionLanguage->parse('1 + 1', array()); + $parsedExpression = $expressionLanguage->parse('1 + 1', []); $this->assertSame($savedParsedExpression, $parsedExpression); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Cache argument has to implement Psr\Cache\CacheItemPoolInterface. - */ public function testWrongCacheImplementation() { + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessage('Cache argument has to implement "Psr\Cache\CacheItemPoolInterface".'); $cacheMock = $this->getMockBuilder('Psr\Cache\CacheItemSpoolInterface')->getMock(); - $expressionLanguage = new ExpressionLanguage($cacheMock); + new ExpressionLanguage($cacheMock); } public function testConstantFunction() { $expressionLanguage = new ExpressionLanguage(); - $this->assertEquals(PHP_VERSION, $expressionLanguage->evaluate('constant("PHP_VERSION")')); + $this->assertEquals(\PHP_VERSION, $expressionLanguage->evaluate('constant("PHP_VERSION")')); $expressionLanguage = new ExpressionLanguage(); $this->assertEquals('\constant("PHP_VERSION")', $expressionLanguage->compile('constant("PHP_VERSION")')); @@ -115,7 +112,7 @@ class ExpressionLanguageTest extends TestCase public function testProviders() { - $expressionLanguage = new ExpressionLanguage(null, array(new TestProvider())); + $expressionLanguage = new ExpressionLanguage(null, [new TestProvider()]); $this->assertEquals('foo', $expressionLanguage->evaluate('identity("foo")')); $this->assertEquals('"foo"', $expressionLanguage->compile('identity("foo")')); $this->assertEquals('FOO', $expressionLanguage->evaluate('strtoupper("foo")')); @@ -146,45 +143,43 @@ class ExpressionLanguageTest extends TestCase $this->assertSame($expected, $result); } - /** - * @expectedException \Symfony\Component\ExpressionLanguage\SyntaxError - * @expectedExceptionMessage Unexpected end of expression around position 6 for expression `node.`. - */ public function testParseThrowsInsteadOfNotice() { + $this->expectException('Symfony\Component\ExpressionLanguage\SyntaxError'); + $this->expectExceptionMessage('Unexpected end of expression around position 6 for expression `node.`.'); $expressionLanguage = new ExpressionLanguage(); - $expressionLanguage->parse('node.', array('node')); + $expressionLanguage->parse('node.', ['node']); } public function shortCircuitProviderEvaluate() { - $object = $this->getMockBuilder('stdClass')->setMethods(array('foo'))->getMock(); + $object = $this->getMockBuilder('stdClass')->setMethods(['foo'])->getMock(); $object->expects($this->never())->method('foo'); - return array( - array('false and object.foo()', array('object' => $object), false), - array('false && object.foo()', array('object' => $object), false), - array('true || object.foo()', array('object' => $object), true), - array('true or object.foo()', array('object' => $object), true), - ); + return [ + ['false and object.foo()', ['object' => $object], false], + ['false && object.foo()', ['object' => $object], false], + ['true || object.foo()', ['object' => $object], true], + ['true or object.foo()', ['object' => $object], true], + ]; } public function shortCircuitProviderCompile() { - return array( - array('false and foo', array('foo' => 'foo'), false), - array('false && foo', array('foo' => 'foo'), false), - array('true || foo', array('foo' => 'foo'), true), - array('true or foo', array('foo' => 'foo'), true), - ); + return [ + ['false and foo', ['foo' => 'foo'], false], + ['false && foo', ['foo' => 'foo'], false], + ['true || foo', ['foo' => 'foo'], true], + ['true or foo', ['foo' => 'foo'], true], + ]; } public function testCachingForOverriddenVariableNames() { $expressionLanguage = new ExpressionLanguage(); $expression = 'a + b'; - $expressionLanguage->evaluate($expression, array('a' => 1, 'b' => 1)); - $result = $expressionLanguage->compile($expression, array('a', 'B' => 'b')); + $expressionLanguage->evaluate($expression, ['a' => 1, 'b' => 1]); + $result = $expressionLanguage->compile($expression, ['a', 'B' => 'b']); $this->assertSame('($a + $B)', $result); } @@ -192,7 +187,7 @@ class ExpressionLanguageTest extends TestCase { $expressionLanguage = new ExpressionLanguage(); $expression = '123 === a'; - $result = $expressionLanguage->compile($expression, array('a')); + $result = $expressionLanguage->compile($expression, ['a']); $this->assertSame('(123 === $a)', $result); } @@ -201,7 +196,7 @@ class ExpressionLanguageTest extends TestCase $cacheMock = $this->getMockBuilder('Psr\Cache\CacheItemPoolInterface')->getMock(); $cacheItemMock = $this->getMockBuilder('Psr\Cache\CacheItemInterface')->getMock(); $expressionLanguage = new ExpressionLanguage($cacheMock); - $savedParsedExpressions = array(); + $savedParsedExpression = null; $cacheMock ->expects($this->exactly(2)) @@ -213,18 +208,18 @@ class ExpressionLanguageTest extends TestCase $cacheItemMock ->expects($this->exactly(2)) ->method('get') - ->will($this->returnCallback(function () use (&$savedParsedExpression) { + ->willReturnCallback(function () use (&$savedParsedExpression) { return $savedParsedExpression; - })) + }) ; $cacheItemMock ->expects($this->exactly(1)) ->method('set') ->with($this->isInstanceOf(ParsedExpression::class)) - ->will($this->returnCallback(function ($parsedExpression) use (&$savedParsedExpression) { + ->willReturnCallback(function ($parsedExpression) use (&$savedParsedExpression) { $savedParsedExpression = $parsedExpression; - })) + }) ; $cacheMock @@ -234,48 +229,57 @@ class ExpressionLanguageTest extends TestCase ; $expression = 'a + b'; - $expressionLanguage->compile($expression, array('a', 'B' => 'b')); - $expressionLanguage->compile($expression, array('B' => 'b', 'a')); + $expressionLanguage->compile($expression, ['a', 'B' => 'b']); + $expressionLanguage->compile($expression, ['B' => 'b', 'a']); + } + + public function testOperatorCollisions() + { + $expressionLanguage = new ExpressionLanguage(); + $expression = 'foo.not in [bar]'; + $compiled = $expressionLanguage->compile($expression, ['foo', 'bar']); + $this->assertSame('in_array($foo->not, [0 => $bar])', $compiled); + + $result = $expressionLanguage->evaluate($expression, ['foo' => (object) ['not' => 'test'], 'bar' => 'test']); + $this->assertTrue($result); } /** * @dataProvider getRegisterCallbacks - * @expectedException \LogicException */ public function testRegisterAfterParse($registerCallback) { + $this->expectException('LogicException'); $el = new ExpressionLanguage(); - $el->parse('1 + 1', array()); + $el->parse('1 + 1', []); $registerCallback($el); } /** * @dataProvider getRegisterCallbacks - * @expectedException \LogicException */ public function testRegisterAfterEval($registerCallback) { + $this->expectException('LogicException'); $el = new ExpressionLanguage(); $el->evaluate('1 + 1'); $registerCallback($el); } - /** - * @expectedException \RuntimeException - * @expectedExceptionMessageRegExp /Unable to call method "\w+" of object "\w+"./ - */ public function testCallBadCallable() { + $this->expectException('RuntimeException'); + $this->expectExceptionMessageMatches('/Unable to call method "\w+" of object "\w+"./'); $el = new ExpressionLanguage(); - $el->evaluate('foo.myfunction()', array('foo' => new \stdClass())); + $el->evaluate('foo.myfunction()', ['foo' => new \stdClass()]); } /** * @dataProvider getRegisterCallbacks - * @expectedException \LogicException */ public function testRegisterAfterCompile($registerCallback) { + $this->expectException('LogicException'); $el = new ExpressionLanguage(); $el->compile('1 + 1'); $registerCallback($el); @@ -283,22 +287,22 @@ class ExpressionLanguageTest extends TestCase public function getRegisterCallbacks() { - return array( - array( + return [ + [ function (ExpressionLanguage $el) { $el->register('fn', function () {}, function () {}); }, - ), - array( + ], + [ function (ExpressionLanguage $el) { $el->addFunction(new ExpressionFunction('fn', function () {}, function () {})); }, - ), - array( + ], + [ function (ExpressionLanguage $el) { $el->registerProvider(new TestProvider()); }, - ), - ); + ], + ]; } } diff --git a/advancedcontentfilter/vendor/symfony/expression-language/Tests/Fixtures/TestProvider.php b/advancedcontentfilter/vendor/symfony/expression-language/Tests/Fixtures/TestProvider.php index 20c5182bb..8405d4f97 100644 --- a/advancedcontentfilter/vendor/symfony/expression-language/Tests/Fixtures/TestProvider.php +++ b/advancedcontentfilter/vendor/symfony/expression-language/Tests/Fixtures/TestProvider.php @@ -19,7 +19,7 @@ class TestProvider implements ExpressionFunctionProviderInterface { public function getFunctions() { - return array( + return [ new ExpressionFunction('identity', function ($input) { return $input; }, function (array $values, $input) { @@ -31,7 +31,7 @@ class TestProvider implements ExpressionFunctionProviderInterface ExpressionFunction::fromPhp('\strtolower'), ExpressionFunction::fromPhp('Symfony\Component\ExpressionLanguage\Tests\Fixtures\fn_namespaced', 'fn_namespaced'), - ); + ]; } } diff --git a/advancedcontentfilter/vendor/symfony/expression-language/Tests/LexerTest.php b/advancedcontentfilter/vendor/symfony/expression-language/Tests/LexerTest.php index 87c16f707..6c3d1a7d2 100644 --- a/advancedcontentfilter/vendor/symfony/expression-language/Tests/LexerTest.php +++ b/advancedcontentfilter/vendor/symfony/expression-language/Tests/LexerTest.php @@ -33,59 +33,55 @@ class LexerTest extends TestCase */ public function testTokenize($tokens, $expression) { - $tokens[] = new Token('end of expression', null, strlen($expression) + 1); + $tokens[] = new Token('end of expression', null, \strlen($expression) + 1); $this->assertEquals(new TokenStream($tokens, $expression), $this->lexer->tokenize($expression)); } - /** - * @expectedException \Symfony\Component\ExpressionLanguage\SyntaxError - * @expectedExceptionMessage Unexpected character "'" around position 33 for expression `service(faulty.expression.example').dummyMethod()`. - */ public function testTokenizeThrowsErrorWithMessage() { + $this->expectException('Symfony\Component\ExpressionLanguage\SyntaxError'); + $this->expectExceptionMessage('Unexpected character "\'" around position 33 for expression `service(faulty.expression.example\').dummyMethod()`.'); $expression = "service(faulty.expression.example').dummyMethod()"; $this->lexer->tokenize($expression); } - /** - * @expectedException \Symfony\Component\ExpressionLanguage\SyntaxError - * @expectedExceptionMessage Unclosed "(" around position 7 for expression `service(unclosed.expression.dummyMethod()`. - */ public function testTokenizeThrowsErrorOnUnclosedBrace() { + $this->expectException('Symfony\Component\ExpressionLanguage\SyntaxError'); + $this->expectExceptionMessage('Unclosed "(" around position 7 for expression `service(unclosed.expression.dummyMethod()`.'); $expression = 'service(unclosed.expression.dummyMethod()'; $this->lexer->tokenize($expression); } public function getTokenizeData() { - return array( - array( - array(new Token('name', 'a', 3)), + return [ + [ + [new Token('name', 'a', 3)], ' a ', - ), - array( - array(new Token('name', 'a', 1)), + ], + [ + [new Token('name', 'a', 1)], 'a', - ), - array( - array(new Token('string', 'foo', 1)), + ], + [ + [new Token('string', 'foo', 1)], '"foo"', - ), - array( - array(new Token('number', '3', 1)), + ], + [ + [new Token('number', '3', 1)], '3', - ), - array( - array(new Token('operator', '+', 1)), + ], + [ + [new Token('operator', '+', 1)], '+', - ), - array( - array(new Token('punctuation', '.', 1)), + ], + [ + [new Token('punctuation', '.', 1)], '.', - ), - array( - array( + ], + [ + [ new Token('punctuation', '(', 1), new Token('number', '3', 2), new Token('operator', '+', 4), @@ -101,21 +97,33 @@ class LexerTest extends TestCase new Token('punctuation', '[', 25), new Token('number', '4', 26), new Token('punctuation', ']', 27), - ), + ], '(3 + 5) ~ foo("bar").baz[4]', - ), - array( - array(new Token('operator', '..', 1)), + ], + [ + [new Token('operator', '..', 1)], '..', - ), - array( - array(new Token('string', '#foo', 1)), + ], + [ + [new Token('string', '#foo', 1)], "'#foo'", - ), - array( - array(new Token('string', '#foo', 1)), + ], + [ + [new Token('string', '#foo', 1)], '"#foo"', - ), - ); + ], + [ + [ + new Token('name', 'foo', 1), + new Token('punctuation', '.', 4), + new Token('name', 'not', 5), + new Token('operator', 'in', 9), + new Token('punctuation', '[', 12), + new Token('name', 'bar', 13), + new Token('punctuation', ']', 16), + ], + 'foo.not in [bar]', + ], + ]; } } diff --git a/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/AbstractNodeTest.php b/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/AbstractNodeTest.php index a6f80c2f6..297503746 100644 --- a/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/AbstractNodeTest.php +++ b/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/AbstractNodeTest.php @@ -19,7 +19,7 @@ abstract class AbstractNodeTest extends TestCase /** * @dataProvider getEvaluateData */ - public function testEvaluate($expected, $node, $variables = array(), $functions = array()) + public function testEvaluate($expected, $node, $variables = [], $functions = []) { $this->assertSame($expected, $node->evaluate($functions, $variables)); } @@ -29,7 +29,7 @@ abstract class AbstractNodeTest extends TestCase /** * @dataProvider getCompileData */ - public function testCompile($expected, $node, $functions = array()) + public function testCompile($expected, $node, $functions = []) { $compiler = new Compiler($functions); $node->compile($compiler); diff --git a/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/ArgumentsNodeTest.php b/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/ArgumentsNodeTest.php index 60a6d1ca2..9d88b4ae7 100644 --- a/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/ArgumentsNodeTest.php +++ b/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/ArgumentsNodeTest.php @@ -17,16 +17,16 @@ class ArgumentsNodeTest extends ArrayNodeTest { public function getCompileData() { - return array( - array('"a", "b"', $this->getArrayNode()), - ); + return [ + ['"a", "b"', $this->getArrayNode()], + ]; } public function getDumpData() { - return array( - array('"a", "b"', $this->getArrayNode()), - ); + return [ + ['"a", "b"', $this->getArrayNode()], + ]; } protected function createArrayNode() diff --git a/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/ArrayNodeTest.php b/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/ArrayNodeTest.php index 11a35d461..3d03d837e 100644 --- a/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/ArrayNodeTest.php +++ b/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/ArrayNodeTest.php @@ -30,31 +30,31 @@ class ArrayNodeTest extends AbstractNodeTest public function getEvaluateData() { - return array( - array(array('b' => 'a', 'b'), $this->getArrayNode()), - ); + return [ + [['b' => 'a', 'b'], $this->getArrayNode()], + ]; } public function getCompileData() { - return array( - array('array("b" => "a", 0 => "b")', $this->getArrayNode()), - ); + return [ + ['["b" => "a", 0 => "b"]', $this->getArrayNode()], + ]; } public function getDumpData() { - yield array('{"b": "a", 0: "b"}', $this->getArrayNode()); + yield ['{"b": "a", 0: "b"}', $this->getArrayNode()]; $array = $this->createArrayNode(); $array->addElement(new ConstantNode('c'), new ConstantNode('a"b')); $array->addElement(new ConstantNode('d'), new ConstantNode('a\b')); - yield array('{"a\\"b": "c", "a\\\\b": "d"}', $array); + yield ['{"a\\"b": "c", "a\\\\b": "d"}', $array]; $array = $this->createArrayNode(); $array->addElement(new ConstantNode('c')); $array->addElement(new ConstantNode('d')); - yield array('["c", "d"]', $array); + yield ['["c", "d"]', $array]; } protected function getArrayNode() diff --git a/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/BinaryNodeTest.php b/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/BinaryNodeTest.php index 258d276b5..b45a1e57b 100644 --- a/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/BinaryNodeTest.php +++ b/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/BinaryNodeTest.php @@ -11,8 +11,8 @@ namespace Symfony\Component\ExpressionLanguage\Tests\Node; -use Symfony\Component\ExpressionLanguage\Node\BinaryNode; use Symfony\Component\ExpressionLanguage\Node\ArrayNode; +use Symfony\Component\ExpressionLanguage\Node\BinaryNode; use Symfony\Component\ExpressionLanguage\Node\ConstantNode; class BinaryNodeTest extends AbstractNodeTest @@ -23,47 +23,47 @@ class BinaryNodeTest extends AbstractNodeTest $array->addElement(new ConstantNode('a')); $array->addElement(new ConstantNode('b')); - return array( - array(true, new BinaryNode('or', new ConstantNode(true), new ConstantNode(false))), - array(true, new BinaryNode('||', new ConstantNode(true), new ConstantNode(false))), - array(false, new BinaryNode('and', new ConstantNode(true), new ConstantNode(false))), - array(false, new BinaryNode('&&', new ConstantNode(true), new ConstantNode(false))), + return [ + [true, new BinaryNode('or', new ConstantNode(true), new ConstantNode(false))], + [true, new BinaryNode('||', new ConstantNode(true), new ConstantNode(false))], + [false, new BinaryNode('and', new ConstantNode(true), new ConstantNode(false))], + [false, new BinaryNode('&&', new ConstantNode(true), new ConstantNode(false))], - array(0, new BinaryNode('&', new ConstantNode(2), new ConstantNode(4))), - array(6, new BinaryNode('|', new ConstantNode(2), new ConstantNode(4))), - array(6, new BinaryNode('^', new ConstantNode(2), new ConstantNode(4))), + [0, new BinaryNode('&', new ConstantNode(2), new ConstantNode(4))], + [6, new BinaryNode('|', new ConstantNode(2), new ConstantNode(4))], + [6, new BinaryNode('^', new ConstantNode(2), new ConstantNode(4))], - array(true, new BinaryNode('<', new ConstantNode(1), new ConstantNode(2))), - array(true, new BinaryNode('<=', new ConstantNode(1), new ConstantNode(2))), - array(true, new BinaryNode('<=', new ConstantNode(1), new ConstantNode(1))), + [true, new BinaryNode('<', new ConstantNode(1), new ConstantNode(2))], + [true, new BinaryNode('<=', new ConstantNode(1), new ConstantNode(2))], + [true, new BinaryNode('<=', new ConstantNode(1), new ConstantNode(1))], - array(false, new BinaryNode('>', new ConstantNode(1), new ConstantNode(2))), - array(false, new BinaryNode('>=', new ConstantNode(1), new ConstantNode(2))), - array(true, new BinaryNode('>=', new ConstantNode(1), new ConstantNode(1))), + [false, new BinaryNode('>', new ConstantNode(1), new ConstantNode(2))], + [false, new BinaryNode('>=', new ConstantNode(1), new ConstantNode(2))], + [true, new BinaryNode('>=', new ConstantNode(1), new ConstantNode(1))], - array(true, new BinaryNode('===', new ConstantNode(true), new ConstantNode(true))), - array(false, new BinaryNode('!==', new ConstantNode(true), new ConstantNode(true))), + [true, new BinaryNode('===', new ConstantNode(true), new ConstantNode(true))], + [false, new BinaryNode('!==', new ConstantNode(true), new ConstantNode(true))], - array(false, new BinaryNode('==', new ConstantNode(2), new ConstantNode(1))), - array(true, new BinaryNode('!=', new ConstantNode(2), new ConstantNode(1))), + [false, new BinaryNode('==', new ConstantNode(2), new ConstantNode(1))], + [true, new BinaryNode('!=', new ConstantNode(2), new ConstantNode(1))], - array(-1, new BinaryNode('-', new ConstantNode(1), new ConstantNode(2))), - array(3, new BinaryNode('+', new ConstantNode(1), new ConstantNode(2))), - array(4, new BinaryNode('*', new ConstantNode(2), new ConstantNode(2))), - array(1, new BinaryNode('/', new ConstantNode(2), new ConstantNode(2))), - array(1, new BinaryNode('%', new ConstantNode(5), new ConstantNode(2))), - array(25, new BinaryNode('**', new ConstantNode(5), new ConstantNode(2))), - array('ab', new BinaryNode('~', new ConstantNode('a'), new ConstantNode('b'))), + [-1, new BinaryNode('-', new ConstantNode(1), new ConstantNode(2))], + [3, new BinaryNode('+', new ConstantNode(1), new ConstantNode(2))], + [4, new BinaryNode('*', new ConstantNode(2), new ConstantNode(2))], + [1, new BinaryNode('/', new ConstantNode(2), new ConstantNode(2))], + [1, new BinaryNode('%', new ConstantNode(5), new ConstantNode(2))], + [25, new BinaryNode('**', new ConstantNode(5), new ConstantNode(2))], + ['ab', new BinaryNode('~', new ConstantNode('a'), new ConstantNode('b'))], - array(true, new BinaryNode('in', new ConstantNode('a'), $array)), - array(false, new BinaryNode('in', new ConstantNode('c'), $array)), - array(true, new BinaryNode('not in', new ConstantNode('c'), $array)), - array(false, new BinaryNode('not in', new ConstantNode('a'), $array)), + [true, new BinaryNode('in', new ConstantNode('a'), $array)], + [false, new BinaryNode('in', new ConstantNode('c'), $array)], + [true, new BinaryNode('not in', new ConstantNode('c'), $array)], + [false, new BinaryNode('not in', new ConstantNode('a'), $array)], - array(array(1, 2, 3), new BinaryNode('..', new ConstantNode(1), new ConstantNode(3))), + [[1, 2, 3], new BinaryNode('..', new ConstantNode(1), new ConstantNode(3))], - array(1, new BinaryNode('matches', new ConstantNode('abc'), new ConstantNode('/^[a-z]+$/'))), - ); + [1, new BinaryNode('matches', new ConstantNode('abc'), new ConstantNode('/^[a-z]+$/'))], + ]; } public function getCompileData() @@ -72,47 +72,47 @@ class BinaryNodeTest extends AbstractNodeTest $array->addElement(new ConstantNode('a')); $array->addElement(new ConstantNode('b')); - return array( - array('(true || false)', new BinaryNode('or', new ConstantNode(true), new ConstantNode(false))), - array('(true || false)', new BinaryNode('||', new ConstantNode(true), new ConstantNode(false))), - array('(true && false)', new BinaryNode('and', new ConstantNode(true), new ConstantNode(false))), - array('(true && false)', new BinaryNode('&&', new ConstantNode(true), new ConstantNode(false))), + return [ + ['(true || false)', new BinaryNode('or', new ConstantNode(true), new ConstantNode(false))], + ['(true || false)', new BinaryNode('||', new ConstantNode(true), new ConstantNode(false))], + ['(true && false)', new BinaryNode('and', new ConstantNode(true), new ConstantNode(false))], + ['(true && false)', new BinaryNode('&&', new ConstantNode(true), new ConstantNode(false))], - array('(2 & 4)', new BinaryNode('&', new ConstantNode(2), new ConstantNode(4))), - array('(2 | 4)', new BinaryNode('|', new ConstantNode(2), new ConstantNode(4))), - array('(2 ^ 4)', new BinaryNode('^', new ConstantNode(2), new ConstantNode(4))), + ['(2 & 4)', new BinaryNode('&', new ConstantNode(2), new ConstantNode(4))], + ['(2 | 4)', new BinaryNode('|', new ConstantNode(2), new ConstantNode(4))], + ['(2 ^ 4)', new BinaryNode('^', new ConstantNode(2), new ConstantNode(4))], - array('(1 < 2)', new BinaryNode('<', new ConstantNode(1), new ConstantNode(2))), - array('(1 <= 2)', new BinaryNode('<=', new ConstantNode(1), new ConstantNode(2))), - array('(1 <= 1)', new BinaryNode('<=', new ConstantNode(1), new ConstantNode(1))), + ['(1 < 2)', new BinaryNode('<', new ConstantNode(1), new ConstantNode(2))], + ['(1 <= 2)', new BinaryNode('<=', new ConstantNode(1), new ConstantNode(2))], + ['(1 <= 1)', new BinaryNode('<=', new ConstantNode(1), new ConstantNode(1))], - array('(1 > 2)', new BinaryNode('>', new ConstantNode(1), new ConstantNode(2))), - array('(1 >= 2)', new BinaryNode('>=', new ConstantNode(1), new ConstantNode(2))), - array('(1 >= 1)', new BinaryNode('>=', new ConstantNode(1), new ConstantNode(1))), + ['(1 > 2)', new BinaryNode('>', new ConstantNode(1), new ConstantNode(2))], + ['(1 >= 2)', new BinaryNode('>=', new ConstantNode(1), new ConstantNode(2))], + ['(1 >= 1)', new BinaryNode('>=', new ConstantNode(1), new ConstantNode(1))], - array('(true === true)', new BinaryNode('===', new ConstantNode(true), new ConstantNode(true))), - array('(true !== true)', new BinaryNode('!==', new ConstantNode(true), new ConstantNode(true))), + ['(true === true)', new BinaryNode('===', new ConstantNode(true), new ConstantNode(true))], + ['(true !== true)', new BinaryNode('!==', new ConstantNode(true), new ConstantNode(true))], - array('(2 == 1)', new BinaryNode('==', new ConstantNode(2), new ConstantNode(1))), - array('(2 != 1)', new BinaryNode('!=', new ConstantNode(2), new ConstantNode(1))), + ['(2 == 1)', new BinaryNode('==', new ConstantNode(2), new ConstantNode(1))], + ['(2 != 1)', new BinaryNode('!=', new ConstantNode(2), new ConstantNode(1))], - array('(1 - 2)', new BinaryNode('-', new ConstantNode(1), new ConstantNode(2))), - array('(1 + 2)', new BinaryNode('+', new ConstantNode(1), new ConstantNode(2))), - array('(2 * 2)', new BinaryNode('*', new ConstantNode(2), new ConstantNode(2))), - array('(2 / 2)', new BinaryNode('/', new ConstantNode(2), new ConstantNode(2))), - array('(5 % 2)', new BinaryNode('%', new ConstantNode(5), new ConstantNode(2))), - array('pow(5, 2)', new BinaryNode('**', new ConstantNode(5), new ConstantNode(2))), - array('("a" . "b")', new BinaryNode('~', new ConstantNode('a'), new ConstantNode('b'))), + ['(1 - 2)', new BinaryNode('-', new ConstantNode(1), new ConstantNode(2))], + ['(1 + 2)', new BinaryNode('+', new ConstantNode(1), new ConstantNode(2))], + ['(2 * 2)', new BinaryNode('*', new ConstantNode(2), new ConstantNode(2))], + ['(2 / 2)', new BinaryNode('/', new ConstantNode(2), new ConstantNode(2))], + ['(5 % 2)', new BinaryNode('%', new ConstantNode(5), new ConstantNode(2))], + ['pow(5, 2)', new BinaryNode('**', new ConstantNode(5), new ConstantNode(2))], + ['("a" . "b")', new BinaryNode('~', new ConstantNode('a'), new ConstantNode('b'))], - array('in_array("a", array(0 => "a", 1 => "b"))', new BinaryNode('in', new ConstantNode('a'), $array)), - array('in_array("c", array(0 => "a", 1 => "b"))', new BinaryNode('in', new ConstantNode('c'), $array)), - array('!in_array("c", array(0 => "a", 1 => "b"))', new BinaryNode('not in', new ConstantNode('c'), $array)), - array('!in_array("a", array(0 => "a", 1 => "b"))', new BinaryNode('not in', new ConstantNode('a'), $array)), + ['in_array("a", [0 => "a", 1 => "b"])', new BinaryNode('in', new ConstantNode('a'), $array)], + ['in_array("c", [0 => "a", 1 => "b"])', new BinaryNode('in', new ConstantNode('c'), $array)], + ['!in_array("c", [0 => "a", 1 => "b"])', new BinaryNode('not in', new ConstantNode('c'), $array)], + ['!in_array("a", [0 => "a", 1 => "b"])', new BinaryNode('not in', new ConstantNode('a'), $array)], - array('range(1, 3)', new BinaryNode('..', new ConstantNode(1), new ConstantNode(3))), + ['range(1, 3)', new BinaryNode('..', new ConstantNode(1), new ConstantNode(3))], - array('preg_match("/^[a-z]+/i\$/", "abc")', new BinaryNode('matches', new ConstantNode('abc'), new ConstantNode('/^[a-z]+/i$/'))), - ); + ['preg_match("/^[a-z]+/i\$/", "abc")', new BinaryNode('matches', new ConstantNode('abc'), new ConstantNode('/^[a-z]+/i$/'))], + ]; } public function getDumpData() @@ -121,46 +121,46 @@ class BinaryNodeTest extends AbstractNodeTest $array->addElement(new ConstantNode('a')); $array->addElement(new ConstantNode('b')); - return array( - array('(true or false)', new BinaryNode('or', new ConstantNode(true), new ConstantNode(false))), - array('(true || false)', new BinaryNode('||', new ConstantNode(true), new ConstantNode(false))), - array('(true and false)', new BinaryNode('and', new ConstantNode(true), new ConstantNode(false))), - array('(true && false)', new BinaryNode('&&', new ConstantNode(true), new ConstantNode(false))), + return [ + ['(true or false)', new BinaryNode('or', new ConstantNode(true), new ConstantNode(false))], + ['(true || false)', new BinaryNode('||', new ConstantNode(true), new ConstantNode(false))], + ['(true and false)', new BinaryNode('and', new ConstantNode(true), new ConstantNode(false))], + ['(true && false)', new BinaryNode('&&', new ConstantNode(true), new ConstantNode(false))], - array('(2 & 4)', new BinaryNode('&', new ConstantNode(2), new ConstantNode(4))), - array('(2 | 4)', new BinaryNode('|', new ConstantNode(2), new ConstantNode(4))), - array('(2 ^ 4)', new BinaryNode('^', new ConstantNode(2), new ConstantNode(4))), + ['(2 & 4)', new BinaryNode('&', new ConstantNode(2), new ConstantNode(4))], + ['(2 | 4)', new BinaryNode('|', new ConstantNode(2), new ConstantNode(4))], + ['(2 ^ 4)', new BinaryNode('^', new ConstantNode(2), new ConstantNode(4))], - array('(1 < 2)', new BinaryNode('<', new ConstantNode(1), new ConstantNode(2))), - array('(1 <= 2)', new BinaryNode('<=', new ConstantNode(1), new ConstantNode(2))), - array('(1 <= 1)', new BinaryNode('<=', new ConstantNode(1), new ConstantNode(1))), + ['(1 < 2)', new BinaryNode('<', new ConstantNode(1), new ConstantNode(2))], + ['(1 <= 2)', new BinaryNode('<=', new ConstantNode(1), new ConstantNode(2))], + ['(1 <= 1)', new BinaryNode('<=', new ConstantNode(1), new ConstantNode(1))], - array('(1 > 2)', new BinaryNode('>', new ConstantNode(1), new ConstantNode(2))), - array('(1 >= 2)', new BinaryNode('>=', new ConstantNode(1), new ConstantNode(2))), - array('(1 >= 1)', new BinaryNode('>=', new ConstantNode(1), new ConstantNode(1))), + ['(1 > 2)', new BinaryNode('>', new ConstantNode(1), new ConstantNode(2))], + ['(1 >= 2)', new BinaryNode('>=', new ConstantNode(1), new ConstantNode(2))], + ['(1 >= 1)', new BinaryNode('>=', new ConstantNode(1), new ConstantNode(1))], - array('(true === true)', new BinaryNode('===', new ConstantNode(true), new ConstantNode(true))), - array('(true !== true)', new BinaryNode('!==', new ConstantNode(true), new ConstantNode(true))), + ['(true === true)', new BinaryNode('===', new ConstantNode(true), new ConstantNode(true))], + ['(true !== true)', new BinaryNode('!==', new ConstantNode(true), new ConstantNode(true))], - array('(2 == 1)', new BinaryNode('==', new ConstantNode(2), new ConstantNode(1))), - array('(2 != 1)', new BinaryNode('!=', new ConstantNode(2), new ConstantNode(1))), + ['(2 == 1)', new BinaryNode('==', new ConstantNode(2), new ConstantNode(1))], + ['(2 != 1)', new BinaryNode('!=', new ConstantNode(2), new ConstantNode(1))], - array('(1 - 2)', new BinaryNode('-', new ConstantNode(1), new ConstantNode(2))), - array('(1 + 2)', new BinaryNode('+', new ConstantNode(1), new ConstantNode(2))), - array('(2 * 2)', new BinaryNode('*', new ConstantNode(2), new ConstantNode(2))), - array('(2 / 2)', new BinaryNode('/', new ConstantNode(2), new ConstantNode(2))), - array('(5 % 2)', new BinaryNode('%', new ConstantNode(5), new ConstantNode(2))), - array('(5 ** 2)', new BinaryNode('**', new ConstantNode(5), new ConstantNode(2))), - array('("a" ~ "b")', new BinaryNode('~', new ConstantNode('a'), new ConstantNode('b'))), + ['(1 - 2)', new BinaryNode('-', new ConstantNode(1), new ConstantNode(2))], + ['(1 + 2)', new BinaryNode('+', new ConstantNode(1), new ConstantNode(2))], + ['(2 * 2)', new BinaryNode('*', new ConstantNode(2), new ConstantNode(2))], + ['(2 / 2)', new BinaryNode('/', new ConstantNode(2), new ConstantNode(2))], + ['(5 % 2)', new BinaryNode('%', new ConstantNode(5), new ConstantNode(2))], + ['(5 ** 2)', new BinaryNode('**', new ConstantNode(5), new ConstantNode(2))], + ['("a" ~ "b")', new BinaryNode('~', new ConstantNode('a'), new ConstantNode('b'))], - array('("a" in ["a", "b"])', new BinaryNode('in', new ConstantNode('a'), $array)), - array('("c" in ["a", "b"])', new BinaryNode('in', new ConstantNode('c'), $array)), - array('("c" not in ["a", "b"])', new BinaryNode('not in', new ConstantNode('c'), $array)), - array('("a" not in ["a", "b"])', new BinaryNode('not in', new ConstantNode('a'), $array)), + ['("a" in ["a", "b"])', new BinaryNode('in', new ConstantNode('a'), $array)], + ['("c" in ["a", "b"])', new BinaryNode('in', new ConstantNode('c'), $array)], + ['("c" not in ["a", "b"])', new BinaryNode('not in', new ConstantNode('c'), $array)], + ['("a" not in ["a", "b"])', new BinaryNode('not in', new ConstantNode('a'), $array)], - array('(1 .. 3)', new BinaryNode('..', new ConstantNode(1), new ConstantNode(3))), + ['(1 .. 3)', new BinaryNode('..', new ConstantNode(1), new ConstantNode(3))], - array('("abc" matches "/^[a-z]+/i$/")', new BinaryNode('matches', new ConstantNode('abc'), new ConstantNode('/^[a-z]+/i$/'))), - ); + ['("abc" matches "/^[a-z]+/i$/")', new BinaryNode('matches', new ConstantNode('abc'), new ConstantNode('/^[a-z]+/i$/'))], + ]; } } diff --git a/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/ConditionalNodeTest.php b/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/ConditionalNodeTest.php index cbf9e8d43..13b7cbdec 100644 --- a/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/ConditionalNodeTest.php +++ b/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/ConditionalNodeTest.php @@ -18,25 +18,25 @@ class ConditionalNodeTest extends AbstractNodeTest { public function getEvaluateData() { - return array( - array(1, new ConditionalNode(new ConstantNode(true), new ConstantNode(1), new ConstantNode(2))), - array(2, new ConditionalNode(new ConstantNode(false), new ConstantNode(1), new ConstantNode(2))), - ); + return [ + [1, new ConditionalNode(new ConstantNode(true), new ConstantNode(1), new ConstantNode(2))], + [2, new ConditionalNode(new ConstantNode(false), new ConstantNode(1), new ConstantNode(2))], + ]; } public function getCompileData() { - return array( - array('((true) ? (1) : (2))', new ConditionalNode(new ConstantNode(true), new ConstantNode(1), new ConstantNode(2))), - array('((false) ? (1) : (2))', new ConditionalNode(new ConstantNode(false), new ConstantNode(1), new ConstantNode(2))), - ); + return [ + ['((true) ? (1) : (2))', new ConditionalNode(new ConstantNode(true), new ConstantNode(1), new ConstantNode(2))], + ['((false) ? (1) : (2))', new ConditionalNode(new ConstantNode(false), new ConstantNode(1), new ConstantNode(2))], + ]; } public function getDumpData() { - return array( - array('(true ? 1 : 2)', new ConditionalNode(new ConstantNode(true), new ConstantNode(1), new ConstantNode(2))), - array('(false ? 1 : 2)', new ConditionalNode(new ConstantNode(false), new ConstantNode(1), new ConstantNode(2))), - ); + return [ + ['(true ? 1 : 2)', new ConditionalNode(new ConstantNode(true), new ConstantNode(1), new ConstantNode(2))], + ['(false ? 1 : 2)', new ConditionalNode(new ConstantNode(false), new ConstantNode(1), new ConstantNode(2))], + ]; } } diff --git a/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/ConstantNodeTest.php b/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/ConstantNodeTest.php index af79a91c5..fee9f5bff 100644 --- a/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/ConstantNodeTest.php +++ b/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/ConstantNodeTest.php @@ -17,44 +17,44 @@ class ConstantNodeTest extends AbstractNodeTest { public function getEvaluateData() { - return array( - array(false, new ConstantNode(false)), - array(true, new ConstantNode(true)), - array(null, new ConstantNode(null)), - array(3, new ConstantNode(3)), - array(3.3, new ConstantNode(3.3)), - array('foo', new ConstantNode('foo')), - array(array(1, 'b' => 'a'), new ConstantNode(array(1, 'b' => 'a'))), - ); + return [ + [false, new ConstantNode(false)], + [true, new ConstantNode(true)], + [null, new ConstantNode(null)], + [3, new ConstantNode(3)], + [3.3, new ConstantNode(3.3)], + ['foo', new ConstantNode('foo')], + [[1, 'b' => 'a'], new ConstantNode([1, 'b' => 'a'])], + ]; } public function getCompileData() { - return array( - array('false', new ConstantNode(false)), - array('true', new ConstantNode(true)), - array('null', new ConstantNode(null)), - array('3', new ConstantNode(3)), - array('3.3', new ConstantNode(3.3)), - array('"foo"', new ConstantNode('foo')), - array('array(0 => 1, "b" => "a")', new ConstantNode(array(1, 'b' => 'a'))), - ); + return [ + ['false', new ConstantNode(false)], + ['true', new ConstantNode(true)], + ['null', new ConstantNode(null)], + ['3', new ConstantNode(3)], + ['3.3', new ConstantNode(3.3)], + ['"foo"', new ConstantNode('foo')], + ['[0 => 1, "b" => "a"]', new ConstantNode([1, 'b' => 'a'])], + ]; } public function getDumpData() { - return array( - array('false', new ConstantNode(false)), - array('true', new ConstantNode(true)), - array('null', new ConstantNode(null)), - array('3', new ConstantNode(3)), - array('3.3', new ConstantNode(3.3)), - array('"foo"', new ConstantNode('foo')), - array('foo', new ConstantNode('foo', true)), - array('{0: 1, "b": "a", 1: true}', new ConstantNode(array(1, 'b' => 'a', true))), - array('{"a\\"b": "c", "a\\\\b": "d"}', new ConstantNode(array('a"b' => 'c', 'a\\b' => 'd'))), - array('["c", "d"]', new ConstantNode(array('c', 'd'))), - array('{"a": ["b"]}', new ConstantNode(array('a' => array('b')))), - ); + return [ + ['false', new ConstantNode(false)], + ['true', new ConstantNode(true)], + ['null', new ConstantNode(null)], + ['3', new ConstantNode(3)], + ['3.3', new ConstantNode(3.3)], + ['"foo"', new ConstantNode('foo')], + ['foo', new ConstantNode('foo', true)], + ['{0: 1, "b": "a", 1: true}', new ConstantNode([1, 'b' => 'a', true])], + ['{"a\\"b": "c", "a\\\\b": "d"}', new ConstantNode(['a"b' => 'c', 'a\\b' => 'd'])], + ['["c", "d"]', new ConstantNode(['c', 'd'])], + ['{"a": ["b"]}', new ConstantNode(['a' => ['b']])], + ]; } } diff --git a/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/FunctionNodeTest.php b/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/FunctionNodeTest.php index 8d6f92a9c..c6cb02c1b 100644 --- a/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/FunctionNodeTest.php +++ b/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/FunctionNodeTest.php @@ -11,42 +11,42 @@ namespace Symfony\Component\ExpressionLanguage\Tests\Node; -use Symfony\Component\ExpressionLanguage\Node\FunctionNode; use Symfony\Component\ExpressionLanguage\Node\ConstantNode; +use Symfony\Component\ExpressionLanguage\Node\FunctionNode; use Symfony\Component\ExpressionLanguage\Node\Node; class FunctionNodeTest extends AbstractNodeTest { public function getEvaluateData() { - return array( - array('bar', new FunctionNode('foo', new Node(array(new ConstantNode('bar')))), array(), array('foo' => $this->getCallables())), - ); + return [ + ['bar', new FunctionNode('foo', new Node([new ConstantNode('bar')])), [], ['foo' => $this->getCallables()]], + ]; } public function getCompileData() { - return array( - array('foo("bar")', new FunctionNode('foo', new Node(array(new ConstantNode('bar')))), array('foo' => $this->getCallables())), - ); + return [ + ['foo("bar")', new FunctionNode('foo', new Node([new ConstantNode('bar')])), ['foo' => $this->getCallables()]], + ]; } public function getDumpData() { - return array( - array('foo("bar")', new FunctionNode('foo', new Node(array(new ConstantNode('bar')))), array('foo' => $this->getCallables())), - ); + return [ + ['foo("bar")', new FunctionNode('foo', new Node([new ConstantNode('bar')])), ['foo' => $this->getCallables()]], + ]; } protected function getCallables() { - return array( + return [ 'compiler' => function ($arg) { return sprintf('foo(%s)', $arg); }, 'evaluator' => function ($variables, $arg) { return $arg; }, - ); + ]; } } diff --git a/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/GetAttrNodeTest.php b/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/GetAttrNodeTest.php index cf7cd7a03..c790f33ac 100644 --- a/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/GetAttrNodeTest.php +++ b/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/GetAttrNodeTest.php @@ -12,49 +12,49 @@ namespace Symfony\Component\ExpressionLanguage\Tests\Node; use Symfony\Component\ExpressionLanguage\Node\ArrayNode; -use Symfony\Component\ExpressionLanguage\Node\NameNode; -use Symfony\Component\ExpressionLanguage\Node\GetAttrNode; use Symfony\Component\ExpressionLanguage\Node\ConstantNode; +use Symfony\Component\ExpressionLanguage\Node\GetAttrNode; +use Symfony\Component\ExpressionLanguage\Node\NameNode; class GetAttrNodeTest extends AbstractNodeTest { public function getEvaluateData() { - return array( - array('b', new GetAttrNode(new NameNode('foo'), new ConstantNode(0), $this->getArrayNode(), GetAttrNode::ARRAY_CALL), array('foo' => array('b' => 'a', 'b'))), - array('a', new GetAttrNode(new NameNode('foo'), new ConstantNode('b'), $this->getArrayNode(), GetAttrNode::ARRAY_CALL), array('foo' => array('b' => 'a', 'b'))), + return [ + ['b', new GetAttrNode(new NameNode('foo'), new ConstantNode(0), $this->getArrayNode(), GetAttrNode::ARRAY_CALL), ['foo' => ['b' => 'a', 'b']]], + ['a', new GetAttrNode(new NameNode('foo'), new ConstantNode('b'), $this->getArrayNode(), GetAttrNode::ARRAY_CALL), ['foo' => ['b' => 'a', 'b']]], - array('bar', new GetAttrNode(new NameNode('foo'), new ConstantNode('foo'), $this->getArrayNode(), GetAttrNode::PROPERTY_CALL), array('foo' => new Obj())), + ['bar', new GetAttrNode(new NameNode('foo'), new ConstantNode('foo'), $this->getArrayNode(), GetAttrNode::PROPERTY_CALL), ['foo' => new Obj()]], - array('baz', new GetAttrNode(new NameNode('foo'), new ConstantNode('foo'), $this->getArrayNode(), GetAttrNode::METHOD_CALL), array('foo' => new Obj())), - array('a', new GetAttrNode(new NameNode('foo'), new NameNode('index'), $this->getArrayNode(), GetAttrNode::ARRAY_CALL), array('foo' => array('b' => 'a', 'b'), 'index' => 'b')), - ); + ['baz', new GetAttrNode(new NameNode('foo'), new ConstantNode('foo'), $this->getArrayNode(), GetAttrNode::METHOD_CALL), ['foo' => new Obj()]], + ['a', new GetAttrNode(new NameNode('foo'), new NameNode('index'), $this->getArrayNode(), GetAttrNode::ARRAY_CALL), ['foo' => ['b' => 'a', 'b'], 'index' => 'b']], + ]; } public function getCompileData() { - return array( - array('$foo[0]', new GetAttrNode(new NameNode('foo'), new ConstantNode(0), $this->getArrayNode(), GetAttrNode::ARRAY_CALL)), - array('$foo["b"]', new GetAttrNode(new NameNode('foo'), new ConstantNode('b'), $this->getArrayNode(), GetAttrNode::ARRAY_CALL)), + return [ + ['$foo[0]', new GetAttrNode(new NameNode('foo'), new ConstantNode(0), $this->getArrayNode(), GetAttrNode::ARRAY_CALL)], + ['$foo["b"]', new GetAttrNode(new NameNode('foo'), new ConstantNode('b'), $this->getArrayNode(), GetAttrNode::ARRAY_CALL)], - array('$foo->foo', new GetAttrNode(new NameNode('foo'), new ConstantNode('foo'), $this->getArrayNode(), GetAttrNode::PROPERTY_CALL), array('foo' => new Obj())), + ['$foo->foo', new GetAttrNode(new NameNode('foo'), new ConstantNode('foo'), $this->getArrayNode(), GetAttrNode::PROPERTY_CALL), ['foo' => new Obj()]], - array('$foo->foo(array("b" => "a", 0 => "b"))', new GetAttrNode(new NameNode('foo'), new ConstantNode('foo'), $this->getArrayNode(), GetAttrNode::METHOD_CALL), array('foo' => new Obj())), - array('$foo[$index]', new GetAttrNode(new NameNode('foo'), new NameNode('index'), $this->getArrayNode(), GetAttrNode::ARRAY_CALL)), - ); + ['$foo->foo(["b" => "a", 0 => "b"])', new GetAttrNode(new NameNode('foo'), new ConstantNode('foo'), $this->getArrayNode(), GetAttrNode::METHOD_CALL), ['foo' => new Obj()]], + ['$foo[$index]', new GetAttrNode(new NameNode('foo'), new NameNode('index'), $this->getArrayNode(), GetAttrNode::ARRAY_CALL)], + ]; } public function getDumpData() { - return array( - array('foo[0]', new GetAttrNode(new NameNode('foo'), new ConstantNode(0), $this->getArrayNode(), GetAttrNode::ARRAY_CALL)), - array('foo["b"]', new GetAttrNode(new NameNode('foo'), new ConstantNode('b'), $this->getArrayNode(), GetAttrNode::ARRAY_CALL)), + return [ + ['foo[0]', new GetAttrNode(new NameNode('foo'), new ConstantNode(0), $this->getArrayNode(), GetAttrNode::ARRAY_CALL)], + ['foo["b"]', new GetAttrNode(new NameNode('foo'), new ConstantNode('b'), $this->getArrayNode(), GetAttrNode::ARRAY_CALL)], - array('foo.foo', new GetAttrNode(new NameNode('foo'), new NameNode('foo'), $this->getArrayNode(), GetAttrNode::PROPERTY_CALL), array('foo' => new Obj())), + ['foo.foo', new GetAttrNode(new NameNode('foo'), new NameNode('foo'), $this->getArrayNode(), GetAttrNode::PROPERTY_CALL), ['foo' => new Obj()]], - array('foo.foo({"b": "a", 0: "b"})', new GetAttrNode(new NameNode('foo'), new NameNode('foo'), $this->getArrayNode(), GetAttrNode::METHOD_CALL), array('foo' => new Obj())), - array('foo[index]', new GetAttrNode(new NameNode('foo'), new NameNode('index'), $this->getArrayNode(), GetAttrNode::ARRAY_CALL)), - ); + ['foo.foo({"b": "a", 0: "b"})', new GetAttrNode(new NameNode('foo'), new NameNode('foo'), $this->getArrayNode(), GetAttrNode::METHOD_CALL), ['foo' => new Obj()]], + ['foo[index]', new GetAttrNode(new NameNode('foo'), new NameNode('index'), $this->getArrayNode(), GetAttrNode::ARRAY_CALL)], + ]; } protected function getArrayNode() diff --git a/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/NameNodeTest.php b/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/NameNodeTest.php index 5fa2c37f2..a30c27b80 100644 --- a/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/NameNodeTest.php +++ b/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/NameNodeTest.php @@ -17,22 +17,22 @@ class NameNodeTest extends AbstractNodeTest { public function getEvaluateData() { - return array( - array('bar', new NameNode('foo'), array('foo' => 'bar')), - ); + return [ + ['bar', new NameNode('foo'), ['foo' => 'bar']], + ]; } public function getCompileData() { - return array( - array('$foo', new NameNode('foo')), - ); + return [ + ['$foo', new NameNode('foo')], + ]; } public function getDumpData() { - return array( - array('foo', new NameNode('foo')), - ); + return [ + ['foo', new NameNode('foo')], + ]; } } diff --git a/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/NodeTest.php b/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/NodeTest.php index 0f35b5feb..351da0514 100644 --- a/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/NodeTest.php +++ b/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/NodeTest.php @@ -12,14 +12,14 @@ namespace Symfony\Component\ExpressionLanguage\Tests\Node; use PHPUnit\Framework\TestCase; -use Symfony\Component\ExpressionLanguage\Node\Node; use Symfony\Component\ExpressionLanguage\Node\ConstantNode; +use Symfony\Component\ExpressionLanguage\Node\Node; class NodeTest extends TestCase { public function testToString() { - $node = new Node(array(new ConstantNode('foo'))); + $node = new Node([new ConstantNode('foo')]); $this->assertEquals(<<<'EOF' Node( @@ -31,7 +31,7 @@ EOF public function testSerialization() { - $node = new Node(array('foo' => 'bar'), array('bar' => 'foo')); + $node = new Node(['foo' => 'bar'], ['bar' => 'foo']); $serializedNode = serialize($node); $unserializedNode = unserialize($serializedNode); diff --git a/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/UnaryNodeTest.php b/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/UnaryNodeTest.php index ae2e3eee7..bac75d24d 100644 --- a/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/UnaryNodeTest.php +++ b/advancedcontentfilter/vendor/symfony/expression-language/Tests/Node/UnaryNodeTest.php @@ -11,38 +11,38 @@ namespace Symfony\Component\ExpressionLanguage\Tests\Node; -use Symfony\Component\ExpressionLanguage\Node\UnaryNode; use Symfony\Component\ExpressionLanguage\Node\ConstantNode; +use Symfony\Component\ExpressionLanguage\Node\UnaryNode; class UnaryNodeTest extends AbstractNodeTest { public function getEvaluateData() { - return array( - array(-1, new UnaryNode('-', new ConstantNode(1))), - array(3, new UnaryNode('+', new ConstantNode(3))), - array(false, new UnaryNode('!', new ConstantNode(true))), - array(false, new UnaryNode('not', new ConstantNode(true))), - ); + return [ + [-1, new UnaryNode('-', new ConstantNode(1))], + [3, new UnaryNode('+', new ConstantNode(3))], + [false, new UnaryNode('!', new ConstantNode(true))], + [false, new UnaryNode('not', new ConstantNode(true))], + ]; } public function getCompileData() { - return array( - array('(-1)', new UnaryNode('-', new ConstantNode(1))), - array('(+3)', new UnaryNode('+', new ConstantNode(3))), - array('(!true)', new UnaryNode('!', new ConstantNode(true))), - array('(!true)', new UnaryNode('not', new ConstantNode(true))), - ); + return [ + ['(-1)', new UnaryNode('-', new ConstantNode(1))], + ['(+3)', new UnaryNode('+', new ConstantNode(3))], + ['(!true)', new UnaryNode('!', new ConstantNode(true))], + ['(!true)', new UnaryNode('not', new ConstantNode(true))], + ]; } public function getDumpData() { - return array( - array('(- 1)', new UnaryNode('-', new ConstantNode(1))), - array('(+ 3)', new UnaryNode('+', new ConstantNode(3))), - array('(! true)', new UnaryNode('!', new ConstantNode(true))), - array('(not true)', new UnaryNode('not', new ConstantNode(true))), - ); + return [ + ['(- 1)', new UnaryNode('-', new ConstantNode(1))], + ['(+ 3)', new UnaryNode('+', new ConstantNode(3))], + ['(! true)', new UnaryNode('!', new ConstantNode(true))], + ['(not true)', new UnaryNode('not', new ConstantNode(true))], + ]; } } diff --git a/advancedcontentfilter/vendor/symfony/expression-language/Tests/ParserCache/ParserCacheAdapterTest.php b/advancedcontentfilter/vendor/symfony/expression-language/Tests/ParserCache/ParserCacheAdapterTest.php index 447316111..f82af92e1 100644 --- a/advancedcontentfilter/vendor/symfony/expression-language/Tests/ParserCache/ParserCacheAdapterTest.php +++ b/advancedcontentfilter/vendor/symfony/expression-language/Tests/ParserCache/ParserCacheAdapterTest.php @@ -12,9 +12,9 @@ namespace Symfony\Component\ExpressionLanguage\Tests; use PHPUnit\Framework\TestCase; +use Symfony\Component\ExpressionLanguage\Node\Node; use Symfony\Component\ExpressionLanguage\ParsedExpression; use Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheAdapter; -use Symfony\Component\ExpressionLanguage\Node\Node; /** * @group legacy @@ -38,8 +38,8 @@ class ParserCacheAdapterTest extends TestCase $cacheItem = $parserCacheAdapter->getItem($key); - $this->assertEquals($cacheItem->get(), $value); - $this->assertEquals($cacheItem->isHit(), true); + $this->assertEquals($value, $cacheItem->get()); + $this->assertTrue($cacheItem->isHit()); } public function testSave() @@ -47,7 +47,7 @@ class ParserCacheAdapterTest extends TestCase $poolMock = $this->getMockBuilder('Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface')->getMock(); $cacheItemMock = $this->getMockBuilder('Psr\Cache\CacheItemInterface')->getMock(); $key = 'key'; - $value = new ParsedExpression('1 + 1', new Node(array(), array())); + $value = new ParsedExpression('1 + 1', new Node([], [])); $parserCacheAdapter = new ParserCacheAdapter($poolMock); $poolMock @@ -68,14 +68,14 @@ class ParserCacheAdapterTest extends TestCase ->willReturn($value) ; - $cacheItem = $parserCacheAdapter->save($cacheItemMock); + $parserCacheAdapter->save($cacheItemMock); } public function testGetItems() { $poolMock = $this->getMockBuilder('Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface')->getMock(); $parserCacheAdapter = new ParserCacheAdapter($poolMock); - $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}(\BadMethodCallException::class); + $this->expectException(\BadMethodCallException::class); $parserCacheAdapter->getItems(); } @@ -85,7 +85,7 @@ class ParserCacheAdapterTest extends TestCase $poolMock = $this->getMockBuilder('Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface')->getMock(); $key = 'key'; $parserCacheAdapter = new ParserCacheAdapter($poolMock); - $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}(\BadMethodCallException::class); + $this->expectException(\BadMethodCallException::class); $parserCacheAdapter->hasItem($key); } @@ -94,7 +94,7 @@ class ParserCacheAdapterTest extends TestCase { $poolMock = $this->getMockBuilder('Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface')->getMock(); $parserCacheAdapter = new ParserCacheAdapter($poolMock); - $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}(\BadMethodCallException::class); + $this->expectException(\BadMethodCallException::class); $parserCacheAdapter->clear(); } @@ -104,7 +104,7 @@ class ParserCacheAdapterTest extends TestCase $poolMock = $this->getMockBuilder('Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface')->getMock(); $key = 'key'; $parserCacheAdapter = new ParserCacheAdapter($poolMock); - $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}(\BadMethodCallException::class); + $this->expectException(\BadMethodCallException::class); $parserCacheAdapter->deleteItem($key); } @@ -112,9 +112,9 @@ class ParserCacheAdapterTest extends TestCase public function testDeleteItems() { $poolMock = $this->getMockBuilder('Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface')->getMock(); - $keys = array('key'); + $keys = ['key']; $parserCacheAdapter = new ParserCacheAdapter($poolMock); - $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}(\BadMethodCallException::class); + $this->expectException(\BadMethodCallException::class); $parserCacheAdapter->deleteItems($keys); } @@ -124,7 +124,7 @@ class ParserCacheAdapterTest extends TestCase $poolMock = $this->getMockBuilder('Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface')->getMock(); $parserCacheAdapter = new ParserCacheAdapter($poolMock); $cacheItemMock = $this->getMockBuilder('Psr\Cache\CacheItemInterface')->getMock(); - $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}(\BadMethodCallException::class); + $this->expectException(\BadMethodCallException::class); $parserCacheAdapter->saveDeferred($cacheItemMock); } @@ -133,7 +133,7 @@ class ParserCacheAdapterTest extends TestCase { $poolMock = $this->getMockBuilder('Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface')->getMock(); $parserCacheAdapter = new ParserCacheAdapter($poolMock); - $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}(\BadMethodCallException::class); + $this->expectException(\BadMethodCallException::class); $parserCacheAdapter->commit(); } diff --git a/advancedcontentfilter/vendor/symfony/expression-language/Tests/ParserTest.php b/advancedcontentfilter/vendor/symfony/expression-language/Tests/ParserTest.php index 11464abd2..2d5a0a6c8 100644 --- a/advancedcontentfilter/vendor/symfony/expression-language/Tests/ParserTest.php +++ b/advancedcontentfilter/vendor/symfony/expression-language/Tests/ParserTest.php @@ -12,41 +12,37 @@ namespace Symfony\Component\ExpressionLanguage\Tests; use PHPUnit\Framework\TestCase; -use Symfony\Component\ExpressionLanguage\Parser; use Symfony\Component\ExpressionLanguage\Lexer; use Symfony\Component\ExpressionLanguage\Node; +use Symfony\Component\ExpressionLanguage\Parser; class ParserTest extends TestCase { - /** - * @expectedException \Symfony\Component\ExpressionLanguage\SyntaxError - * @expectedExceptionMessage Variable "foo" is not valid around position 1 for expression `foo`. - */ public function testParseWithInvalidName() { + $this->expectException('Symfony\Component\ExpressionLanguage\SyntaxError'); + $this->expectExceptionMessage('Variable "foo" is not valid around position 1 for expression `foo`.'); $lexer = new Lexer(); - $parser = new Parser(array()); + $parser = new Parser([]); $parser->parse($lexer->tokenize('foo')); } - /** - * @expectedException \Symfony\Component\ExpressionLanguage\SyntaxError - * @expectedExceptionMessage Variable "foo" is not valid around position 1 for expression `foo`. - */ public function testParseWithZeroInNames() { + $this->expectException('Symfony\Component\ExpressionLanguage\SyntaxError'); + $this->expectExceptionMessage('Variable "foo" is not valid around position 1 for expression `foo`.'); $lexer = new Lexer(); - $parser = new Parser(array()); - $parser->parse($lexer->tokenize('foo'), array(0)); + $parser = new Parser([]); + $parser->parse($lexer->tokenize('foo'), [0]); } /** * @dataProvider getParseData */ - public function testParse($node, $expression, $names = array()) + public function testParse($node, $expression, $names = []) { $lexer = new Lexer(); - $parser = new Parser(array()); + $parser = new Parser([]); $this->assertEquals($node, $parser->parse($lexer->tokenize($expression), $names)); } @@ -57,63 +53,66 @@ class ParserTest extends TestCase $arguments->addElement(new Node\ConstantNode(2)); $arguments->addElement(new Node\ConstantNode(true)); - return array( - array( + $arrayNode = new Node\ArrayNode(); + $arrayNode->addElement(new Node\NameNode('bar')); + + return [ + [ new Node\NameNode('a'), 'a', - array('a'), - ), - array( + ['a'], + ], + [ new Node\ConstantNode('a'), '"a"', - ), - array( + ], + [ new Node\ConstantNode(3), '3', - ), - array( + ], + [ new Node\ConstantNode(false), 'false', - ), - array( + ], + [ new Node\ConstantNode(true), 'true', - ), - array( + ], + [ new Node\ConstantNode(null), 'null', - ), - array( + ], + [ new Node\UnaryNode('-', new Node\ConstantNode(3)), '-3', - ), - array( + ], + [ new Node\BinaryNode('-', new Node\ConstantNode(3), new Node\ConstantNode(3)), '3 - 3', - ), - array( + ], + [ new Node\BinaryNode('*', new Node\BinaryNode('-', new Node\ConstantNode(3), new Node\ConstantNode(3)), new Node\ConstantNode(2) ), '(3 - 3) * 2', - ), - array( + ], + [ new Node\GetAttrNode(new Node\NameNode('foo'), new Node\ConstantNode('bar', true), new Node\ArgumentsNode(), Node\GetAttrNode::PROPERTY_CALL), 'foo.bar', - array('foo'), - ), - array( + ['foo'], + ], + [ new Node\GetAttrNode(new Node\NameNode('foo'), new Node\ConstantNode('bar', true), new Node\ArgumentsNode(), Node\GetAttrNode::METHOD_CALL), 'foo.bar()', - array('foo'), - ), - array( + ['foo'], + ], + [ new Node\GetAttrNode(new Node\NameNode('foo'), new Node\ConstantNode('not', true), new Node\ArgumentsNode(), Node\GetAttrNode::METHOD_CALL), 'foo.not()', - array('foo'), - ), - array( + ['foo'], + ], + [ new Node\GetAttrNode( new Node\NameNode('foo'), new Node\ConstantNode('bar', true), @@ -121,24 +120,24 @@ class ParserTest extends TestCase Node\GetAttrNode::METHOD_CALL ), 'foo.bar("arg1", 2, true)', - array('foo'), - ), - array( + ['foo'], + ], + [ new Node\GetAttrNode(new Node\NameNode('foo'), new Node\ConstantNode(3), new Node\ArgumentsNode(), Node\GetAttrNode::ARRAY_CALL), 'foo[3]', - array('foo'), - ), - array( + ['foo'], + ], + [ new Node\ConditionalNode(new Node\ConstantNode(true), new Node\ConstantNode(true), new Node\ConstantNode(false)), 'true ? true : false', - ), - array( + ], + [ new Node\BinaryNode('matches', new Node\ConstantNode('foo'), new Node\ConstantNode('/foo/')), '"foo" matches "/foo/"', - ), + ], // chained calls - array( + [ $this->createGetAttrNode( $this->createGetAttrNode( $this->createGetAttrNode( @@ -147,15 +146,45 @@ class ParserTest extends TestCase 'baz', Node\GetAttrNode::PROPERTY_CALL), '3', Node\GetAttrNode::ARRAY_CALL), 'foo.bar().foo().baz[3]', - array('foo'), - ), + ['foo'], + ], - array( + [ new Node\NameNode('foo'), 'bar', - array('foo' => 'bar'), - ), - ); + ['foo' => 'bar'], + ], + + // Operators collisions + [ + new Node\BinaryNode( + 'in', + new Node\GetAttrNode( + new Node\NameNode('foo'), + new Node\ConstantNode('not', true), + new Node\ArgumentsNode(), + Node\GetAttrNode::PROPERTY_CALL + ), + $arrayNode + ), + 'foo.not in [bar]', + ['foo', 'bar'], + ], + [ + new Node\BinaryNode( + 'or', + new Node\UnaryNode('not', new Node\NameNode('foo')), + new Node\GetAttrNode( + new Node\NameNode('foo'), + new Node\ConstantNode('not', true), + new Node\ArgumentsNode(), + Node\GetAttrNode::PROPERTY_CALL + ) + ), + 'not foo or foo.not', + ['foo'], + ], + ]; } private function createGetAttrNode($node, $item, $type) @@ -165,46 +194,44 @@ class ParserTest extends TestCase /** * @dataProvider getInvalidPostfixData - * @expectedException \Symfony\Component\ExpressionLanguage\SyntaxError */ - public function testParseWithInvalidPostfixData($expr, $names = array()) + public function testParseWithInvalidPostfixData($expr, $names = []) { + $this->expectException('Symfony\Component\ExpressionLanguage\SyntaxError'); $lexer = new Lexer(); - $parser = new Parser(array()); + $parser = new Parser([]); $parser->parse($lexer->tokenize($expr), $names); } public function getInvalidPostfixData() { - return array( - array( + return [ + [ 'foo."#"', - array('foo'), - ), - array( + ['foo'], + ], + [ 'foo."bar"', - array('foo'), - ), - array( + ['foo'], + ], + [ 'foo.**', - array('foo'), - ), - array( + ['foo'], + ], + [ 'foo.123', - array('foo'), - ), - ); + ['foo'], + ], + ]; } - /** - * @expectedException \Symfony\Component\ExpressionLanguage\SyntaxError - * @expectedExceptionMessage Did you mean "baz"? - */ public function testNameProposal() { + $this->expectException('Symfony\Component\ExpressionLanguage\SyntaxError'); + $this->expectExceptionMessage('Did you mean "baz"?'); $lexer = new Lexer(); - $parser = new Parser(array()); + $parser = new Parser([]); - $parser->parse($lexer->tokenize('foo > bar'), array('foo', 'baz')); + $parser->parse($lexer->tokenize('foo > bar'), ['foo', 'baz']); } } diff --git a/advancedcontentfilter/vendor/symfony/expression-language/Token.php b/advancedcontentfilter/vendor/symfony/expression-language/Token.php index 4517335bb..60dc32d7f 100644 --- a/advancedcontentfilter/vendor/symfony/expression-language/Token.php +++ b/advancedcontentfilter/vendor/symfony/expression-language/Token.php @@ -54,7 +54,7 @@ class Token /** * Tests the current token for a type and/or a value. * - * @param array|int $type The type to test + * @param string $type The type to test * @param string|null $value The token value * * @return bool diff --git a/advancedcontentfilter/vendor/symfony/expression-language/TokenStream.php b/advancedcontentfilter/vendor/symfony/expression-language/TokenStream.php index 9096b183f..09d3854e8 100644 --- a/advancedcontentfilter/vendor/symfony/expression-language/TokenStream.php +++ b/advancedcontentfilter/vendor/symfony/expression-language/TokenStream.php @@ -53,7 +53,7 @@ class TokenStream ++$this->position; if (!isset($this->tokens[$this->position])) { - throw new SyntaxError('Unexpected end of expression', $this->current->cursor, $this->expression); + throw new SyntaxError('Unexpected end of expression.', $this->current->cursor, $this->expression); } $this->current = $this->tokens[$this->position]; @@ -70,7 +70,7 @@ class TokenStream { $token = $this->current; if (!$token->test($type, $value)) { - throw new SyntaxError(sprintf('%sUnexpected token "%s" of value "%s" ("%s" expected%s)', $message ? $message.'. ' : '', $token->type, $token->value, $type, $value ? sprintf(' with value "%s"', $value) : ''), $token->cursor, $this->expression); + throw new SyntaxError(sprintf('%sUnexpected token "%s" of value "%s" ("%s" expected%s).', $message ? $message.'. ' : '', $token->type, $token->value, $type, $value ? sprintf(' with value "%s"', $value) : ''), $token->cursor, $this->expression); } $this->next(); } diff --git a/advancedcontentfilter/vendor/symfony/expression-language/composer.json b/advancedcontentfilter/vendor/symfony/expression-language/composer.json index 5f662ffd3..5d5825b9a 100644 --- a/advancedcontentfilter/vendor/symfony/expression-language/composer.json +++ b/advancedcontentfilter/vendor/symfony/expression-language/composer.json @@ -17,7 +17,8 @@ ], "require": { "php": "^5.5.9|>=7.0.8", - "symfony/cache": "~3.1|~4.0" + "symfony/cache": "~3.1|~4.0", + "symfony/polyfill-php70": "~1.6" }, "autoload": { "psr-4": { "Symfony\\Component\\ExpressionLanguage\\": "" }, @@ -25,10 +26,5 @@ "/Tests/" ] }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - } + "minimum-stability": "dev" } diff --git a/advancedcontentfilter/vendor/symfony/expression-language/phpunit.xml.dist b/advancedcontentfilter/vendor/symfony/expression-language/phpunit.xml.dist index 517322fb4..ae84dcd94 100644 --- a/advancedcontentfilter/vendor/symfony/expression-language/phpunit.xml.dist +++ b/advancedcontentfilter/vendor/symfony/expression-language/phpunit.xml.dist @@ -1,7 +1,7 @@ $v) { if (!apc_add($k, $v, $ttl)) { $errors[$k] = -1; @@ -39,11 +39,11 @@ final class Apcu public static function apcu_store($key, $var = null, $ttl = 0) { - if (!is_array($key)) { + if (!\is_array($key)) { return apc_store($key, $var, $ttl); } - $errors = array(); + $errors = []; foreach ($key as $k => $v) { if (!apc_store($k, $v, $ttl)) { $errors[$k] = -1; @@ -55,11 +55,11 @@ final class Apcu public static function apcu_exists($keys) { - if (!is_array($keys)) { + if (!\is_array($keys)) { return apc_exists($keys); } - $existing = array(); + $existing = []; foreach ($keys as $k) { if (apc_exists($k)) { $existing[$k] = true; @@ -71,12 +71,12 @@ final class Apcu public static function apcu_fetch($key, &$success = null) { - if (!is_array($key)) { + if (!\is_array($key)) { return apc_fetch($key, $success); } $succeeded = true; - $values = array(); + $values = []; foreach ($key as $k) { $v = apc_fetch($k, $success); if ($success) { @@ -92,7 +92,7 @@ final class Apcu public static function apcu_delete($key) { - if (!is_array($key)) { + if (!\is_array($key)) { return apc_delete($key); } diff --git a/advancedcontentfilter/vendor/symfony/polyfill-apcu/LICENSE b/advancedcontentfilter/vendor/symfony/polyfill-apcu/LICENSE index 24fa32c2e..6e3afce69 100644 --- a/advancedcontentfilter/vendor/symfony/polyfill-apcu/LICENSE +++ b/advancedcontentfilter/vendor/symfony/polyfill-apcu/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2015-2018 Fabien Potencier +Copyright (c) 2015-present Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/advancedcontentfilter/vendor/symfony/polyfill-apcu/README.md b/advancedcontentfilter/vendor/symfony/polyfill-apcu/README.md index e614bcab5..57f4bf6bb 100644 --- a/advancedcontentfilter/vendor/symfony/polyfill-apcu/README.md +++ b/advancedcontentfilter/vendor/symfony/polyfill-apcu/README.md @@ -1,10 +1,10 @@ Symfony Polyfill / APCu ======================== -This component provides `apcu_*` functions and the `APCUIterator` class to users of the legacy APC extension. +This component provides `apcu_*` functions and the `APCuIterator` class to users of the legacy APC extension. More information can be found in the -[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md). +[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md). License ======= diff --git a/advancedcontentfilter/vendor/symfony/polyfill-apcu/bootstrap.php b/advancedcontentfilter/vendor/symfony/polyfill-apcu/bootstrap.php index 305183b6a..96b2706ad 100644 --- a/advancedcontentfilter/vendor/symfony/polyfill-apcu/bootstrap.php +++ b/advancedcontentfilter/vendor/symfony/polyfill-apcu/bootstrap.php @@ -15,32 +15,67 @@ if (!extension_loaded('apc') && !extension_loaded('apcu')) { return; } -if (!function_exists('apcu_add')) { - if (extension_loaded('Zend Data Cache')) { - function apcu_add($key, $var = null, $ttl = 0) { return p\Apcu::apcu_add($key, $var, $ttl); } - function apcu_delete($key) { return p\Apcu::apcu_delete($key); } - function apcu_exists($keys) { return p\Apcu::apcu_exists($keys); } - function apcu_fetch($key, &$success = null) { return p\Apcu::apcu_fetch($key, $success); } - function apcu_store($key, $var = null, $ttl = 0) { return p\Apcu::apcu_store($key, $var, $ttl); } - } else { - function apcu_add($key, $var = null, $ttl = 0) { return apc_add($key, $var, $ttl); } - function apcu_delete($key) { return apc_delete($key); } - function apcu_exists($keys) { return apc_exists($keys); } - function apcu_fetch($key, &$success = null) { return apc_fetch($key, $success); } - function apcu_store($key, $var = null, $ttl = 0) { return apc_store($key, $var, $ttl); } +if (\PHP_VERSION_ID >= 80000) { + return require __DIR__.'/bootstrap80.php'; +} + +if (extension_loaded('Zend Data Cache')) { + if (!function_exists('apcu_add')) { + function apcu_add($key, $value = null, $ttl = 0) { return p\Apcu::apcu_add($key, $value, $ttl); } } + if (!function_exists('apcu_delete')) { + function apcu_delete($key) { return p\Apcu::apcu_delete($key); } + } + if (!function_exists('apcu_exists')) { + function apcu_exists($key) { return p\Apcu::apcu_exists($key); } + } + if (!function_exists('apcu_fetch')) { + function apcu_fetch($key, &$success = null) { return p\Apcu::apcu_fetch($key, $success); } + } + if (!function_exists('apcu_store')) { + function apcu_store($key, $value = null, $ttl = 0) { return p\Apcu::apcu_store($key, $value, $ttl); } + } +} else { + if (!function_exists('apcu_add')) { + function apcu_add($key, $value = null, $ttl = 0) { return apc_add($key, $value, $ttl); } + } + if (!function_exists('apcu_delete')) { + function apcu_delete($key) { return apc_delete($key); } + } + if (!function_exists('apcu_exists')) { + function apcu_exists($key) { return apc_exists($key); } + } + if (!function_exists('apcu_fetch')) { + function apcu_fetch($key, &$success = null) { return apc_fetch($key, $success); } + } + if (!function_exists('apcu_store')) { + function apcu_store($key, $value = null, $ttl = 0) { return apc_store($key, $value, $ttl); } + } +} + +if (!function_exists('apcu_cache_info')) { function apcu_cache_info($limited = false) { return apc_cache_info('user', $limited); } +} +if (!function_exists('apcu_cas')) { function apcu_cas($key, $old, $new) { return apc_cas($key, $old, $new); } +} +if (!function_exists('apcu_clear_cache')) { function apcu_clear_cache() { return apc_clear_cache('user'); } +} +if (!function_exists('apcu_dec')) { function apcu_dec($key, $step = 1, &$success = false) { return apc_dec($key, $step, $success); } +} +if (!function_exists('apcu_inc')) { function apcu_inc($key, $step = 1, &$success = false) { return apc_inc($key, $step, $success); } +} +if (!function_exists('apcu_sma_info')) { function apcu_sma_info($limited = false) { return apc_sma_info($limited); } } -if (!class_exists('APCUIterator', false) && class_exists('APCIterator', false)) { - class APCUIterator extends APCIterator +if (!class_exists('APCuIterator', false) && class_exists('APCIterator', false)) { + class APCuIterator extends APCIterator { - public function __construct($search = null, $format = APC_ITER_ALL, $chunk_size = 100, $list = APC_LIST_ACTIVE) + public function __construct($search = null, $format = \APC_ITER_ALL, $chunk_size = 100, $list = \APC_LIST_ACTIVE) { parent::__construct('user', $search, $format, $chunk_size, $list); } diff --git a/advancedcontentfilter/vendor/symfony/polyfill-apcu/bootstrap80.php b/advancedcontentfilter/vendor/symfony/polyfill-apcu/bootstrap80.php new file mode 100644 index 000000000..69e9f1603 --- /dev/null +++ b/advancedcontentfilter/vendor/symfony/polyfill-apcu/bootstrap80.php @@ -0,0 +1,75 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Apcu as p; + +if (extension_loaded('Zend Data Cache')) { + if (!function_exists('apcu_add')) { + function apcu_add($key, mixed $value, ?int $ttl = 0): array|bool { return p\Apcu::apcu_add($key, $value, (int) $ttl); } + } + if (!function_exists('apcu_delete')) { + function apcu_delete($key): array|bool { return p\Apcu::apcu_delete($key); } + } + if (!function_exists('apcu_exists')) { + function apcu_exists($key): array|bool { return p\Apcu::apcu_exists($key); } + } + if (!function_exists('apcu_fetch')) { + function apcu_fetch($key, &$success = null): mixed { return p\Apcu::apcu_fetch($key, $success); } + } + if (!function_exists('apcu_store')) { + function apcu_store($key, mixed $value, ?int $ttl = 0): array|bool { return p\Apcu::apcu_store($key, $value, (int) $ttl); } + } +} else { + if (!function_exists('apcu_add')) { + function apcu_add($key, mixed $value, ?int $ttl = 0): array|bool { return apc_add($key, $value, (int) $ttl); } + } + if (!function_exists('apcu_delete')) { + function apcu_delete($key): array|bool { return apc_delete($key); } + } + if (!function_exists('apcu_exists')) { + function apcu_exists($key): array|bool { return apc_exists($key); } + } + if (!function_exists('apcu_fetch')) { + function apcu_fetch($key, &$success = null) { return apc_fetch($key, $success); } + } + if (!function_exists('apcu_store')) { + function apcu_store($key, mixed $value, ?int $ttl = 0): array|bool { return apc_store($key, $value, (int) $ttl); } + } +} + +if (!function_exists('apcu_cache_info')) { + function apcu_cache_info($limited = false) { return apc_cache_info('user', $limited); } +} +if (!function_exists('apcu_cas')) { + function apcu_cas($key, $old, $new) { return apc_cas($key, $old, $new); } +} +if (!function_exists('apcu_clear_cache')) { + function apcu_clear_cache() { return apc_clear_cache('user'); } +} +if (!function_exists('apcu_dec')) { + function apcu_dec($key, $step = 1, &$success = false) { return apc_dec($key, $step, $success); } +} +if (!function_exists('apcu_inc')) { + function apcu_inc($key, $step = 1, &$success = false) { return apc_inc($key, $step, $success); } +} +if (!function_exists('apcu_sma_info')) { + function apcu_sma_info($limited = false) { return apc_sma_info($limited); } +} + +if (!class_exists('APCuIterator', false) && class_exists('APCIterator', false)) { + class APCuIterator extends APCIterator + { + public function __construct($search = null, $format = APC_ITER_ALL, $chunk_size = 100, $list = APC_LIST_ACTIVE) + { + parent::__construct('user', $search, $format, $chunk_size, $list); + } + } +} diff --git a/advancedcontentfilter/vendor/symfony/polyfill-apcu/composer.json b/advancedcontentfilter/vendor/symfony/polyfill-apcu/composer.json index 54ea2b857..e92524f3b 100644 --- a/advancedcontentfilter/vendor/symfony/polyfill-apcu/composer.json +++ b/advancedcontentfilter/vendor/symfony/polyfill-apcu/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.3.3" + "php": ">=7.1" }, "autoload": { "psr-4": { "Symfony\\Polyfill\\Apcu\\": "" }, @@ -25,7 +25,11 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "1.7-dev" + "dev-main": "1.28-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } } } From 8b35c9fddba1cd7695a33ce4d9aa5e2d9dd312b2 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 22 Jan 2024 18:01:51 +0000 Subject: [PATCH 102/388] Tesseract: Improved detection --- tesseract/tesseract.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tesseract/tesseract.php b/tesseract/tesseract.php index 3c61273f2..b3e1feb68 100644 --- a/tesseract/tesseract.php +++ b/tesseract/tesseract.php @@ -24,6 +24,10 @@ function tesseract_ocr_detection(&$media) { $ocr = new TesseractOCR(); try { + $languages = $ocr->availableLanguages(); + if ($languages) { + $ocr->lang(implode('+', $languages)); + } $ocr->tempDir(System::getTempPath()); $ocr->imageData($media['img_str'], strlen($media['img_str'])); $media['description'] = $ocr->run(); From c9f985d8424c3410cf85b9636ad4d3df2ea2c8a7 Mon Sep 17 00:00:00 2001 From: Hannes Heute Date: Fri, 2 Feb 2024 14:08:06 +0100 Subject: [PATCH 103/388] remove .php from openstreetmap server in config to fix created links --- openstreetmap/config/openstreetmap.config.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openstreetmap/config/openstreetmap.config.php b/openstreetmap/config/openstreetmap.config.php index c649da5f3..d633fd26e 100644 --- a/openstreetmap/config/openstreetmap.config.php +++ b/openstreetmap/config/openstreetmap.config.php @@ -10,7 +10,7 @@ return [ 'tmsserver' => 'https://www.openstreetmap.org', // nomserver (String) - 'nomserver' => 'https://nominatim.openstreetmap.org/search.php', + 'nomserver' => 'https://nominatim.openstreetmap.org/search', // zoom (Integer) // The default zoom level on the map. From 84fc5ba9220f393d75ad0cb110260e458082ae0b Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 10 Feb 2024 12:00:36 +0000 Subject: [PATCH 104/388] Markdown: Avoid problems with [*] BBCode element --- markdown/markdown.php | 1 + 1 file changed, 1 insertion(+) diff --git a/markdown/markdown.php b/markdown/markdown.php index 236fb297f..6f4592445 100644 --- a/markdown/markdown.php +++ b/markdown/markdown.php @@ -64,6 +64,7 @@ function markdown_post_local_start(&$request) { // (right chevrons are used for quoting in Markdown) // See https://github.com/friendica/friendica/issues/10634 $text = strtr($text, ['<' => '<']); + $text = str_replace('[*]', '[li]', $text); return Markdown::toBBCode($text); }); From f678468d429b597ce5ff42d6979fc8aa370d8fe8 Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 16 Feb 2024 02:29:12 +0000 Subject: [PATCH 105/388] Bluesky/Twitter: New parameter added for rhe picture creation --- bluesky/bluesky.php | 2 +- twitter/twitter.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index a2c85ad37..fe1faab18 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -896,7 +896,7 @@ function bluesky_upload_blob(int $uid, array $photo): ?stdClass $retrial = Worker::getRetrial(); $content = Photo::getImageForPhoto($photo); - $picture = new Image($content, $photo['type']); + $picture = new Image($content, $photo['type'], $photo['filename']); $height = $picture->getHeight(); $width = $picture->getWidth(); $size = strlen($content); diff --git a/twitter/twitter.php b/twitter/twitter.php index b01345b74..11c163efc 100644 --- a/twitter/twitter.php +++ b/twitter/twitter.php @@ -308,7 +308,7 @@ function twitter_upload_image(int $uid, array $image, int $retrial) $picturedata = Photo::getImageForPhoto($photo); - $picture = new Image($picturedata, $photo['type']); + $picture = new Image($picturedata, $photo['type'], $photo['filename']); $height = $picture->getHeight(); $width = $picture->getWidth(); $size = strlen($picturedata); From 9208fd46a4afefd9c2789bd866585e29f425705b Mon Sep 17 00:00:00 2001 From: Morgan McMillian Date: Tue, 20 Feb 2024 17:53:21 -0800 Subject: [PATCH 106/388] Pnut: add connector for pnut.io --- pnut/LICENSE | 662 +++++++ pnut/README.md | 5 + pnut/lib/LICENSE | 24 + pnut/lib/phpnut.php | 2504 +++++++++++++++++++++++++ pnut/lib/phpnutException.php | 5 + pnut/pnut.php | 293 +++ pnut/pnut.svg | 1 + pnut/templates/connector_settings.tpl | 12 + 8 files changed, 3506 insertions(+) create mode 100644 pnut/LICENSE create mode 100644 pnut/README.md create mode 100644 pnut/lib/LICENSE create mode 100644 pnut/lib/phpnut.php create mode 100644 pnut/lib/phpnutException.php create mode 100644 pnut/pnut.php create mode 100644 pnut/pnut.svg create mode 100644 pnut/templates/connector_settings.tpl diff --git a/pnut/LICENSE b/pnut/LICENSE new file mode 100644 index 000000000..fe6b9036b --- /dev/null +++ b/pnut/LICENSE @@ -0,0 +1,662 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 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 Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are 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. + + 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. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + 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 Affero 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. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + 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 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 work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero 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 Affero 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 Affero 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 Affero 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. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state 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 program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. + diff --git a/pnut/README.md b/pnut/README.md new file mode 100644 index 000000000..d935efe7f --- /dev/null +++ b/pnut/README.md @@ -0,0 +1,5 @@ +# Pnut connector + +With this addon to friendica you can give your users the possibility to post their *public* messages to pnut.io. + +No setup is needed for the admins to make it work for their users. diff --git a/pnut/lib/LICENSE b/pnut/lib/LICENSE new file mode 100644 index 000000000..579599a8b --- /dev/null +++ b/pnut/lib/LICENSE @@ -0,0 +1,24 @@ +Copyright (c) 2013, Josh Dolitsky +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Josh Dolitsky nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL TRAVIS RICHARDSON BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/pnut/lib/phpnut.php b/pnut/lib/phpnut.php new file mode 100644 index 000000000..303a860b3 --- /dev/null +++ b/pnut/lib/phpnut.php @@ -0,0 +1,2504 @@ +_clientId = $client_id_or_token; + $this->_clientSecret = $client_secret; + } else { + $this->_accessToken = $client_id_or_token; + } + + // if the digicert certificate exists in the same folder as this file, + // remember that fact for later + if (file_exists(__DIR__ . '/DigiCertHighAssuranceEVRootCA.pem')) { + $this->_sslCA = __DIR__ . '/DigiCertHighAssuranceEVRootCA.pem'; + } + } + + /** + * Set whether or not to strip Envelope Response (meta) information + * This option will be deprecated in the future. Is it to allow + * a stepped migration path between code expecting the old behavior + * and new behavior. When not stripped, you still can use the proper + * method to pull the meta information. Please start converting your code ASAP + */ + public function includeResponseEnvelope(): void + { + $this->_stripResponseEnvelope = false; + } + + /** + * Construct the proper Auth URL for the user to visit and either grant + * or not access to your app. Usually you would place this as a link for + * the user to client, or a redirect to send them to the auth URL. + * Also can be called after authentication for additional scopes + * @param string $callbackUri Where you want the user to be directed + * after authenticating with pnut.io. This must be one of the URIs + * allowed by your pnut.io application settings. + * @param array $scope An array of scopes (permissions) you wish to obtain + * from the user. If you don't specify anything, you'll only receive + * access to the user's basic profile (the default). + */ + public function getAuthUrl(?string $callback_uri=null, array|string|null $scope=null): string + { + if (empty($this->_clientId)) { + throw new phpnutException('You must specify your pnut client ID'); + } + + if (is_null($callback_uri)) { + if (defined('PNUT_REDIRECT_URI')) { + $callback_uri = PNUT_REDIRECT_URI; + } elseif (isset($_ENV['PNUT_REDIRECT_URI'])) { + $callback_uri = $_ENV['PNUT_REDIRECT_URI']; + } else { + throw new phpnutException('You must specify your pnut callback URI'); + } + } + + if (is_null($scope)) { + if (defined('PNUT_APP_SCOPE')) { + $scope = PNUT_APP_SCOPE; + } elseif (isset($_ENV['PNUT_APP_SCOPE'])) { + $scope = $_ENV['PNUT_APP_SCOPE']; + } else { + $scope = 'basic'; + } + } + + if (is_array($scope)) { + $scope = implode(',', $scope); + } + + // construct an authorization url based on our client id and other data + $data = [ + 'client_id'=>$this->_clientId, + 'response_type'=>'code', + 'redirect_uri'=>$callback_uri, + 'scope'=>$scope, + ]; + + $url = $this->_authUrl; + if ($this->_accessToken) { + $url .= 'authorize?'; + } else { + $url .= 'authenticate?'; + } + $url .= $this->buildQueryString($data); + + // return the constructed url + return $url; + } + + /** + * Call this after they return from the auth page, or anytime you need the + * token. For example, you could store it in a database and use + * setAccessToken() later on to return on behalf of the user. + */ + public function getAccessToken(string $callback_uri) + { + // if there's no access token set, and they're returning from + // the auth page with a code, use the code to get a token + if (!$this->_accessToken && isset($_GET['code']) && $_GET['code'] !== '') { + + if (empty($this->_clientId) || empty($this->_clientSecret)) { + throw new phpnutException('You must specify your Pnut client ID and client secret'); + } + + // construct the necessary elements to get a token + $data = [ + 'client_id'=>$this->_clientId, + 'client_secret'=>$this->_clientSecret, + 'grant_type'=>'authorization_code', + 'redirect_uri'=>$callback_uri, + 'code'=>$_GET['code'], + ]; + + // try and fetch the token with the above data + $res = $this->httpReq( + 'post', + "{$this->_baseUrl}oauth/access_token", + $data + ); + + // store it for later + $this->_accessToken = $res['access_token']; + $this->_username = $res['username']; + $this->_user_id = $res['user_id']; + } + + // return what we have (this may be a token, or it may be nothing) + return $this->_accessToken; + } + + /** + * Check the scope of current token to see if it has required scopes + * has to be done after a check + */ + public function checkScopes(array $app_scopes): int|array + { + if (count($this->_scopes) === 0) { + return -1; // _scope is empty + } + $missing = []; + foreach($app_scopes as $scope) { + if (!in_array($scope, $this->_scopes)) { + if ($scope === 'public_messages') { + // messages works for public_messages + if (in_array('messages', $this->_scopes)) { + // if we have messages in our scopes + continue; + } + } + $missing[] = $scope; + } + } + // identify the ones missing + if (count($missing) !== 0) { + // do something + return $missing; + } + return 0; // 0 missing + } + + /** + * Set the access token (eg: after retrieving it from offline storage) + * @param string $token A valid access token you're previously received + * from calling getAccessToken(). + */ + public function setAccessToken(?string $token=null): void + { + $this->_accessToken = $token; + } + + /** + * Deauthorize the current token (delete your authorization from the API) + * Generally this is useful for logging users out from a web app, so they + * don't get automatically logged back in the next time you redirect them + * to the authorization URL. + */ + public function deauthorizeToken() + { + return $this->httpReq('delete', "{$this->_baseUrl}token"); + } + + /** + * Retrieve an app access token from the app.net API. This allows you + * to access the API without going through the user access flow if you + * just want to (eg) consume global. App access tokens are required for + * some actions (like streaming global). DO NOT share the return value + * of this function with any user (or save it in a cookie, etc). This + * is considered secret info for your app only. + * @return string The app access token + */ + public function getAppAccessToken() + { + if (empty($this->_clientId) || empty($this->_clientSecret)) { + throw new phpnutException('You must specify your Pnut client ID and client secret'); + } + + // construct the necessary elements to get a token + $data = [ + 'client_id'=>$this->_clientId, + 'client_secret'=>$this->_clientSecret, + 'grant_type'=>'client_credentials', + ]; + // try and fetch the token with the above data + $res = $this->httpReq( + 'post', + "{$this->_baseUrl}oauth/access_token", + $data + ); + // store it for later + $this->_appAccessToken = $res['access_token']; + $this->_accessToken = $res['access_token']; + $this->_username = null; + $this->_user_id = null; + return $this->_accessToken; + } + + /** + * Returns the total number of requests you're allowed within the + * alloted time period. + * @see getRateLimitReset() + */ + public function getRateLimit() + { + return $this->_rateLimit; + } + + /** + * The number of requests you have remaining within the alloted time period + * @see getRateLimitReset() + */ + public function getRateLimitRemaining() + { + return $this->_rateLimitRemaining; + } + + /** + * The number of seconds remaining in the alloted time period. + * When this time is up you'll have getRateLimit() available again. + */ + public function getRateLimitReset() + { + return $this->_rateLimitReset; + } + + /** + * The scope the user has + */ + public function getScope() + { + return $this->_scope; + } + + /** + * Internal function, parses out important information pnut.io adds + * to the headers. + */ + protected function parseHeaders(string $response) + { + // take out the headers + // set internal variables + // return the body/content + $this->_rateLimit = null; + $this->_rateLimitRemaining = null; + $this->_rateLimitReset = null; + $this->_scope = null; + + $response = explode("\r\n\r\n", $response, 2); + $headers = $response[0]; + + if ($headers === 'HTTP/1.1 100 Continue') { + $response = explode("\r\n\r\n", $response[1], 2); + $headers = $response[0]; + } + + // this is not a good way to parse http headers + // it will not (for example) take into account multiline headers + // but what we're looking for is pretty basic, so we can ignore those shortcomings + $headers = explode("\r\n", $headers); + foreach ($headers as $header) { + $header = explode(': ', $header, 2); + if (count($header) < 2) { + continue; + } + list($k, $v) = $header; + switch ($k) { + case 'X-RateLimit-Remaining': + $this->_rateLimitRemaining = $v; + break; + case 'X-RateLimit-Limit': + $this->_rateLimit = $v; + break; + case 'X-RateLimit-Reset': + $this->_rateLimitReset = $v; + break; + case 'X-OAuth-Scopes': + $this->_scope = $v; + $this->_scopes = explode(',', $v); + break; + } + } + return $response[1] ?? null; + } + + /** + * Internal function. Used to turn things like TRUE into 1, and then + * calls http_build_query. + */ + protected function buildQueryString(array $array): string + { + foreach ($array as $k => &$v) { + if (is_array($v)) { + $v = implode(',', $v); + } elseif ($v === true) { + $v = '1'; + } + elseif ($v === false) { + $v = '0'; + } + unset($v); + } + return http_build_query($array); + } + + + /** + * Internal function to handle all + * HTTP requests (POST,PUT,GET,DELETE) + */ + protected function httpReq(string $act, string $req, string|array $params=[], string $contentType='application/x-www-form-urlencoded') + { + $ch = curl_init($req); + $headers = []; + if($act !== 'get') { + curl_setopt($ch, CURLOPT_POST, true); + // if they passed an array, build a list of parameters from it + if (is_array($params) && $act !== 'post-raw') { + $params = $this->buildQueryString($params); + } + curl_setopt($ch, CURLOPT_POSTFIELDS, $params); + $headers[] = "Content-Type: {$contentType}"; + } + if($act !== 'post' && $act !== 'post-raw') { + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, strtoupper($act)); + } + if($act === 'get' && isset($params['access_token'])) { + $headers[] = "Authorization: Bearer {$params['access_token']}"; + } elseif ($this->_accessToken) { + $headers[] = "Authorization: Bearer {$this->_accessToken}"; + } + curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLINFO_HEADER_OUT, true); + curl_setopt($ch, CURLOPT_HEADER, true); + if ($this->_sslCA) { + curl_setopt($ch, CURLOPT_CAINFO, $this->_sslCA); + } + $this->_last_response = curl_exec($ch); + $this->_last_request = curl_getinfo($ch, CURLINFO_HEADER_OUT); + $http_status = curl_getinfo($ch, CURLINFO_HTTP_CODE); + curl_close($ch); + + if ($http_status === 0) { + throw new phpnutException("Unable to connect to {$req}"); + } + if ($this->_last_request === false) { + if (!curl_getinfo($ch, CURLINFO_SSL_VERIFYRESULT)) { + throw new phpnutException('SSL verification failed, connection terminated.'); + } + } + if ($this->_last_response) { + $response = $this->parseHeaders($this->_last_response); + if ($response) { + $response = json_decode($response, true); + + if (isset($response['meta'])) { + if (isset($response['meta']['max_id'])) { + $this->_maxid = $response['meta']['max_id']; + $this->_minid = $response['meta']['min_id']; + } + if (isset($response['meta']['more'])) { + $this->_more = $response['meta']['more']; + } + if (isset($response['meta']['marker'])) { + $this->_last_marker = $response['meta']['marker']; + } + } + + // look for errors + if (isset($response['error'])) { + if (is_array($response['error'])) { + throw new phpnutException( + $response['error']['message'], + $response['error']['code'] + ); + } else { + throw new phpnutException($response['error']); + } + } + + // look for response migration errors + elseif (isset($response['meta'], $response['meta']['error_message'])) { + throw new phpnutException( + $response['meta']['error_message'], + $response['meta']['code'] + ); + } + } + } + + if ($http_status < 200 || $http_status >= 300) { + throw new phpnutException("HTTP error {$http_status}"); + } + + // if we've received a migration response, handle it and return data only + elseif ($this->_stripResponseEnvelope && isset($response['meta'], $response['data'])) { + return $response['data']; + } + + // else non response migration response, just return it + elseif (isset($response)) { + return $response; + } + + else { + throw new phpnutException('No response'); + } + } + + + /** + * Get max_id from last meta response data envelope + */ + public function getResponseMaxID() + { + return $this->_maxid; + } + + /** + * Get min_id from last meta response data envelope + */ + public function getResponseMinID() + { + return $this->_minid; + } + + /** + * Get more from last meta response data envelope + */ + public function getResponseMore() + { + return $this->_more; + } + + /** + * Get marker from last meta response data envelope + */ + public function getResponseMarker() + { + return $this->_last_marker; + } + + public function getLastRequest() + { + return $this->_last_request; + } + + public function getLastResponse() + { + return $this->_last_response; + } + + /** + * Fetch API configuration object + * @return array + */ + public function getConfig() + { + return $this->httpReq('get', "{$this->_baseUrl}sys/config"); + } + + /** + * Fetch basic API statistics + * @return array + */ + public function getStats() + { + return $this->httpReq('get', "{$this->_baseUrl}sys/stats"); + } + + /** + * Process user content, message or post text. + * Mentions and hashtags will be parsed out of the + * text, as will bare URLs. To create a link in the text without using a + * bare URL, include the anchor text in the object text and include a link + * entity in the function call. + * @param string $text The text of the user/message/post + * @param array $data An associative array of optional post data. This + * will likely change as the API evolves, as of this writing allowed keys are: + * reply_to, and raw. "raw" may be a complex object represented + * by an associative array. + * @param array $params An associative array of optional data to be included + * in the URL (such as 'include_raw') + * @return array An associative array representing the post. + */ + public function processText(string $text, array $data=[], array $params=[]) + { + $data['text'] = $text; + $json = json_encode($data); + $qs = ''; + if (!empty($params)) { + $qs = '?' . $this->buildQueryString($params); + } + return $this->httpReq( + 'post', + $this->_baseUrl . 'text/process' . $qs, + $json, + 'application/json' + ); + } + + /** + * Create a new Post object. Mentions and hashtags will be parsed out of the + * post text, as will bare URLs. To create a link in a post without using a + * bare URL, include the anchor text in the post's text and include a link + * entity in the post creation call. + * @param string $text The text of the post + * @param array $data An associative array of optional post data. This + * will likely change as the API evolves, as of this writing allowed keys are: + * reply_to, is_nsfw, and raw. "raw" may be a complex object represented + * by an associative array. + * @param array $params An associative array of optional data to be included + * in the URL (such as 'include_raw') + * @return array An associative array representing the post. + */ + public function createPost(string $text, array $data=[], array $params=[]) + { + $data['text'] = $text; + $json = json_encode($data); + $qs = ''; + if (!empty($params)) { + $qs = '?' . $this->buildQueryString($params); + } + return $this->httpReq( + 'post', + $this->_baseUrl . 'posts' . $qs, + $json, + 'application/json' + ); + } + + /** + * Create a new Post object. Mentions and hashtags will be parsed out of the + * post text, as will bare URLs. To create a link in a post without using a + * bare URL, include the anchor text in the post's text and include a link + * entity in the post creation call. + * @param integer $post_id The ID of the post to revise + * @param string $text The new text of the post + * @param array $data An associative array of optional post data. This + * will likely change as the API evolves, as of this writing allowed keys are: + * is_nsfw. + * @param array $params An associative array of optional data to be included + * in the URL (such as 'include_raw') + * @return array An associative array representing the post. + */ + public function revisePost(int $post_id, string $text, array $data=[], array $params=[]) + { + $data['text'] = $text; + $json = json_encode($data); + $qs = ''; + if (!empty($params)) { + $qs = '?' . $this->buildQueryString($params); + } + return $this->httpReq( + 'put', + $this->_baseUrl . 'posts/' . urlencode($post_id) . $qs, + $json, + 'application/json' + ); + } + + /** + * Returns a specific Post. + * @param integer $post_id The ID of the post to retrieve + * @param array $params An associative array of optional general parameters. + * @return array An associative array representing the post + */ + public function getPost(int $post_id, array $params=[]) + { + return $this->httpReq( + 'get', + $this->_baseUrl . 'posts/' . urlencode($post_id) . '?' + . $this->buildQueryString($params) + ); + } + + /** + * Returns a list of Posts. + * @param array $post_ids The list of post IDs to retrieve + * @param array $params An associative array of optional general parameters. + * @return array An array of arrays representing the posts + */ + public function getMultiplePosts(array $post_ids, array $params=[]) + { + $params['ids'] = $post_ids; + + return $this->httpReq( + 'get', + $this->_baseUrl . 'posts?' . $this->buildQueryString($params) + ); + } + + /** + * Delete a Post. The current user must be the same user who created the Post. + * It returns the deleted Post on success. + * @param integer $post_id The ID of the post to delete + * @param array An associative array representing the post that was deleted + */ + public function deletePost(int $post_id) + { + return $this->httpReq( + 'delete', + $this->_baseUrl . 'posts/' . urlencode($post_id) + ); + } + + /** + * Retrieve the Posts that are 'in reply to' a specific Post. + * @param integer $post_id The ID of the post you want to retrieve replies for. + * @param array $params An associative array of optional general parameters. + * @return An array of associative arrays, each representing a single post. + */ + public function getPostThread(int $post_id, array $params=[]) + { + return $this->httpReq( + 'get', + $this->_baseUrl . 'posts/' . urlencode($post_id) . '/thread?' + . $this->buildQueryString($params) + ); + } + + /** + * Retrieve revisions of a post. Currently only one can be created. + * @param integer $post_id The ID of the post you want to retrieve previous revisions of. + * @param array $params An associative array of optional general parameters. + * @return An array of associative arrays, each representing a single post. + */ + public function getPostRevisions(int $post_id, array $params=[]) + { + return $this->httpReq( + 'get', + $this->_baseUrl . 'posts/' . urlencode($post_id) . '/revisions?' + . $this->buildQueryString($params) + ); + } + + /** + * Get the most recent Posts created by a specific User in reverse + * chronological order (most recent first). + * @param mixed $user_id Either the ID of the user you wish to retrieve posts by, + * or the string "me", which will retrieve posts for the user you're authenticated + * as. + * @param array $params An associative array of optional general parameters. + * @return An array of associative arrays, each representing a single post. + */ + public function getUserPosts(string|int $user_id='me', array $params=[]) + { + return $this->httpReq( + 'get', + $this->_baseUrl . 'users/' . urlencode($user_id) . '/posts?' + . $this->buildQueryString($params) + ); + } + + /** + * Get the most recent Posts mentioning by a specific User in reverse + * chronological order (newest first). + * @param mixed $user_id Either the ID of the user who is being mentioned, or + * the string "me", which will retrieve posts for the user you're authenticated + * as. + * @param array $params An associative array of optional general parameters. + * @return An array of associative arrays, each representing a single post. + */ + public function getUserMentions(string|int $user_id='me', array $params=[]) + { + return $this->httpReq( + 'get', + $this->_baseUrl . 'users/' . urlencode($user_id) . '/mentions?' + . $this->buildQueryString($params) + ); + } + + /** + * Get the currently authenticated user's recent messages + * @param array $params An associative array of optional general parameters. + * @return An array of associative arrays, each representing a single post. + */ + public function getUserMessages(array $params=[]) + { + return $this->httpReq( + 'get', + $this->_baseUrl . 'users/me/messages?' + . $this->buildQueryString($params) + ); + } + + /** + * Return the 20 most recent posts from the current User and + * the Users they follow. + * @param array $params An associative array of optional general parameters. + * @return An array of associative arrays, each representing a single post. + */ + public function getUserStream(array $params=[]) + { + return $this->httpReq( + 'get', + $this->_baseUrl . 'posts/streams/me?' + . $this->buildQueryString($params) + ); + } + + /** + * Retrieve a list of all public Posts on pnut.io, often referred to as the + * global stream. + * @param array $params An associative array of optional general parameters. + * @return An array of associative arrays, each representing a single post. + */ + public function getPublicPosts(array $params=[]) + { + return $this->httpReq( + 'get', + $this->_baseUrl . 'posts/streams/global?' + . $this->buildQueryString($params) + ); + } + + /** + * Retrieve a list of "explore" streams + * @return An array of associative arrays, each representing a single explore stream. + */ + public function getPostExploreStreams() + { + return $this->httpReq( + 'get', + $this->_baseUrl . 'posts/streams/explore' + ); + } + + /** + * Retrieve a list of posts from an "explore" stream on pnut.io. + * @param string $slug [] + * @param array $params An associative array of optional general parameters. + * @return An array of associative arrays, each representing a single post. + */ + public function getPostExploreStream(string $slug, array $params=[]) + { + return $this->httpReq( + 'get', + $this->_baseUrl . 'posts/streams/explore/' . urlencode($slug) . '?' + . $this->buildQueryString($params) + ); + } + + /** + * Bookmark a post + * @param integer $post_id The post ID to bookmark + */ + public function bookmarkPost(int $post_id) + { + return $this->httpReq( + 'put', + $this->_baseUrl . 'posts/' . urlencode($post_id) . '/bookmark' + ); + } + + /** + * Unbookmark a post + * @param integer $post_id The post ID to unbookmark + */ + public function unbookmarkPost(int $post_id) + { + return $this->httpReq( + 'delete', + $this->_baseUrl . 'posts/' . urlencode($post_id) . '/bookmark' + ); + } + + /** + * List the posts bookmarked by the current user + * @param array $params An associative array of optional general parameters. + * This will likely change as the API evolves, as of this writing allowed keys + * are: count, before_id, since_id, include_muted, include_deleted, + * and include_post_raw. + * See https://github.com/phpnut/api-spec/blob/master/resources/posts.md#general-parameters + * @return array An array of associative arrays, each representing a single + * user who has bookmarked a post + */ + public function getBookmarked(string|int $user_id='me', array $params=[]) + { + return $this->httpReq( + 'get', + $this->_baseUrl . 'users/' . urlencode($user_id) . '/bookmarks?' + . $this->buildQueryString($params) + ); + } + + /** + * List the interactions with a post (bookmark, repost, reply) + * @param integer $post_id the post ID to get interactions from + * @param array $params optional parameters like filters or excludes + * @return array An array of associative arrays, each representing one post interaction. + */ + public function getPostInteractions(int $post_id, array $params=[]) + { + return $this->httpReq( + 'get', + $this->_baseUrl . 'posts/' . urlencode($post_id) . '/interactions?' + . $this->buildQueryString($params) + ); + } + + /** + * List the bookmarks of a post + * @param integer $post_id the post ID to get stars from + * @return array An array of associative arrays, each representing one bookmark action. + */ + public function getPostBookmarks(int $post_id) + { + return $this->getPostInteractions($post_id, ['filters'=>['bookmark']]); + } + + /** + * Returns an array of User objects of users who reposted the specified post. + * @param integer $post_id the post ID to + * @return array An array of associative arrays, each representing a single + * user who reposted $post_id + */ + public function getPostReposts(int $post_id) + { + return $this->getPostInteractions($post_id, ['filters'=>['repost']]); + } + + /** + * Repost an existing Post object. + * @param integer $post_id The id of the post + * @return the reposted post + */ + public function repost(int $post_id) + { + return $this->httpReq( + 'put', + $this->_baseUrl . 'posts/' . urlencode($post_id) . '/repost' + ); + } + + /** + * Delete a post that the user has reposted. + * @param integer $post_id The id of the post + * @return the un-reposted post + */ + public function deleteRepost(int $post_id) + { + return $this->httpReq( + 'delete', + $this->_baseUrl . 'posts/' . urlencode($post_id) . '/repost' + ); + } + + /** + * Return Posts matching a specific #hashtag. + * @param string $hashtag The hashtag you're looking for. + * @param array $params An associative array of optional general parameters. + * This will likely change as the API evolves, as of this writing allowed keys + * are: count, before_id, since_id, include_muted, include_deleted, + * include_directed_posts, and include_raw. + * @return An array of associative arrays, each representing a single post. + */ + public function searchHashtags(string $hashtag, array $params=[]) + { + return $this->httpReq( + 'get', + $this->_baseUrl . 'posts/tags/' . urlencode($hashtag) . '?' + . $this->buildQueryString($params) + ); + } + + /** + * List the posts who match a specific search term + * @param array $params a list of filter, search query, and general Post parameters + * see: https://docs.pnut.io/resources/posts/search + * @param string $query The search query. Supports + * normal search terms. Searches post text. + * @return array An array of associative arrays, each representing one post. + * or false on error + */ + public function searchPosts(array $params=[], string $query='', string $order='default') + { + if (!is_array($params)) { + return false; + } + if (!empty($query)) { + $params['q'] = $query; + } + if ($order === 'default') { + if (!empty($query)) { + $params['order'] = 'relevance'; + } else { + $params['order'] = 'id'; + } + } + return $this->httpReq( + 'get', + $this->_baseUrl . 'posts/search?' . $this->buildQueryString($params) + ); + } + + /** + * Return the 20 most recent posts for a stream using a valid Token + * @param array $params An associative array of optional general parameters. + * This will likely change as the API evolves, as of this writing allowed keys + * are: count, before_id, since_id, include_muted, include_deleted, + * and include_post_raw. + * @return An array of associative arrays, each representing a single post. + */ + public function getUserPersonalStream(array $params=[]) + { + if ($params['access_token']) { + return $this->httpReq( + 'get', + $this->_baseUrl . 'posts/streams/me?' + . $this->buildQueryString($params), + $params + ); + } else { + return $this->httpReq( + 'get', + $this->_baseUrl . 'posts/streams/me?' + . $this->buildQueryString($params) + ); + } + } + + /** + * Return the 20 most recent Posts from the current User's personalized stream + * and mentions stream merged into one stream. + * @param array $params An associative array of optional general parameters. + * This will likely change as the API evolves, as of this writing allowed keys + * are: count, before_id, since_id, include_muted, include_deleted, + * include_directed_posts, and include_raw. + * @return An array of associative arrays, each representing a single post. + */ + public function getUserUnifiedStream(array $params=[]) + { + return $this->httpReq( + 'get', + $this->_baseUrl . 'posts/streams/unified?' + . $this->buildQueryString($params) + ); + } + + /** + * List User interactions + */ + public function getMyActions(array $params=[]) + { + return $this->httpReq( + 'get', + $this->_baseUrl . 'users/me/interactions?' + . $this->buildQueryString($params) + ); + } + + /** + * Returns a specific user object. + * @param mixed $user_id The ID of the user you want to retrieve, or the string "@-username", or the string + * "me" to retrieve data for the users you're currently authenticated as. + * @param array $params An associative array of optional general parameters. + * This will likely change as the API evolves, as of this writing allowed keys + * are: include_raw|include_user_raw. + * @return array An associative array representing the user data. + */ + public function getUser(string|int $user_id='me', array $params=[]) + { + return $this->httpReq( + 'get', + $this->_baseUrl . 'users/' . urlencode($user_id) . '?' + . $this->buildQueryString($params) + ); + } + + /** + * Returns multiple users request by an array of user ids + * @param array $params An associative array of optional general parameters. + * This will likely change as the API evolves, as of this writing allowed keys + * are: include_raw|include_user_raw. + * @return array An associative array representing the users data. + */ + public function getUsers(array $user_arr, array $params=[]) + { + return $this->httpReq( + 'get', + $this->_baseUrl . 'users?ids=' . implode(',', $user_arr) + . '&' . $this->buildQueryString($params) + ); + } + + /** + * Add the specified user ID to the list of users followed. + * Returns the User object of the user being followed. + * @param integer $user_id The user ID of the user to follow. + * @return array An associative array representing the user you just followed. + */ + public function followUser(string|int $user_id) + { + return $this->httpReq( + 'put', + $this->_baseUrl . 'users/' . urlencode($user_id) . '/follow' + ); + } + + /** + * Removes the specified user ID to the list of users followed. + * Returns the User object of the user being unfollowed. + * @param integer $user_id The user ID of the user to unfollow. + * @return array An associative array representing the user you just unfollowed. + */ + public function unfollowUser(string|int $user_id) + { + return $this->httpReq( + 'delete', + $this->_baseUrl . 'users/' . urlencode($user_id) . '/follow' + ); + } + + /** + * Returns an array of User objects the specified user is following. + * @param mixed $user_id Either the ID of the user being followed, or + * the string "me", which will retrieve posts for the user you're authenticated + * as. + * @return array An array of associative arrays, each representing a single + * user following $user_id + */ + public function getFollowing(string|int $user_id='me', array $params=[]) + { + return $this->httpReq( + 'get', + $this->_baseUrl . 'users/' . urlencode($user_id) . '/following?' + . $this->buildQueryString($params) + ); + } + + /** + * Returns an array of User ids the specified user is following. + * @param mixed $user_id Either the ID of the user being followed, or + * the string "me", which will retrieve posts for the user you're authenticated + * as. + * @return array user ids the specified user is following. + */ + public function getFollowingIDs(string|int $user_id='me') + { + return $this->httpReq( + 'get', + "{$this->_baseUrl}users/{$user_id}/following?include_user=0" + ); + } + + /** + * Returns an array of User objects for users following the specified user. + * @param mixed $user_id Either the ID of the user being followed, or + * the string "me", which will retrieve posts for the user you're authenticated + * as. + * @return array An array of associative arrays, each representing a single + * user following $user_id + */ + public function getFollowers(string|int $user_id='me', array $params=[]) + { + return $this->httpReq( + 'get', + $this->_baseUrl . 'users/' . urlencode($user_id) . '/followers?' + . $this->buildQueryString($params) + ); + } + + /** + * Returns an array of User ids for users following the specified user. + * @param mixed $user_id Either the ID of the user being followed, or + * the string "me", which will retrieve posts for the user you're authenticated + * as. + * @return array user ids for users following the specified user + */ + public function getFollowersIDs(string|int $user_id='me') + { + return $this->httpReq( + 'get', + "{$this->_baseUrl}users/{$user_id}/followers?include_user=0" + ); + } + + /** + * Retrieve a user's user ID by specifying their username. + * @param string $username The username of the user you want the ID of, without + * an @ symbol at the beginning. + * @return integer The user's user ID + */ + public function getIdByUsername(string $username) + { + return $this->httpReq( + 'get', + "{$this->_baseUrl}users/@{$username}?include_user=0" + ); + } + + /** + * Mute a user + * @param integer $user_id The user ID to mute + */ + public function muteUser(string|int $user_id) + { + return $this->httpReq( + 'put', + $this->_baseUrl . 'users/' . urlencode($user_id) . '/mute' + ); + } + + /** + * Unmute a user + * @param integer $user_id The user ID to unmute + */ + public function unmuteUser(string|int $user_id) + { + return $this->httpReq( + 'delete', + $this->_baseUrl . 'users/' . urlencode($user_id) . '/mute' + ); + } + + /** + * List the users muted by the current user + * @return array An array of associative arrays, each representing one muted user. + */ + public function getMuted() + { + return $this->httpReq( + 'get', + "{$this->_baseUrl}users/me/muted" + ); + } + + /** + * Get a user object by username + * @param string $name the @name to get + * @return array representing one user + */ + public function getUserByName(string $name) + { + return $this->httpReq( + 'get', + "{$this->_baseUrl}users/@{$name}" + ); + } + + /** + * List the users who match a specific search term + * @param string $search The search query. Supports @username or #tag searches as + * well as normal search terms. Searches username, display name, bio information. + * Does not search posts. + * @return array An array of associative arrays, each representing one user. + */ + public function searchUsers(array $params=[], string $query='') + { + if (!is_array($params)) { + return false; + } + if ($query === '') { + return false; + } + $params['q'] = $query; + return $this->httpReq( + 'get', + $this->_baseUrl . 'users/search?q=' . $this->buildQueryString($params) + ); + } + + /** + * Update Profile Data via JSON + * @data array containing user descriptors + */ + public function updateUserData(array $data=[], array $params=[]) + { + $json = json_encode($data); + return $this->httpReq( + 'put', + $this->_baseUrl . 'users/me?' + . $this->buildQueryString($params), + $json, + 'application/json' + ); + } + + /** + * Update a user image + * @image path reference to image + * @which avatar|cover + */ + protected function updateUserImage(string $image, string $which='avatar') + { + $test = @getimagesize($image); + if ($test && array_key_exists('mime', $test)) { + $mimeType = $test['mime']; + } + $data = [ + $which => new CurlFile($image, $mimeType) + ]; + return $this->httpReq( + 'post-raw', + "{$this->_baseUrl}users/me/{$which}", + $data, + 'multipart/form-data' + ); + } + + public function updateUserAvatar($avatar) + { + return $this->updateUserImage('avatar', $avatar); + } + + public function updateUserCover($cover) + { + return $this->updateUserImage('cover', $cover); + } + + /** + * Returns a Client object + * @param string $client_id + * @return array An array representing the client + */ + public function getClient(string $client_id, array $params=[]) + { + return $this->httpReq( + 'get', + $this->_baseUrl . 'clients/' . urlencode($client_id) . '?' + . $this->buildQueryString($params) + ); + } + + /** + * Returns a list of truncated client details made by a user + * @param string $user_id + * @return array A list of arrays representing clients + */ + public function getUserClients(string $user_id) + { + return $this->httpReq( + 'get', + $this->_baseUrl . 'users/' . urlencode($user_id) . '/clients' + ); + } + + /** + * update stream marker + */ + public function updateStreamMarker(array $data=[]) + { + $json = json_encode($data); + return $this->httpReq( + 'post', + "{$this->_baseUrl}markers", + $json, + 'application/json' + ); + } + + /** + * get a page of current user subscribed channels + */ + public function getMyChannelSubscriptions(array $params=[]) + { + return $this->httpReq( + 'get', + $this->_baseUrl . 'users/me/channels/subscribed?' . $this->buildQueryString($params) + ); + } + + /** + * get user channels + */ + public function getMyChannels(array $params=[]) + { + return $this->httpReq( + 'get', + $this->_baseUrl . 'users/me/channels?' . $this->buildQueryString($params) + ); + } + + /** + * create a channel + * note: you cannot create a channel with type=io.pnut.core.pm (see createMessage) + */ + public function createChannel(array $data=[]) + { + $json = json_encode($data); + return $this->httpReq( + 'post', + "{$this->_baseUrl}channels", + $json, + 'application/json' + ); + } + + /** + * get channelid info + */ + public function getChannel(int $channelid, array $params=[]) + { + return $this->httpReq( + 'get', + $this->_baseUrl . 'channels/' . $channelid . '?' + . $this->buildQueryString($params) + ); + } + + /** + * get an existing private message channel between multiple users + * @param mixed $users Can be a comma- or space-separated string, or an array. + * Usernames with @-symbol, or user ids. + */ + public function getExistingPM(string|array $users, array $params=[]) + { + if (is_string($users)) { + $users = explode(',', str_replace(' ', ',', $users)); + } + foreach($users as $key=>$user) { + if (!is_numeric($user) && substr($user, 0, 1) !== '@') { + $users[$key] = "@{$user}"; + } + } + $params['ids'] = $users; + return $this->httpReq( + 'get', + $this->_baseUrl . 'users/me/channels/existing_pm?' + . $this->buildQueryString($params) + ); + } + + /** + * get multiple channels' info by an array of channelids + */ + public function getChannels(array $channels, array $params=[]) + { + return $this->httpReq( + 'get', + $this->_baseUrl . 'channels?ids=' . implode(',', $channels) . '&' + . $this->buildQueryString($params) + ); + } + + /** + * update channelid + */ + public function updateChannel(int $channelid, array $data=[]) + { + $json = json_encode($data); + return $this->httpReq( + 'put', + "{$this->_baseUrl}channels/{$channelid}", + $json, + 'application/json' + ); + } + + /** + * subscribe from channelid + */ + public function channelSubscribe(int $channelid) + { + return $this->httpReq( + 'put', + $this->_baseUrl.'channels/'.$channelid.'/subscribe' + ); + } + + /** + * unsubscribe from channelid + */ + public function channelUnsubscribe(int $channelid) + { + return $this->httpReq( + 'delete', + $this->_baseUrl.'channels/'.$channelid.'/subscribe' + ); + } + + /** + * mute channelid + */ + public function channelMute(int $channelid) + { + return $this->httpReq( + 'put', + $this->_baseUrl.'channels/'.$channelid.'/mute' + ); + } + + /** + * unmute channelid + */ + public function channelUnmute(int $channelid) + { + return $this->httpReq( + 'delete', + $this->_baseUrl.'channels/'.$channelid.'/mute' + ); + } + + /** + * get all user objects subscribed to channelid + */ + public function getChannelSubscriptions(int $channelid, array $params=[]) + { + return $this->httpReq( + 'get', + $this->_baseUrl.'channels/'.$channelid.'/subscribers?' + . $this->buildQueryString($params) + ); + } + + /** + * get all user IDs subscribed to channelid + */ + public function getChannelSubscriptionsById(int $channelid) + { + return $this->httpReq( + 'get', + "{$this->_baseUrl}channels/{$channelid}/subscribers?include_user=0" + ); + } + + /** + * Retrieve a list of "explore" streams + * @return An array of associative arrays, each representing a single explore stream. + */ + public function getChannelExploreStreams() + { + return $this->httpReq( + 'get', + $this->_baseUrl . 'channels/streams/explore' + ); + } + + /** + * Retrieve a list of channels from an "explore" stream on pnut.io. + * @param string $slug [] + * @param array $params An associative array of optional general parameters. + * @return An array of associative arrays, each representing a single channel. + */ + public function getChannelExploreStream(string $slug, array $params=[]) + { + return $this->httpReq( + 'get', + $this->_baseUrl . 'channels/streams/explore/' . urlencode($slug) . '?' + . $this->buildQueryString($params) + ); + } + + /** + * mark channel inactive + */ + public function deleteChannel(int $channelid) + { + return $this->httpReq( + 'delete', + $this->_baseUrl.'channels/'.$channelid + ); + } + + /** + * List the channels that match a specific search term + * @param array $params a list of filter, search query, and general Channel parameters + * see: https://docs.pnut.io/resources/channels/search + * @param string $query The search query. Supports + * normal search terms. Searches common channel raw. + * @return array An array of associative arrays, each representing one channel. + * or false on error + */ + public function searchChannels(array $params=[], string $query='', string $order='default') + { + if (!empty($query)) { + $params['q'] = $query; + } + if ($order === 'default') { + if (!empty($query)) { + $params['order'] = 'id'; + } else { + $params['order'] = 'activity'; + } + } + return $this->httpReq( + 'get', + $this->_baseUrl . 'channels/search?' . $this->buildQueryString($params) + ); + } + + + /** + * get a page of messages in channelid + */ + public function getMessages(int $channelid, array $params=[]) + { + return $this->httpReq( + 'get', + $this->_baseUrl.'channels/'.$channelid.'/messages?' + . $this->buildQueryString($params) + ); + } + + /** + * get a page of messages in channelid in a thread + */ + public function getMessageThread(int $channelid, int $messageid, array $params=[]) + { + return $this->httpReq( + 'get', + $this->_baseUrl.'channels/'.$channelid.'/messages/'.$messageid.'/thread?' + . $this->buildQueryString($params) + ); + } + + /** + * get a page of sticky messages in channelid + */ + public function getStickyMessages(int $channelid, array $params=[]) + { + return $this->httpReq( + 'get', + $this->_baseUrl.'channels/'.$channelid.'/sticky_messages?' + . $this->buildQueryString($params) + ); + } + + /** + * sticky messsage + */ + public function stickyMessage(int $channelid, int $messageid) + { + return $this->httpReq( + 'put', + $this->_baseUrl.'channels/'.$channelid.'/messages/'.$messageid.'/sticky' + ); + } + + /** + * unsticky messsage + */ + public function unstickyMessage(int $channelid, int $messageid) + { + return $this->httpReq( + 'delete', + $this->_baseUrl.'channels/'.$channelid.'/messages/'.$messageid.'/sticky' + ); + } + + /** + * create message + * @param $channelid numeric or "pm" for auto-channel (type=io.pnut.core.pm) + * @param array $data array('text'=>'YOUR_MESSAGE') If a type=io.pnut.core.pm, then "destinations" key can be set to address as an array of people to send this PM too + * @param array $params query parameters + */ + public function createMessage(string|int $channelid, array $data, array $params=[]) + { + if (isset($data['destinations'])) { + if (is_string($data['destinations'])) { + $data['destinations'] = explode(',', str_replace(' ', ',', $data['destinations'])); + } + foreach($data['destinations'] as $key=>$user) { + if (!is_numeric($user) && substr($user, 0,1 ) !== '@') { + $data['destinations'][$key] = "@{$user}"; + } + } + } + $json = json_encode($data); + return $this->httpReq( + 'post', + $this->_baseUrl.'channels/'.$channelid.'/messages?' + . $this->buildQueryString($params), + $json, + 'application/json' + ); + } + + /** + * get message + */ + public function getMessage(int $channelid, int $messageid, array $params=[]) + { + return $this->httpReq( + 'get', + $this->_baseUrl.'channels/'.$channelid.'/messages/'.$messageid.'?' + . $this->buildQueryString($params) + ); + } + + /** + * Returns a list of Messages. + * @param array $message_ids The list of message IDs to retrieve + * @param array $params An associative array of optional general parameters. + * @return array An array of arrays representing the messages + */ + public function getMultipleMessages(array $message_ids, array $params=[]) + { + $params['ids'] = $message_ids; + + return $this->httpReq( + 'get', + $this->_baseUrl . 'channels/messages?' . $this->buildQueryString($params) + ); + } + + /** + * delete messsage + */ + public function deleteMessage(int $channelid, int $messageid) + { + return $this->httpReq( + 'delete', + $this->_baseUrl.'channels/'.$channelid.'/messages/'.$messageid + ); + } + + /** + * List the messages that match a specific search term + * @param array $params a list of filter, search query, and general Message parameters + * see: https://docs.pnut.io/resources/messages/search + * @param string $query The search query. Supports + * normal search terms. Searches common channel raw. + * @return array An array of associative arrays, each representing one channel. + * or false on error + */ + public function searchMessages(array $params=[], string $query='', string $order='default') + { + if (!is_array($params)) { + return false; + } + if (!empty($query)) { + $params['q'] = $query; + } + if ($order === 'default') { + if (!empty($query)) { + $params['order'] = 'id'; + } else { + $params['order'] = 'relevance'; + } + } + return $this->httpReq( + 'get', + $this->_baseUrl . 'channels/messages/search?' + . $this->buildQueryString($params) + ); + } + + /** + * Upload a file to a user's file store + * @param string $file A string containing the path of the file to upload. + * @param array $data Additional data about the file you're uploading. At the + * moment accepted keys are: mime-type, kind, type, name, public and raw. + * - If you don't specify mime-type, phpnut will attempt to guess the mime type + * based on the file, however this isn't always reliable. + * - If you don't specify kind phpnut will attempt to determine if the file is + * an image or not. + * - If you don't specify name, phpnut will use the filename of the first + * parameter. + * - If you don't specify is_public, your file will be uploaded as a private file. + * - Type is REQUIRED. + * @param array $params An associative array of optional general parameters. + * This will likely change as the API evolves, as of this writing allowed keys + * are: include_raw|include_file_raw. + * @return array An associative array representing the file + */ + public function createFile($file, array $data, array $params=[]) + { + if (!$file) { + throw new PhpnutException('You must specify a path to a file'); + } + if (!file_exists($file)) { + throw new PhpnutException('File path specified does not exist'); + } + if (!is_readable($file)) { + throw new PhpnutException('File path specified is not readable'); + } + if (!array_key_exists('type', $data) || !$data['type']) { + throw new PhpnutException('Type is required when creating a file'); + } + if (!array_key_exists('name', $data)) { + $data['name'] = basename($file); + } + if (array_key_exists('mime-type', $data)) { + $mimeType = $data['mime-type']; + unset($data['mime-type']); + } else { + $mimeType = null; + } + if (!array_key_exists('kind', $data)) { + $test = @getimagesize($path); + if ($test && array_key_exists('mime', $test)) { + $data['kind'] = 'image'; + if (!$mimeType) { + $mimeType = $test['mime']; + } + } + else { + $data['kind'] = 'other'; + } + } + if (!$mimeType) { + $finfo = finfo_open(FILEINFO_MIME_TYPE); + $mimeType = finfo_file($finfo, $file); + finfo_close($finfo); + } + if (!$mimeType) { + throw new PhpnutException('Unable to determine mime type of file, try specifying it explicitly'); + } + $data['content'] = new \CurlFile($file, $mimeType); + return $this->httpReq( + 'post-raw', + "{$this->_baseUrl}files", + $data, + 'multipart/form-data' + ); + } + + public function createFilePlaceholder($file, array $params=[]) + { + $name = basename($file); + $data = [ + 'raw' => $params['raw'], + 'kind' => $params['kind'], + 'name' => $name, + 'type' => $params['metadata'] + ]; + $json = json_encode($data); + return $this->httpReq( + 'post', + $this->_baseUrl.'files', + $json, + 'application/json' + ); + } + + public function updateFileContent(int $fileid, string $file) + { + $data = file_get_contents($file); + $finfo = finfo_open(FILEINFO_MIME_TYPE); + $mime = finfo_file($finfo, $file); + finfo_close($finfo); + return $this->httpReq( + 'put', + $this->_baseUrl.'files/'.$fileid.'/content', + $data, + $mime + ); + } + + /** + * Allows for file rename and annotation changes. + * @param integer $file_id The ID of the file to update + * @param array $params An associative array of file parameters. + * @return array An associative array representing the updated file + */ + public function updateFile(int $file_id, array $params=[]) + { + $data = [ + 'raw' => $params['raw'], + 'name' => $params['name'], + ]; + $json = json_encode($data); + return $this->httpReq( + 'put', + $this->_baseUrl.'files/'.urlencode($file_id), + $json, + 'application/json' + ); + } + + /** + * Returns a specific File. + * @param integer $file_id The ID of the file to retrieve + * @param array $params An associative array of optional general parameters. + * This will likely change as the API evolves, as of this writing allowed keys + * are: include_raw|include_file_raw. + * @return array An associative array representing the file + */ + public function getFile(int $file_id, array $params=[]) + { + return $this->httpReq( + 'get', + $this->_baseUrl.'files/'.urlencode($file_id).'?' + . $this->buildQueryString($params) + ); + } + + public function getFileContent(int $file_id, array $params=[]) + { + return $this->httpReq( + 'get', + $this->_baseUrl.'files/'.urlencode($file_id).'/content?' + . $this->buildQueryString($params) + ); + } + + /** $file_key : derived_file_key */ + public function getDerivedFileContent(int $file_id, string $file_key, array $params=[]) + { + return $this->httpReq( + 'get', + $this->_baseUrl.'files/'.urlencode($file_id).'/content/'.urlencode($file_key).'?'.$this->buildQueryString($params) + ); + } + + /** + * Returns file objects. + * @param array $file_ids The IDs of the files to retrieve + * @param array $params An associative array of optional general parameters. + * This will likely change as the API evolves, as of this writing allowed keys + * are: include_raw|include_file_raw. + * @return array An associative array representing the file data. + */ + public function getFiles(array $file_ids, array $params=[]) + { + $ids = ''; + foreach($file_ids as $id) { + $ids .= $id . ','; + } + $params['ids'] = substr($ids, 0, -1); + return $this->httpReq( + 'get', + $this->_baseUrl.'files?'.$this->buildQueryString($params) + ); + } + + /** + * Returns a user's file objects. + * @param array $params An associative array of optional general parameters. + * This will likely change as the API evolves, as of this writing allowed keys + * are: include_raw|include_file_raw|include_user_raw. + * @return array An associative array representing the file data. + */ + public function getUserFiles(array $params=[]) + { + return $this->httpReq( + 'get', + $this->_baseUrl.'users/me/files?'.$this->buildQueryString($params) + ); + } + + /** + * Delete a File. The current user must be the same user who created the File. + * It returns the deleted File on success. + * @param integer $file_id The ID of the file to delete + * @return array An associative array representing the file that was deleted + */ + public function deleteFile(int $file_id) + { + return $this->httpReq( + 'delete', + $this->_baseUrl.'files/'.urlencode($file_id) + ); + } + + /** + * Create a poll + * @param array $data An associative array of the required parameters. + * @param array $params An associative array of optional general parameters. + * Allowed keys: include_raw,include_poll_raw, ... + * @return array An associative array representing the poll + */ + public function createPoll(array $data, array $params=[]) + { + $json = json_encode($data); + return $this->httpReq( + 'post', + $this->_baseUrl.'polls?'.$this->buildQueryString($params), + $json, + 'application/json' + ); + } + + /** + * Responds to a poll. + * @param integer $poll_id The ID of the poll to respond to + * @param array list of positions for the poll response + * @param array $params An associative array of optional general parameters. + */ + public function respondToPoll(int $poll_id, array $positions, array $params=[]) + { + $json = json_encode(['positions' => $positions]); + return $this->httpReq( + 'put', + $this->_baseUrl.'polls/'.urlencode($poll_id).'/response?'.$this->buildQueryString($params), + $json, + 'application/json' + ); + } + + /** + * Returns a specific Poll. + * @param integer $poll_id The ID of the poll to retrieve + * @param array $params An associative array of optional general parameters. + * @return array An associative array representing the poll + */ + public function getPoll(int $poll_id, array $params=[]) + { + return $this->httpReq( + 'get', + $this->_baseUrl.'polls/'.urlencode($poll_id).'?'.$this->buildQueryString($params) + ); + } + + /** + * Returns a list of Polls. + * @param array $poll_ids The list of poll IDs to retrieve + * @param array $params An associative array of optional general parameters. + * @return array An array of arrays representing the polls + */ + public function getMultiplePolls(array $poll_ids, array $params=[]) + { + $params['ids'] = $poll_ids; + + return $this->httpReq( + 'get', + $this->_baseUrl . 'polls?' . $this->buildQueryString($params) + ); + } + + /** + * Returns a user's poll objects. + * @param array $params An associative array of optional general parameters. + * @return array An associative array representing the poll data. + */ + public function getUserPolls(array $params=[]) + { + return $this->httpReq( + 'get', + $this->_baseUrl.'users/me/polls?'.$this->buildQueryString($params) + ); + } + + /** + * Delete a Poll. The current user must be the same user who created the Poll. + * @param integer $poll_id The ID of the poll to delete + * @param array $params An associative array of optional general parameters. + * @return array An associative array representing the poll that was deleted + */ + public function deletePoll(int $poll_id, array $params=[]) + { + return $this->httpReq( + 'delete', + $this->_baseUrl.'polls/'.urlencode($poll_id).'?'.$this->buildQueryString($params) + ); + } + + /** + * List the polls that match a specific search term + * @param array $params a list of filter, search query, and general Poll parameters + * see: https://docs.pnut.io/resources/channels/search + * @param string $query The search query. Supports + * normal search terms. + * @return array An array of associative arrays, each representing one poll. + * or false on error + */ + public function searchPolls(array $params=[], string $order='id') + { + $params['order'] = $order; + + return $this->httpReq( + 'get', + $this->_baseUrl . 'polls/search?' . $this->buildQueryString($params) + ); + } + + + /** + * Get Application Information + */ + public function getAppTokenInfo() + { + // requires appAccessToken + if (!$this->_appAccessToken) { + $this->getAppAccessToken(); + } + // ensure request is made with our appAccessToken + $params['access_token'] = $this->_appAccessToken; + return $this->httpReq( + 'get', + "{$this->_baseUrl}token", + $params + ); + } + + /** + * Get User Information + */ + public function getUserTokenInfo() + { + return $this->httpReq( + 'get', + "{$this->_baseUrl}token" + ); + } + + /** + * Get Application Authorized User IDs + */ + public function getAppUserIDs() + { + // requires appAccessToken + if (!$this->_appAccessToken) { + $this->getAppAccessToken(); + } + // ensure request is made with our appAccessToken + $params['access_token'] = $this->_appAccessToken; + return $this->httpReq( + 'get', + "{$this->_baseUrl}apps/me/users/ids", + $params + ); + } + + /** + * Get Application Authorized User Tokens + */ + public function getAppUserTokens() + { + // requires appAccessToken + if (!$this->_appAccessToken) { + $this->getAppAccessToken(); + } + // ensure request is made with our appAccessToken + $params['access_token'] = $this->_appAccessToken; + return $this->httpReq( + 'get', + "{$this->_baseUrl}apps/me/users/tokens", + $params + ); + } + + + + /** + * Registers your function (or an array of object and method) to be called + * whenever an event is received via an open pnut.io stream. Your function + * will receive a single parameter, which is the object wrapper containing + * the meta and data. + * @param mixed A PHP callback (either a string containing the function name, + * or an array where the first element is the class/object and the second + * is the method). + */ + public function registerStreamFunction($function): void + { + $this->_streamCallback = $function; + } + + /** + * Opens a stream that's been created for this user/app and starts sending + * events/objects to your defined callback functions. You must define at + * least one callback function before opening a stream. + * @param mixed $stream Either a stream ID or the endpoint of a stream + * you've already created. This stream must exist and must be valid for + * your current access token. If you pass a stream ID, the library will + * make an API call to get the endpoint. + * + * This function will return immediately, but your callback functions + * will continue to receive events until you call closeStream() or until + * pnut.io terminates the stream from their end with an error. + * + * If you're disconnected due to a network error, the library will + * automatically attempt to reconnect you to the same stream, no action + * on your part is necessary for this. However if the pnut.io API returns + * an error, a reconnection attempt will not be made. + * + * Note there is no closeStream, because once you open a stream you + * can't stop it (unless you exit() or die() or throw an uncaught + * exception, or something else that terminates the script). + * @return boolean True + * @see createStream() + */ + public function openStream($stream): bool + { + // if there's already a stream running, don't allow another + if ($this->_currentStream) { + throw new phpnutException('There is already a stream being consumed, only one stream can be consumed per phpnutStream instance'); + } + // must register a callback (or the exercise is pointless) + if (!$this->_streamCallback) { + throw new phpnutException('You must define your callback function using registerStreamFunction() before calling openStream'); + } + // if the stream is a numeric value, get the stream info from the api + if (is_numeric($stream)) { + $stream = $this->getStream($stream); + $this->_streamUrl = $stream['endpoint']; + } + else { + $this->_streamUrl = $stream; + } + // continue doing this until we get an error back or something...? + $this->httpStream( + 'get', + $this->_streamUrl + ); + return true; + } + + /** + * Close the currently open stream. + * @return true; + */ + public function closeStream(): void + { + if (!$this->_lastStreamActivity) { + // never opened + return; + } + if (!$this->_multiStream) { + throw new phpnutException('You must open a stream before calling closeStream()'); + } + curl_close($this->_currentStream); + curl_multi_remove_handle($this->_multiStream, $this->_currentStream); + curl_multi_close($this->_multiStream); + $this->_currentStream = null; + $this->_multiStream = null; + } + + /** + * Retrieve all streams for the current access token. + * @return array An array of stream definitions. + */ + public function getAllStreams() + { + return $this->httpReq( + 'get', + "{$this->_baseUrl}streams" + ); + } + + /** + * Returns a single stream specified by a stream ID. The stream must have been + * created with the current access token. + * @return array A stream definition + */ + public function getStream(string $streamId) + { + return $this->httpReq( + 'get', + $this->_baseUrl.'streams/'.urlencode($streamId) + ); + } + + /** + * Creates a stream for the current app access token. + * + * @param array $objectTypes The objects you want to retrieve data for from the + * stream. At time of writing these can be 'post', 'bookmark', 'user_follow', 'mute', 'block', 'stream_marker', 'message', 'channel', 'channel_subscription', 'token', and/or 'user'. + * If you don't specify, a few standard events will be retrieved. + */ + public function createStream(?array $objectTypes=null) + { + // default object types to everything + if (is_null($objectTypes)) { + $objectTypes = [ + 'post', + 'bookmark', + 'user_follow', + ]; + } + $data = [ + 'object_types'=>$objectTypes, + 'type'=>'long_poll', + ]; + $data = json_encode($data); + $response = $this->httpReq( + 'post', + "{$this->_baseUrl}streams", + $data, + 'application/json' + ); + return $response; + } + + /** + * Update stream for the current app access token + * + * @param string $streamId The stream ID to update. This stream must have been + * created by the current access token. + * @param array $data allows object_types, type, filter_id and key to be updated. filter_id/key can be omitted + */ + public function updateStream(string $streamId, array $data) + { + // objectTypes is likely required + if (is_null($data['object_types'])) { + $data['object_types'] = [ + 'post', + 'bookmark', + 'user_follow', + ]; + } + // type can still only be long_poll + if (is_null($data['type'])) { + $data['type'] = 'long_poll'; + } + $data = json_encode($data); + $response = $this->httpReq( + 'put', + $this->_baseUrl.'streams/'.urlencode($streamId), + $data, + 'application/json' + ); + return $response; + } + + /** + * Deletes a stream if you no longer need it. + * + * @param string $streamId The stream ID to delete. This stream must have been + * created by the current access token. + */ + public function deleteStream(string $streamId) + { + return $this->httpReq( + 'delete', + $this->_baseUrl.'streams/'.urlencode($streamId) + ); + } + + /** + * Deletes all streams created by the current access token. + */ + public function deleteAllStreams() + { + return $this->httpReq( + 'delete', + "{$this->_baseUrl}streams" + ); + } + + /** + * Internal function used to process incoming chunks from the stream. This is only + * public because it needs to be accessed by CURL. Do not call or use this function + * in your own code. + * @ignore + */ + public function httpStreamReceive($ch, $data) + { + $this->_lastStreamActivity = time(); + $this->_streamBuffer .= $data; + if (!$this->_streamHeaders) { + $pos = strpos($this->_streamBuffer, "\r\n\r\n"); + if ($pos !== false) { + $this->_streamHeaders = substr($this->_streamBuffer, 0, $pos); + $this->_streamBuffer = substr($this->_streamBuffer, $pos+4); + } + } else { + $pos = strpos($this->_streamBuffer, "\r\n"); + while ($pos !== false) { + $command = substr($this->_streamBuffer, 0, $pos); + $this->_streamBuffer = substr($this->_streamBuffer, $pos+2); + $command = json_decode($command, true); + if ($command) { + call_user_func($this->_streamCallback, $command); + } + $pos = strpos($this->_streamBuffer, "\r\n"); + } + } + return strlen($data); + } + + /** + * Opens a long lived HTTP connection to the pnut.io servers, and sends data + * received to the httpStreamReceive function. As a general rule you should not + * directly call this method, it's used by openStream(). + */ + protected function httpStream(string $act, $req, array $params=[], string $contentType='application/x-www-form-urlencoded'): void + { + if ($this->_currentStream) { + throw new phpnutException('There is already an open stream, you must close the existing one before opening a new one'); + } + $headers = []; + $this->_streamBuffer = ''; + if ($this->_accessToken) { + $headers[] = "Authorization: Bearer {$this->_accessToken}"; + } + $this->_currentStream = curl_init($req); + curl_setopt($this->_currentStream, CURLOPT_HTTPHEADER, $headers); + curl_setopt($this->_currentStream, CURLOPT_RETURNTRANSFER, true); + curl_setopt($this->_currentStream, CURLINFO_HEADER_OUT, true); + curl_setopt($this->_currentStream, CURLOPT_HEADER, true); + if ($this->_sslCA) { + curl_setopt($this->_currentStream, CURLOPT_CAINFO, $this->_sslCA); + } + // every time we receive a chunk of data, forward it to httpStreamReceive + curl_setopt($this->_currentStream, CURLOPT_WRITEFUNCTION, array($this, 'httpStreamReceive')); + // curl_exec($ch); + // return; + $this->_multiStream = curl_multi_init(); + $this->_lastStreamActivity = time(); + curl_multi_add_handle($this->_multiStream, $this->_currentStream); + } + + public function reconnectStream(): void + { + $this->closeStream(); + $this->_connectFailCounter++; + // if we've failed a few times, back off + if ($this->_connectFailCounter > 1) { + $sleepTime = pow(2, $this->_connectFailCounter); + // don't sleep more than 60 seconds + if ($sleepTime > 60) { + $sleepTime = 60; + } + sleep($sleepTime); + } + $this->httpStream('get', $this->_streamUrl); + } + + /** + * Process an open stream for x microseconds, then return. This is useful if you want + * to be doing other things while processing the stream. If you just want to + * consume the stream without other actions, you can call processForever() instead. + * @param float @microseconds The number of microseconds to process for before + * returning. There are 1,000,000 microseconds in a second. + * + * @return void + */ + public function processStream($microseconds=null): void + { + if (!$this->_multiStream) { + throw new phpnutException('You must open a stream before calling processStream()'); + } + $start = microtime(true); + $active = null; + $inQueue = null; + $sleepFor = 0; + do { + // if we haven't received anything within 5.5 minutes, reconnect + // keepalives are sent every 5 minutes (measured on 2013-3-12 by @ryantharp) + if (time()-$this->_lastStreamActivity >= 330) { + $this->reconnectStream(); + } + curl_multi_exec($this->_multiStream, $active); + if (!$active) { + $httpCode = curl_getinfo($this->_currentStream, CURLINFO_HTTP_CODE); + // don't reconnect on 400 errors + if ($httpCode >= 400 && $httpCode <= 499) { + throw new phpnutException("Received HTTP error {$httpCode} check your URL and credentials before reconnecting"); + } + $this->reconnectStream(); + } + // sleep for a max of 2/10 of a second + $timeSoFar = (microtime(true)-$start)*1000000; + $sleepFor = $this->streamingSleepFor; + if ($timeSoFar+$sleepFor > $microseconds) { + $sleepFor = $microseconds - $timeSoFar; + } + if ($sleepFor > 0) { + usleep($sleepFor); + } + } while ($timeSoFar+$sleepFor < $microseconds); + } + + /** + * Process an open stream forever. This function will never return, if you + * want to perform other actions while consuming the stream, you should use + * processFor() instead. + * @return void This function will never return + * @see processFor(); + */ + public function processStreamForever(): void + { + while (true) { + $this->processStream(600); + } + } +} diff --git a/pnut/lib/phpnutException.php b/pnut/lib/phpnutException.php new file mode 100644 index 000000000..77e768fe2 --- /dev/null +++ b/pnut/lib/phpnutException.php @@ -0,0 +1,5 @@ + + * Status: In Development + */ + +require_once 'addon/pnut/lib/phpnut.php'; +require_once 'addon/pnut/lib/phpnutException.php'; + +use Friendica\Content\Text\BBCode; +use Friendica\Content\Text\Plaintext; +use Friendica\Core\Config\Util\ConfigFileManager; +use Friendica\Core\Hook; +use Friendica\Core\Logger; +use Friendica\Core\Renderer; +use Friendica\Core\System; +use Friendica\DI; +use Friendica\Model\Item; +use Friendica\Model\Photo; +use Friendica\Object\Image; +use Friendica\Network\HTTPClient\Client\HttpClientAccept; +use Friendica\Network\HTTPClient\Client\HttpClientOptions; +use Friendica\Util\DateTimeFormat; + +function pnut_install() +{ + Hook::register('load_config', __FILE__, 'pnut_load_config'); + Hook::register('hook_fork', __FILE__, 'pnut_hook_fork'); + Hook::register('post_local', __FILE__, 'pnut_post_local'); + Hook::register('notifier_normal', __FILE__, 'pnut_post_hook'); + Hook::register('jot_networks', __FILE__, 'pnut_jot_nets'); + Hook::register('connector_settings', __FILE__, 'pnut_settings'); + Hook::register('connector_settings_post', __FILE__, 'pnut_settings_post'); +} + +function pnut_module() {} + +function pnut_content() +{ + if (!DI::userSession()->getLocalUserId()) { + DI::sysmsg()->addNotice(DI::l10n()->t('Permission denied.')); + return ''; + } + + if (isset(DI::args()->getArgv()[1])) { + switch (DI::args()->getArgv()[1]) { + case 'connect': + $o = pnut_connect(); + break; + + default: + $o = print_r(DI::args()->getArgv(), true); + break; + } + } else { + $o = pnut_connect(); + } + return $o; +} + +function pnut_connect() +{ + $client_id = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'pnut', 'client_id'); + $client_secret = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'pnut', 'client_secret'); + $callback_url = DI::baseUrl() . '/pnut/connect'; + + $nut = new phpnut\phpnut($client_id, $client_secret); + + try { + $token = $nut->getAccessToken($callback_url); + Logger::debug('TOKEN', [$token]); + $o = DI::l10n()->t('You are now authenticated with pnut.io.'); + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'pnut', 'access_token', $token); + } catch (phpnutException $e) { + $o = DI::l10n()->t('Error fetching token. Please try again.'); + } + + $o .= '
' . DI::l10n()->t("return to the connector page").''; + + return $o; +} + +function pnut_load_config(ConfigFileManager $loader) +{ + DI::app()->getConfigCache()->load($loader->loadAddonConfig('pnut'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); +} + +function pnut_settings(array &$data) +{ + if (!DI::userSession()->getLocalUserId()) { + return; + } + + $redirectUri = DI::baseUrl() . '/pnut/connect'; + $scope = ['write_post','files']; + + $enabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'pnut', 'post') ?? false; + $def_enabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'pnut', 'post_by_default') ?? false; + $client_id = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'pnut', 'client_id'); + $client_secret = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'pnut', 'client_secret'); + $token = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'pnut', 'access_token'); + + Logger::debug('CLIENT_ID', [$client_id]); + Logger::debug('CLIENT_SECRET', [$client_secret]); + + if (!empty($client_id) && !empty($client_secret) && empty($token)) { + $nut = new phpnut\phpnut($client_id, $client_secret); + $authorize_url = $nut->getAuthUrl($redirectUri, $scope); + $authorize_text = DI::l10n()->t('Authenticate with pnut.io'); + } + + if (!empty($token)) { + $disconn_btn = DI::l10n()->t('Disconnect'); + } + + $t = Renderer::getMarkupTemplate('connector_settings.tpl', 'addon/pnut/'); + $html = Renderer::replaceMacros($t, [ + '$enable' => ['pnut', DI::l10n()->t('Enable Pnut Post Addon'), $enabled], + '$bydefault' => ['pnut_bydefault', DI::l10n()->t('Post to Pnut by default'), $def_enabled], + '$client_id' => ['pnut_client_id', DI::l10n()->t('Client ID'), $client_id], + '$client_secret' => ['pnut_client_secret', DI::l10n()->t('Client Secret'), $client_secret], + '$access_token' => ['pnut_access_token', DI::l10n()->t('Access Token'), $token, '', '', 'readonly'], + '$authorize_url' => $authorize_url ?? '', + '$authorize_text' => $authorize_text ?? '', + '$disconn_btn' => $disconn_btn ?? '', + ]); + + $data = [ + 'connector' => 'pnut', + 'title' => DI::l10n()->t('Pnut Import/Export'), + 'image' => 'addon/pnut/pnut.svg', + 'enabled' => $enabled, + 'html' => $html, + ]; +} + +function pnut_settings_post(array &$b) +{ + if (empty($_POST['pnut-submit']) && empty($_POST['pnut-disconnect'])) { + return; + } + + if (!empty($_POST['pnut-disconnect'])) { + DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'pnut', 'post'); + DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'pnut', 'post_by_default'); + DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'pnut', 'client_id'); + DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'pnut', 'client_secret'); + DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'pnut', 'access_token'); + } else { + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'pnut', 'post', intval($_POST['pnut'])); + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'pnut', 'post_by_default', intval($_POST['pnut_bydefault'])); + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'pnut', 'client_id', $_POST['pnut_client_id']); + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'pnut', 'client_secret', $_POST['pnut_client_secret']); + } +} + +function pnut_jot_nets(array &$jotnets_fields) +{ + if (!DI::userSession()->getLocalUserId()) { + return; + } + + if (DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'pnut', 'post')) { + $jotnets_fields[] = [ + 'type' => 'checkbox', + 'field' => [ + 'pnut_enable', + DI::l10n()->t('Post to Pnut'), + DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'pnut', 'post_by_default') + ] + ]; + } +} + +function pnut_hook_fork(array &$b) +{ + if ($b['name'] != 'notifier_normal') { + return; + } + + $post = $b['data']; + + if (($post['created'] !== $post['edited']) && !$post['deleted']) { + DI::logger()->info('Editing is not supported by the addon'); + $b['execute'] = false; + return; + } + + if (!strstr($post['postopts'] ?? '', 'pnut') || ($post['parent'] != $post['id']) || $post['private']) { + $b['execute'] = false; + return; + } +} + +function pnut_post_local(array &$b) +{ + if ($b['edit']) { + return; + } + + if (!DI::userSession()->getLocalUserId() || (DI::userSession()->getLocalUserId() != $b['uid'])) { + return; + } + + if ($b['private'] || $b['parent']) { + return; + } + + $pnut_post = intval(DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'pnut', 'post')); + $pnut_enable = (($pnut_post && !empty($_REQUEST['pnut_enable'])) ? intval($_REQUEST['pnut_enable']) : 0); + + // if API is used, default to the chosen settings + if ($b['api_source'] && intval(DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'pnut', 'post_by_default'))) { + $pnut_enable = 1; + } + + if (!$pnut_enable) { + return; + } + + if (strlen($b['postopts'])) { + $b['postopts'] .= ','; + } + + $b['postopts'] .= 'pnut'; +} + +function pnut_post_hook(array &$b) +{ + /** + * Post to pnut.io + */ + if ($b['deleted'] || $b['private'] || ($b['created'] !== $b['edited'])) { + return; + } + + Logger::notice('PNUT post invoked', ['id' => $b['id'], 'guid' => $b['guid'], 'plink' => $b['plink']]); + Logger::debug('PNUT array', $b); + + $token = DI::pConfig()->get($b['uid'], 'pnut', 'access_token'); + $nut = new phpnut\phpnut($token); + + $msgarr = Plaintext::getPost($b, 256, true, BBCode::EXTERNAL); + $text = $msgarr['text']; + $raw = []; + + Logger::debug('PNUT msgarr', $msgarr); + + if (count($msgarr['parts']) > 1) { + $tstamp = time(); + $raw['nl.chimpnut.blog.post'][] = ['body' => $b['body'], 'tstamp' => $tstamp]; + $text = Plaintext::shorten($text, 252 - strlen($b['plink']), $b['uid']); + $text .= "\n" . $b['plink']; + } + + if ($msgarr['type'] == 'link') { + $text .= "\n[" . $msgarr['title'] . "](" . $msgarr['url'] . ")"; + } + + if ($msgarr['type'] == 'photo') { + $fileraw = ['type' => 'dev.mcmillian.friendica.image', 'kind' => 'image', 'is_public' => true]; + foreach ($msgarr['images'] as $image) { + Logger::debug('PNUT image', $image); + + if (!empty($image['id'])) { + $photo = Photo::selectFirst([], ['id' => $image['id']]); + Logger::debug('PNUT selectFirst'); + } else { + $photo = Photo::createPhotoForExternalResource($image['url']); + Logger::debug('PNUT createPhotoForExternalResource'); + } + $picturedata = Photo::getImageForPhoto($photo); + + Logger::debug('PNUT photo', $photo); + $picurefile = System::getTempPath() . DIRECTORY_SEPARATOR . $photo['filename']; + file_put_contents($picurefile, $picturedata); + Logger::debug('PNUT got file?', ['filename' => $picurefile]); + $imagefile = $nut->createFile($picurefile, $fileraw); + Logger::debug('PNUT file', ['pnutimagefile' => $imagefile]); + unlink($picurefile); + + $raw['io.pnut.core.oembed'][] = ['+io.pnut.core.file' => ['file_id' => $imagefile['id'], 'file_token' => $imagefile['file_token'], 'format' => 'oembed']]; + } + } + + $raw['io.pnut.core.crosspost'][] = ['canonical_url' => $b['plink']]; + $nut->createPost($text, ['raw' => $raw]); + + Logger::debug('PNUT post complete', ['id' => $b['id'], 'text' => $text, 'raw' => $raw]); +} diff --git a/pnut/pnut.svg b/pnut/pnut.svg new file mode 100644 index 000000000..6cc64b010 --- /dev/null +++ b/pnut/pnut.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/pnut/templates/connector_settings.tpl b/pnut/templates/connector_settings.tpl new file mode 100644 index 000000000..7d1ad3f2a --- /dev/null +++ b/pnut/templates/connector_settings.tpl @@ -0,0 +1,12 @@ +

{{$status}}

+{{include file="field_checkbox.tpl" field=$enable}} +{{include file="field_checkbox.tpl" field=$bydefault}} +{{include file="field_input.tpl" field=$client_id}} +{{include file="field_input.tpl" field=$client_secret}} +{{include file="field_input.tpl" field=$access_token}} +{{if $authorize_url}} + {{$authorize_text}} +{{/if}} +{{if $disconn_btn}} +
+{{/if}} From e4bb463b5b36b90018672b8c8fc9c23192ddde4c Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 23 Feb 2024 13:32:24 +0000 Subject: [PATCH 107/388] Bluesky: Several improvements and fixes --- bluesky/bluesky.php | 171 ++++++++++++++++++++------------------------ 1 file changed, 79 insertions(+), 92 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index fe1faab18..b651238bd 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -141,7 +141,7 @@ function bluesky_probe_detect(array &$hookData) return; } - $hookData['result'] = bluesky_get_contact_fields($data, 0, false); + $hookData['result'] = bluesky_get_contact_fields($data, 0, $pconfig['uid'], false); $hookData['result']['baseurl'] = bluesky_get_pds($did); @@ -942,7 +942,7 @@ function bluesky_fetch_timeline(int $uid, int $last_poll) } foreach (array_reverse($data->feed) as $entry) { - bluesky_process_post($entry->post, $uid, Item::PR_NONE, 0, $last_poll); + bluesky_process_post($entry->post, $uid, $uid, Item::PR_NONE, 0, 0, $last_poll); if (!empty($entry->reason)) { bluesky_process_reason($entry->reason, bluesky_get_uri($entry->post), $uid); } @@ -1041,18 +1041,21 @@ function bluesky_fetch_notifications(int $uid, int $last_poll) break; case 'mention': - $data = bluesky_process_post($notification, $uid, Item::PR_PUSHED, 0, $last_poll); - Logger::debug('Got mention', ['uid' => $uid, 'result' => $data, 'uri' => $uri]); + $contact = bluesky_get_contact($notification->author, 0, $uid); + $result = bluesky_fetch_missing_post($uri, $uid, $uid, $contact['id'], 0, $last_poll); + Logger::debug('Got mention', ['uid' => $uid, 'nick' => $contact['nick'], 'result' => $result, 'uri' => $uri]); break; case 'reply': - $data = bluesky_process_post($notification, $uid, Item::PR_PUSHED, 0, $last_poll); - Logger::debug('Got reply', ['uid' => $uid, 'result' => $data, 'uri' => $uri]); + $contact = bluesky_get_contact($notification->author, 0, $uid); + $result = bluesky_fetch_missing_post($uri, $uid, $uid, $contact['id'], 0, $last_poll); + Logger::debug('Got reply', ['uid' => $uid, 'nick' => $contact['nick'], 'result' => $result, 'uri' => $uri]); break; case 'quote': - $data = bluesky_process_post($notification, $uid, Item::PR_PUSHED, 0, $last_poll); - Logger::debug('Got quote', ['uid' => $uid, 'result' => $data, 'uri' => $uri]); + $contact = bluesky_get_contact($notification->author, 0, $uid); + $result = bluesky_fetch_missing_post($uri, $uid, $uid, $contact['id'], 0, $last_poll); + Logger::debug('Got quote', ['uid' => $uid, 'nick' => $contact['nick'], 'result' => $result, 'uri' => $uri]); break; default: @@ -1090,15 +1093,12 @@ function bluesky_fetch_feed(int $uid, string $feed, int $last_poll) Logger::debug('Unwanted language detected', ['text' => $entry->post->record->text]); continue; } - $id = bluesky_process_post($entry->post, $uid, Item::PR_TAG, 0, $last_poll); - if (!empty($id)) { - $post = Post::selectFirst(['uri-id'], ['id' => $id]); - if (!empty($post['uri-id'])) { - $stored = Post\Category::storeFileByURIId($post['uri-id'], $uid, Post\Category::SUBCRIPTION, $feedname, $feedurl); - Logger::debug('Stored tag subscription for user', ['uri-id' => $post['uri-id'], 'uid' => $uid, 'name' => $feedname, 'url' => $feedurl, 'stored' => $stored]); - } else { - Logger::notice('Post not found', ['id' => $id, 'entry' => $entry]); - } + $uri_id = bluesky_process_post($entry->post, $uid, $uid, Item::PR_TAG, 0, 0, $last_poll); + if (!empty($uri_id)) { + $stored = Post\Category::storeFileByURIId($uri_id, $uid, Post\Category::SUBCRIPTION, $feedname, $feedurl); + Logger::debug('Stored tag subscription for user', ['uri-id' => $uri_id, 'uid' => $uid, 'name' => $feedname, 'url' => $feedurl, 'stored' => $stored]); + } else { + Logger::notice('Post not found', ['entry' => $entry]); } if (!empty($entry->reason)) { bluesky_process_reason($entry->reason, bluesky_get_uri($entry->post), $uid); @@ -1106,22 +1106,23 @@ function bluesky_fetch_feed(int $uid, string $feed, int $last_poll) } } -function bluesky_process_post(stdClass $post, int $uid, int $post_reason, int $level, int $last_poll): int +function bluesky_process_post(stdClass $post, int $uid, int $fetch_uid, int $post_reason, int $causer, int $level, int $last_poll): int { $uri = bluesky_get_uri($post); - if ($id = Post::selectFirst(['id'], ['uri' => $uri, 'uid' => $uid])) { - return $id['id']; + if ($uri_id = bluesky_fetch_uri_id($uri, $uid)) { + return $uri_id; } - if ($id = Post::selectFirst(['id'], ['extid' => $uri, 'uid' => $uid])) { - return $id['id']; + if (empty($post->record)) { + Logger::debug('Invalid post', ['uri' => $uri]); + return 0; } Logger::debug('Importing post', ['uid' => $uid, 'indexedAt' => $post->indexedAt, 'uri' => $post->uri, 'cid' => $post->cid, 'root' => $post->record->reply->root ?? '']); - $item = bluesky_get_header($post, $uri, $uid, $uid); - $item = bluesky_get_content($item, $post->record, $uri, $uid, $uid, $level, $last_poll); + $item = bluesky_get_header($post, $uri, $uid, $fetch_uid); + $item = bluesky_get_content($item, $post->record, $uri, $uid, $fetch_uid, $level, $last_poll); if (empty($item)) { return 0; } @@ -1134,13 +1135,18 @@ function bluesky_process_post(stdClass $post, int $uid, int $post_reason, int $l $item['post-reason'] = $post_reason; } - return Item::insert($item); + if ($causer != 0) { + $item['causer-id'] = $causer; + } + + Item::insert($item); + return bluesky_fetch_uri_id($uri, $uid); } function bluesky_get_header(stdClass $post, string $uri, int $uid, int $fetch_uid): array { $parts = bluesky_get_uri_parts($uri); - if (empty($post->author)) { + if (empty($post->author) || empty($post->cid) || empty($parts->rkey)) { return []; } $contact = bluesky_get_contact($post->author, $uid, $fetch_uid); @@ -1293,55 +1299,35 @@ function bluesky_add_media(stdClass $embed, array $item, int $fetch_uid, int $le break; case 'app.bsky.embed.record#view': - $uri = bluesky_get_uri($embed->record); - $shared = Post::selectFirst(['uri-id'], ['uri' => $uri, 'uid' => $item['uid']]); - if (empty($shared)) { - if (empty($embed->record->value)) { - Logger::info('Record has got no value', ['record' => $embed->record]); - break; - } - $shared = bluesky_get_header($embed->record, $uri, 0, $fetch_uid); - $shared = bluesky_get_content($shared, $embed->record->value, $uri, $item['uid'], $fetch_uid, $level, $last_poll); - if (!empty($shared)) { - if (!empty($embed->record->embeds)) { - foreach ($embed->record->embeds as $single) { - $shared = bluesky_add_media($single, $shared, $fetch_uid, $level, $last_poll); - } - } - Item::insert($shared); - } + $original_uri = $uri = bluesky_get_uri($embed->record); + $uri = bluesky_fetch_missing_post($uri, $item['uid'], $fetch_uid, $item['contact-id'], $level, $last_poll); + if ($uri) { + $shared = Post::selectFirst(['uri-id'], ['uri' => $uri, 'uid' => [$item['uid'], 0]]); + $uri_id = $shared['uri-id'] ?? 0; } - if (!empty($shared['uri-id'])) { - $item['quote-uri-id'] = $shared['uri-id']; + if (!empty($uri_id)) { + $item['quote-uri-id'] = $uri_id; + } else { + Logger::debug('Quoted post could not be fetched', ['original-uri' => $original_uri, 'uri' => $uri]); } break; case 'app.bsky.embed.recordWithMedia#view': - $uri = bluesky_get_uri($embed->record->record); - $shared = Post::selectFirst(['uri-id'], ['uri' => $uri, 'uid' => $item['uid']]); - if (empty($shared)) { - $shared = bluesky_get_header($embed->record->record, $uri, 0, $fetch_uid); - $shared = bluesky_get_content($shared, $embed->record->record->value, $uri, $item['uid'], $fetch_uid, $level, $last_poll); - if (!empty($shared)) { - if (!empty($embed->record->record->embeds)) { - foreach ($embed->record->record->embeds as $single) { - $shared = bluesky_add_media($single, $shared, $fetch_uid, $level, $last_poll); - } - } - Item::insert($shared); - } + $original_uri = $uri = bluesky_get_uri($embed->record->record); + $uri = bluesky_fetch_missing_post($uri, $item['uid'], $fetch_uid, $item['contact-id'], $level, $last_poll); + if ($uri) { + $shared = Post::selectFirst(['uri-id'], ['uri' => $uri, 'uid' => [$item['uid'], 0]]); + $uri_id = $shared['uri-id'] ?? 0; } - if (!empty($shared['uri-id'])) { - $item['quote-uri-id'] = $shared['uri-id']; - } - - if (!empty($embed->media)) { - $item = bluesky_add_media($embed->media, $item, $fetch_uid, $level, $last_poll); + if (!empty($uri_id)) { + $item['quote-uri-id'] = $uri_id; + } else { + Logger::debug('Quoted post could not be fetched', ['original-uri' => $original_uri, 'uri' => $uri]); } break; default: - Logger::notice('Unhandled embed type', ['type' => $embed->$type, 'embed' => $embed]); + Logger::notice('Unhandled embed type', ['uri-id' => $item['uri-id'], 'type' => $embed->$type, 'embed' => $embed]); break; } return $item; @@ -1449,6 +1435,21 @@ function bluesky_fetch_post(string $uri, int $uid): string return ''; } +function bluesky_fetch_uri_id(string $uri, int $uid): string +{ + $reply = Post::selectFirst(['uri-id'], ['uri' => $uri, 'uid' => [$uid, 0]]); + if (!empty($reply['uri-id'])) { + Logger::debug('Post with extid exists', ['uri' => $uri]); + return $reply['uri-id']; + } + $reply = Post::selectFirst(['uri-id'], ['extid' => $uri, 'uid' => [$uid, 0]]); + if (!empty($reply['uri-id'])) { + Logger::debug('Post with extid exists', ['uri' => $uri]); + return $reply['uri-id']; + } + return 0; +} + function bluesky_process_thread(stdClass $thread, int $uid, int $fetch_uid, array $cdata, int $level, int $last_poll): string { if (empty($thread->post)) { @@ -1459,27 +1460,12 @@ function bluesky_process_thread(stdClass $thread, int $uid, int $fetch_uid, arra $fetched_uri = bluesky_fetch_post($uri, $uid); if (empty($fetched_uri)) { - Logger::debug('Process missing post', ['uri' => $uri]); - $item = bluesky_get_header($thread->post, $uri, $uid, $uid); - $item = bluesky_get_content($item, $thread->post->record, $uri, $uid, $fetch_uid, $level, $last_poll); - if (!empty($item)) { - $item['post-reason'] = Item::PR_FETCHED; - - if (!empty($cdata['public'])) { - $item['causer-id'] = $cdata['public']; - } - - if (!empty($thread->post->embed)) { - $item = bluesky_add_media($thread->post->embed, $item, $uid, $level, $last_poll); - } - $id = Item::insert($item); - if (!$id) { - Logger::info('Item has not not been stored', ['uri' => $uri]); - return ''; - } - Logger::debug('Stored item', ['id' => $id, 'uri' => $uri]); + $uri_id = bluesky_process_post($thread->post, $uid, $fetch_uid, Item::PR_FETCHED, $cdata['public'], $level, $last_poll); + if ($uri_id) { + Logger::debug('Post has been processed and stored', ['uri-id' => $uri_id, 'uri' => $uri]); + return $uri; } else { - Logger::info('Post has not not been fetched', ['uri' => $uri]); + Logger::info('Post has not not been stored', ['uri' => $uri]); return ''; } } else { @@ -1502,7 +1488,7 @@ function bluesky_get_contact(stdClass $author, int $uid, int $fetch_uid): array $update = empty($contact) || $contact['updated'] < DateTimeFormat::utc('now -24 hours'); - $public_fields = $fields = bluesky_get_contact_fields($author, $fetch_uid, $update); + $public_fields = $fields = bluesky_get_contact_fields($author, $uid, $fetch_uid, $update); $public_fields['uid'] = 0; $public_fields['rel'] = Contact::NOTHING; @@ -1543,8 +1529,9 @@ function bluesky_get_contact(stdClass $author, int $uid, int $fetch_uid): array return Contact::getById($cid); } -function bluesky_get_contact_fields(stdClass $author, int $uid, bool $update): array +function bluesky_get_contact_fields(stdClass $author, int $uid, int $fetch_uid, bool $update): array { + $nick = $author->handle ?? $author->did; $fields = [ 'uid' => $uid, 'network' => Protocol::BLUESKY, @@ -1555,10 +1542,10 @@ function bluesky_get_contact_fields(stdClass $author, int $uid, bool $update): a 'pending' => false, 'url' => $author->did, 'nurl' => $author->did, - 'alias' => BLUESKY_WEB . '/profile/' . $author->handle, - 'name' => $author->displayName ?? $author->handle, - 'nick' => $author->handle, - 'addr' => $author->handle, + 'alias' => BLUESKY_WEB . '/profile/' . $nick, + 'name' => $author->displayName ?? $nick, + 'nick' => $nick, + 'addr' => $nick, ]; if (!$update) { @@ -1572,7 +1559,7 @@ function bluesky_get_contact_fields(stdClass $author, int $uid, bool $update): a $fields['gsid'] = GServer::getID($fields['baseurl'], true); } - $data = bluesky_xrpc_get($uid, 'app.bsky.actor.getProfile', ['actor' => $author->did]); + $data = bluesky_xrpc_get($fetch_uid, 'app.bsky.actor.getProfile', ['actor' => $author->did]); if (empty($data)) { Logger::debug('Error fetching contact fields', ['uid' => $uid, 'url' => $fields['url']]); return $fields; From 2b5f8e9c82c2bae768b5b38a18a4587ce34020e8 Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 23 Feb 2024 14:04:06 +0000 Subject: [PATCH 108/388] Fix coding standards --- bluesky/bluesky.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index b651238bd..5fa2f32fb 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -1019,7 +1019,7 @@ function bluesky_fetch_notifications(int $uid, int $last_poll) } else { Logger::info('Thread parent not found', ['uid' => $uid, 'parent' => $item['thr-parent'], 'uri' => $uri]); } - break; + break; case 'repost': $item = bluesky_get_header($notification, $uri, $uid, $uid); @@ -1033,7 +1033,7 @@ function bluesky_fetch_notifications(int $uid, int $last_poll) } else { Logger::info('Thread parent not found', ['uid' => $uid, 'parent' => $item['thr-parent'], 'uri' => $uri]); } - break; + break; case 'follow': $contact = bluesky_get_contact($notification->author, $uid, $uid); @@ -1531,7 +1531,7 @@ function bluesky_get_contact(stdClass $author, int $uid, int $fetch_uid): array function bluesky_get_contact_fields(stdClass $author, int $uid, int $fetch_uid, bool $update): array { - $nick = $author->handle ?? $author->did; + $nick = $author->handle ?: $author->did; $fields = [ 'uid' => $uid, 'network' => Protocol::BLUESKY, @@ -1543,7 +1543,7 @@ function bluesky_get_contact_fields(stdClass $author, int $uid, int $fetch_uid, 'url' => $author->did, 'nurl' => $author->did, 'alias' => BLUESKY_WEB . '/profile/' . $nick, - 'name' => $author->displayName ?? $nick, + 'name' => $author->displayName ?: $nick, 'nick' => $nick, 'addr' => $nick, ]; @@ -1741,7 +1741,6 @@ function bluesky_xrpc_get(int $uid, string $url, array $parameters = []): ?stdCl $data = bluesky_get(bluesky_get_user_pds($uid) . '/xrpc/' . $url, HttpClientAccept::JSON, [HttpClientOptions::HEADERS => ['Authorization' => ['Bearer ' . bluesky_get_token($uid)]]]); DI::pConfig()->set($uid, 'bluesky', 'status', is_null($data) ? BLUEKSY_STATUS_API_FAIL : BLUEKSY_STATUS_SUCCESS); return $data; - } function bluesky_get(string $url, string $accept_content = HttpClientAccept::DEFAULT, array $opts = []): ?stdClass From bcef83e14852d4bcab31fcc533a05ec96ebfcfb8 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 24 Feb 2024 06:48:19 +0000 Subject: [PATCH 109/388] Set post reasons --- bluesky/bluesky.php | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index 5fa2f32fb..7da7d6b5e 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -183,7 +183,7 @@ function bluesky_item_by_link(array &$hookData) $uri = 'at://' . $did . '/app.bsky.feed.post/' . $matches[2]; - $uri = bluesky_fetch_missing_post($uri, $hookData['uid'], $hookData['uid'], 0, 0); + $uri = bluesky_fetch_missing_post($uri, $hookData['uid'], $hookData['uid'], Item::PR_FETCHED, 0, 0, 0); Logger::debug('Got post', ['profile' => $matches[1], 'cid' => $matches[2], 'result' => $uri]); if (!empty($uri)) { $item = Post::selectFirst(['id'], ['uri' => $uri, 'uid' => $hookData['uid']]); @@ -1012,7 +1012,7 @@ function bluesky_fetch_notifications(int $uid, int $last_poll) $item['gravity'] = Item::GRAVITY_ACTIVITY; $item['body'] = $item['verb'] = Activity::LIKE; $item['thr-parent'] = bluesky_get_uri($notification->record->subject); - $item['thr-parent'] = bluesky_fetch_missing_post($item['thr-parent'], $uid, $uid, $item['contact-id'], 0, $last_poll); + $item['thr-parent'] = bluesky_fetch_missing_post($item['thr-parent'], $uid, $uid, Item::PR_FETCHED, $item['contact-id'], 0, $last_poll); if (!empty($item['thr-parent'])) { $data = Item::insert($item); Logger::debug('Got like', ['uid' => $uid, 'result' => $data, 'uri' => $uri]); @@ -1026,7 +1026,7 @@ function bluesky_fetch_notifications(int $uid, int $last_poll) $item['gravity'] = Item::GRAVITY_ACTIVITY; $item['body'] = $item['verb'] = Activity::ANNOUNCE; $item['thr-parent'] = bluesky_get_uri($notification->record->subject); - $item['thr-parent'] = bluesky_fetch_missing_post($item['thr-parent'], $uid, $uid, $item['contact-id'], 0, $last_poll); + $item['thr-parent'] = bluesky_fetch_missing_post($item['thr-parent'], $uid, $uid, Item::PR_FETCHED, $item['contact-id'], 0, $last_poll); if (!empty($item['thr-parent'])) { $data = Item::insert($item); Logger::debug('Got repost', ['uid' => $uid, 'result' => $data, 'uri' => $uri]); @@ -1042,19 +1042,19 @@ function bluesky_fetch_notifications(int $uid, int $last_poll) case 'mention': $contact = bluesky_get_contact($notification->author, 0, $uid); - $result = bluesky_fetch_missing_post($uri, $uid, $uid, $contact['id'], 0, $last_poll); + $result = bluesky_fetch_missing_post($uri, $uid, $uid, Item::PR_TO, $contact['id'], 0, $last_poll); Logger::debug('Got mention', ['uid' => $uid, 'nick' => $contact['nick'], 'result' => $result, 'uri' => $uri]); break; case 'reply': $contact = bluesky_get_contact($notification->author, 0, $uid); - $result = bluesky_fetch_missing_post($uri, $uid, $uid, $contact['id'], 0, $last_poll); + $result = bluesky_fetch_missing_post($uri, $uid, $uid, Item::PR_COMMENT, $contact['id'], 0, $last_poll); Logger::debug('Got reply', ['uid' => $uid, 'nick' => $contact['nick'], 'result' => $result, 'uri' => $uri]); break; case 'quote': $contact = bluesky_get_contact($notification->author, 0, $uid); - $result = bluesky_fetch_missing_post($uri, $uid, $uid, $contact['id'], 0, $last_poll); + $result = bluesky_fetch_missing_post($uri, $uid, $uid, Item::PR_PUSHED, $contact['id'], 0, $last_poll); Logger::debug('Got quote', ['uid' => $uid, 'nick' => $contact['nick'], 'result' => $result, 'uri' => $uri]); break; @@ -1187,7 +1187,7 @@ function bluesky_get_content(array $item, stdClass $record, string $uri, int $ui if (!empty($record->reply)) { $item['parent-uri'] = bluesky_get_uri($record->reply->root); if ($item['parent-uri'] != $uri) { - $item['parent-uri'] = bluesky_fetch_missing_post($item['parent-uri'], $uid, $fetch_uid, $item['contact-id'], $level, $last_poll); + $item['parent-uri'] = bluesky_fetch_missing_post($item['parent-uri'], $uid, $fetch_uid, Item::PR_COMPLETION, $item['contact-id'], $level, $last_poll); if (empty($item['parent-uri'])) { return []; } @@ -1195,7 +1195,7 @@ function bluesky_get_content(array $item, stdClass $record, string $uri, int $ui $item['thr-parent'] = bluesky_get_uri($record->reply->parent); if (!in_array($item['thr-parent'], [$uri, $item['parent-uri']])) { - $item['thr-parent'] = bluesky_fetch_missing_post($item['thr-parent'], $uid, $fetch_uid, $item['contact-id'], $level, $last_poll, $item['parent-uri']); + $item['thr-parent'] = bluesky_fetch_missing_post($item['thr-parent'], $uid, $fetch_uid, Item::PR_COMPLETION, $item['contact-id'], $level, $last_poll, $item['parent-uri']); if (empty($item['thr-parent'])) { return []; } @@ -1300,7 +1300,7 @@ function bluesky_add_media(stdClass $embed, array $item, int $fetch_uid, int $le case 'app.bsky.embed.record#view': $original_uri = $uri = bluesky_get_uri($embed->record); - $uri = bluesky_fetch_missing_post($uri, $item['uid'], $fetch_uid, $item['contact-id'], $level, $last_poll); + $uri = bluesky_fetch_missing_post($uri, $item['uid'], $fetch_uid, Item::PR_FETCHED, $item['contact-id'], $level, $last_poll); if ($uri) { $shared = Post::selectFirst(['uri-id'], ['uri' => $uri, 'uid' => [$item['uid'], 0]]); $uri_id = $shared['uri-id'] ?? 0; @@ -1314,7 +1314,7 @@ function bluesky_add_media(stdClass $embed, array $item, int $fetch_uid, int $le case 'app.bsky.embed.recordWithMedia#view': $original_uri = $uri = bluesky_get_uri($embed->record->record); - $uri = bluesky_fetch_missing_post($uri, $item['uid'], $fetch_uid, $item['contact-id'], $level, $last_poll); + $uri = bluesky_fetch_missing_post($uri, $item['uid'], $fetch_uid, Item::PR_FETCHED, $item['contact-id'], $level, $last_poll); if ($uri) { $shared = Post::selectFirst(['uri-id'], ['uri' => $uri, 'uid' => [$item['uid'], 0]]); $uri_id = $shared['uri-id'] ?? 0; @@ -1385,7 +1385,7 @@ function bluesky_get_uri_parts(string $uri): ?stdClass return $class; } -function bluesky_fetch_missing_post(string $uri, int $uid, int $fetch_uid, int $causer, int $level, int $last_poll = 0, string $fallback = ''): string +function bluesky_fetch_missing_post(string $uri, int $uid, int $fetch_uid, int $post_reason, int $causer, int $level, int $last_poll, string $fallback = ''): string { $fetched_uri = bluesky_fetch_post($uri, $uid); if (!empty($fetched_uri)) { @@ -1413,11 +1413,10 @@ function bluesky_fetch_missing_post(string $uri, int $uid, int $fetch_uid, int $ if ($causer != 0) { $cdata = Contact::getPublicAndUserContactID($causer, $uid); - } else { - $cdata = []; + $causer = $cdata['public'] ?? 0; } - return bluesky_process_thread($data->thread, $uid, $fetch_uid, $cdata, $level, $last_poll); + return bluesky_process_thread($data->thread, $uid, $fetch_uid, $post_reason, $causer, $level, $last_poll); } function bluesky_fetch_post(string $uri, int $uid): string @@ -1450,7 +1449,7 @@ function bluesky_fetch_uri_id(string $uri, int $uid): string return 0; } -function bluesky_process_thread(stdClass $thread, int $uid, int $fetch_uid, array $cdata, int $level, int $last_poll): string +function bluesky_process_thread(stdClass $thread, int $uid, int $fetch_uid, int $post_reason, int $causer, int $level, int $last_poll): string { if (empty($thread->post)) { Logger::info('Invalid post', ['post' => $thread]); @@ -1460,7 +1459,7 @@ function bluesky_process_thread(stdClass $thread, int $uid, int $fetch_uid, arra $fetched_uri = bluesky_fetch_post($uri, $uid); if (empty($fetched_uri)) { - $uri_id = bluesky_process_post($thread->post, $uid, $fetch_uid, Item::PR_FETCHED, $cdata['public'], $level, $last_poll); + $uri_id = bluesky_process_post($thread->post, $uid, $fetch_uid, $post_reason, $causer, $level, $last_poll); if ($uri_id) { Logger::debug('Post has been processed and stored', ['uri-id' => $uri_id, 'uri' => $uri]); return $uri; @@ -1474,7 +1473,7 @@ function bluesky_process_thread(stdClass $thread, int $uid, int $fetch_uid, arra } foreach ($thread->replies ?? [] as $reply) { - $reply_uri = bluesky_process_thread($reply, $uid, $fetch_uid, $cdata, $level, $last_poll); + $reply_uri = bluesky_process_thread($reply, $uid, $fetch_uid, Item::PR_COMPLETION, $causer, $level, $last_poll); Logger::debug('Reply has been processed', ['uri' => $uri, 'reply' => $reply_uri]); } @@ -1531,7 +1530,7 @@ function bluesky_get_contact(stdClass $author, int $uid, int $fetch_uid): array function bluesky_get_contact_fields(stdClass $author, int $uid, int $fetch_uid, bool $update): array { - $nick = $author->handle ?: $author->did; + $nick = $author->handle ?? $author->did; $fields = [ 'uid' => $uid, 'network' => Protocol::BLUESKY, @@ -1543,7 +1542,7 @@ function bluesky_get_contact_fields(stdClass $author, int $uid, int $fetch_uid, 'url' => $author->did, 'nurl' => $author->did, 'alias' => BLUESKY_WEB . '/profile/' . $nick, - 'name' => $author->displayName ?: $nick, + 'name' => $author->displayName ?? $nick, 'nick' => $nick, 'addr' => $nick, ]; From 6d578d14952251e4826103d8ab035c8dbd9dee69 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 24 Feb 2024 08:26:06 +0000 Subject: [PATCH 110/388] Changed post reason --- bluesky/bluesky.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index 7da7d6b5e..5e3de1a00 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -1187,7 +1187,7 @@ function bluesky_get_content(array $item, stdClass $record, string $uri, int $ui if (!empty($record->reply)) { $item['parent-uri'] = bluesky_get_uri($record->reply->root); if ($item['parent-uri'] != $uri) { - $item['parent-uri'] = bluesky_fetch_missing_post($item['parent-uri'], $uid, $fetch_uid, Item::PR_COMPLETION, $item['contact-id'], $level, $last_poll); + $item['parent-uri'] = bluesky_fetch_missing_post($item['parent-uri'], $uid, $fetch_uid, Item::PR_FETCHED, $item['contact-id'], $level, $last_poll); if (empty($item['parent-uri'])) { return []; } @@ -1195,7 +1195,7 @@ function bluesky_get_content(array $item, stdClass $record, string $uri, int $ui $item['thr-parent'] = bluesky_get_uri($record->reply->parent); if (!in_array($item['thr-parent'], [$uri, $item['parent-uri']])) { - $item['thr-parent'] = bluesky_fetch_missing_post($item['thr-parent'], $uid, $fetch_uid, Item::PR_COMPLETION, $item['contact-id'], $level, $last_poll, $item['parent-uri']); + $item['thr-parent'] = bluesky_fetch_missing_post($item['thr-parent'], $uid, $fetch_uid, Item::PR_FETCHED, $item['contact-id'], $level, $last_poll, $item['parent-uri']); if (empty($item['thr-parent'])) { return []; } @@ -1473,7 +1473,7 @@ function bluesky_process_thread(stdClass $thread, int $uid, int $fetch_uid, int } foreach ($thread->replies ?? [] as $reply) { - $reply_uri = bluesky_process_thread($reply, $uid, $fetch_uid, Item::PR_COMPLETION, $causer, $level, $last_poll); + $reply_uri = bluesky_process_thread($reply, $uid, $fetch_uid, Item::PR_FETCHED, $causer, $level, $last_poll); Logger::debug('Reply has been processed', ['uri' => $uri, 'reply' => $reply_uri]); } From 346e22c5f5ec44716c28f8447ba9844a1b375f14 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 24 Feb 2024 08:28:34 +0000 Subject: [PATCH 111/388] Tumblr: Fixed token exchange --- tumblr/tumblr.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tumblr/tumblr.php b/tumblr/tumblr.php index d6508ff87..12e9e5e03 100644 --- a/tumblr/tumblr.php +++ b/tumblr/tumblr.php @@ -1479,7 +1479,7 @@ function tumblr_exchange_token(int $uid): stdClass ]); $response = $client->post('oauth2/exchange', ['auth' => 'oauth']); - return json_decode($response->getBodyString()->getContents()); + return json_decode($response->getBody()->getContents()); } catch (RequestException $exception) { Logger::notice('Exchange failed', ['code' => $exception->getCode(), 'message' => $exception->getMessage()]); return new stdClass; From 7580054394a069a754c8e64acff1b036caba3950 Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 1 Mar 2024 05:53:42 +0000 Subject: [PATCH 112/388] Bluesky: fix problems with links and hashtags --- bluesky/bluesky.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index 5e3de1a00..db60d1a4d 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -764,7 +764,7 @@ function bluesky_get_urls(string $body): array if (preg_match_all("/#\[url\=(https?:.*?)\](.*?)\[\/url\]/ism", $body, $matches, PREG_SET_ORDER)) { foreach ($matches as $match) { $text = '#' . $match[2]; - $urls[] = ['tag' => $match[2], 'text' => $text, 'hash' => $text]; + $urls[strpos($body, $match[0])] = ['tag' => $match[2], 'text' => $text, 'hash' => $text]; $body = str_replace($match[0], $text, $body); } } @@ -774,7 +774,7 @@ function bluesky_get_urls(string $body): array foreach ($matches as $match) { $text = Strings::getStyledURL($match[1]); $hash = bluesky_get_hash_for_url($match[0], mb_strlen($text)); - $urls[] = ['url' => $match[1], 'text' => $text, 'hash' => $hash]; + $urls[strpos($body, $match[0])] = ['url' => $match[1], 'text' => $text, 'hash' => $hash]; $body = str_replace($match[0], $hash, $body); } } @@ -789,17 +789,19 @@ function bluesky_get_urls(string $body): array } if (mb_strlen($text) < 100) { $hash = bluesky_get_hash_for_url($match[0], mb_strlen($text)); - $urls[] = ['url' => $match[1], 'text' => $text, 'hash' => $hash]; + $urls[strpos($body, $match[0])] = ['url' => $match[1], 'text' => $text, 'hash' => $hash]; $body = str_replace($match[0], $hash, $body); } else { $text = Strings::getStyledURL($match[1]); $hash = bluesky_get_hash_for_url($match[0], mb_strlen($text)); - $urls[] = ['url' => $match[1], 'text' => $text, 'hash' => $hash]; + $urls[strpos($body, $match[0])] = ['url' => $match[1], 'text' => $text, 'hash' => $hash]; $body = str_replace($match[0], $text . ' ' . $hash, $body); } } } + asort($urls); + return ['body' => $body, 'urls' => $urls]; } From 5f7233fd20b85560ce903f7f26df405daf0414e2 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 28 Feb 2024 03:05:57 +0000 Subject: [PATCH 113/388] Bluesky: Enabled support for Friendica handles --- bluesky/bluesky.php | 56 +++++++++++++----- bluesky/lang/C/messages.po | 73 +++++++++++++++++------- bluesky/templates/admin.tpl | 2 + bluesky/templates/connector_settings.tpl | 1 + 4 files changed, 96 insertions(+), 36 deletions(-) create mode 100644 bluesky/templates/admin.tpl diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index db60d1a4d..5fc0a4f0a 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -42,6 +42,7 @@ use Friendica\Model\ItemURI; use Friendica\Model\Photo; use Friendica\Model\Post; use Friendica\Model\Tag; +use Friendica\Model\User; use Friendica\Network\HTTPClient\Client\HttpClientAccept; use Friendica\Network\HTTPClient\Client\HttpClientOptions; use Friendica\Object\Image; @@ -316,20 +317,44 @@ function bluesky_unblock(array &$hook_data) $hook_data['result'] = true; } +function bluesky_addon_admin(string &$o) +{ + $t = Renderer::getMarkupTemplate('admin.tpl', 'addon/bluesky/'); + + $o = Renderer::replaceMacros($t, [ + '$submit' => DI::l10n()->t('Save Settings'), + '$friendica_handles' => ['friendica_handles', DI::l10n()->t('Allow your users to use your hostname for their Bluesky handles'), DI::config()->get('bluesky', 'friendica_handles'), DI::l10n()->t('Before enabling this option, you have to download and configure the bluesky-handles repository on your system. See https://git.friendi.ca/heluecht/bluesky-handles')], + ]); +} + +function bluesky_addon_admin_post() +{ + DI::config()->set('bluesky', 'friendica_handles', (bool)$_POST['friendica_handles']); +} + function bluesky_settings(array &$data) { if (!DI::userSession()->getLocalUserId()) { return; } - $enabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'post') ?? false; - $def_enabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'post_by_default') ?? false; - $pds = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'pds'); - $handle = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'handle'); - $did = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'did'); - $token = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'access_token'); - $import = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'import') ?? false; - $import_feeds = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'import_feeds') ?? false; + $enabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'post') ?? false; + $def_enabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'post_by_default') ?? false; + $pds = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'pds'); + $handle = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'handle'); + $did = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'did'); + $token = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'access_token'); + $import = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'import') ?? false; + $import_feeds = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'import_feeds') ?? false; + $custom_handle = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'friendica_handle') ?? false; + + if (DI::config()->get('bluesky', 'friendica_handles')) { + $self = User::getById(DI::userSession()->getLocalUserId(), ['nickname']); + $handle = $self['nickname'] . '.' . DI::baseUrl()->getHost(); + $friendica_handle = ['bluesky_friendica_handle', DI::l10n()->t('Allow to use %s as your Bluesky handle.', $handle), $custom_handle, DI::l10n()->t('When enabled, you can use %s as your Bluesky handle. After you enabled this option, please go to https://bsky.app/settings and select to change your handle. Select that you have got your own domain. Then enter %s and select "No DNS Panel". Then select "Verify Text File".', $handle, $handle)]; + } else { + $friendica_handle = []; + } $t = Renderer::getMarkupTemplate('connector_settings.tpl', 'addon/bluesky/'); $html = Renderer::replaceMacros($t, [ @@ -337,6 +362,7 @@ function bluesky_settings(array &$data) '$bydefault' => ['bluesky_bydefault', DI::l10n()->t('Post to Bluesky by default'), $def_enabled], '$import' => ['bluesky_import', DI::l10n()->t('Import the remote timeline'), $import], '$import_feeds' => ['bluesky_import_feeds', DI::l10n()->t('Import the pinned feeds'), $import_feeds, DI::l10n()->t('When activated, Posts will be imported from all the feeds that you pinned in Bluesky.')], + '$custom_handle' => $friendica_handle, '$pds' => ['bluesky_pds', DI::l10n()->t('Personal Data Server'), $pds, DI::l10n()->t('The personal data server (PDS) is the system that hosts your profile.'), '', 'readonly'], '$handle' => ['bluesky_handle', DI::l10n()->t('Bluesky handle'), $handle], '$did' => ['bluesky_did', DI::l10n()->t('Bluesky DID'), $did, DI::l10n()->t('This is the unique identifier. It will be fetched automatically, when the handle is entered.'), '', 'readonly'], @@ -404,11 +430,12 @@ function bluesky_settings_post(array &$b) $handle = trim($_POST['bluesky_handle'], ' @'); - DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'post', intval($_POST['bluesky'])); - DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'post_by_default', intval($_POST['bluesky_bydefault'])); - DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'handle', $handle); - DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'import', intval($_POST['bluesky_import'])); - DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'import_feeds', intval($_POST['bluesky_import_feeds'])); + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'post', intval($_POST['bluesky'])); + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'post_by_default', intval($_POST['bluesky_bydefault'])); + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'handle', $handle); + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'import', intval($_POST['bluesky_import'])); + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'import_feeds', intval($_POST['bluesky_import_feeds'])); + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'friendica_handle', intval($_POST['bluesky_friendica_handle'])); if (!empty($handle)) { if (empty($old_did) || $old_handle != $handle) { @@ -1533,6 +1560,7 @@ function bluesky_get_contact(stdClass $author, int $uid, int $fetch_uid): array function bluesky_get_contact_fields(stdClass $author, int $uid, int $fetch_uid, bool $update): array { $nick = $author->handle ?? $author->did; + $name = $author->displayName ?? $nick; $fields = [ 'uid' => $uid, 'network' => Protocol::BLUESKY, @@ -1544,7 +1572,7 @@ function bluesky_get_contact_fields(stdClass $author, int $uid, int $fetch_uid, 'url' => $author->did, 'nurl' => $author->did, 'alias' => BLUESKY_WEB . '/profile/' . $nick, - 'name' => $author->displayName ?? $nick, + 'name' => $name ?: $nick, 'nick' => $nick, 'addr' => $nick, ]; diff --git a/bluesky/lang/C/messages.po b/bluesky/lang/C/messages.po index 132e608a1..0d69cc102 100644 --- a/bluesky/lang/C/messages.po +++ b/bluesky/lang/C/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-12-06 06:30+0000\n" +"POT-Creation-Date: 2024-02-28 03:05+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,100 +17,129 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: bluesky.php:336 +#: bluesky.php:325 +msgid "Save Settings" +msgstr "" + +#: bluesky.php:326 +msgid "Allow your users to use your hostname for their Bluesky handles" +msgstr "" + +#: bluesky.php:326 +msgid "" +"Before enabling this option, you have to download and configure the bluesky-" +"handles repository on your system. See https://git.friendi.ca/heluecht/" +"bluesky-handles" +msgstr "" + +#: bluesky.php:354 +#, php-format +msgid "Allow to use %s as your Bluesky handle." +msgstr "" + +#: bluesky.php:354 +#, php-format +msgid "" +"When enabled, you can use %s as your Bluesky handle. After you enabled this " +"option, please go to https://bsky.app/settings and select to change your " +"handle. Select that you have got your own domain. Then enter %s and select " +"\"No DNS Panel\". Then select \"Verify Text File\"." +msgstr "" + +#: bluesky.php:361 msgid "Enable Bluesky Post Addon" msgstr "" -#: bluesky.php:337 +#: bluesky.php:362 msgid "Post to Bluesky by default" msgstr "" -#: bluesky.php:338 +#: bluesky.php:363 msgid "Import the remote timeline" msgstr "" -#: bluesky.php:339 +#: bluesky.php:364 msgid "Import the pinned feeds" msgstr "" -#: bluesky.php:339 +#: bluesky.php:364 msgid "" "When activated, Posts will be imported from all the feeds that you pinned in " "Bluesky." msgstr "" -#: bluesky.php:340 +#: bluesky.php:366 msgid "Personal Data Server" msgstr "" -#: bluesky.php:340 +#: bluesky.php:366 msgid "The personal data server (PDS) is the system that hosts your profile." msgstr "" -#: bluesky.php:341 +#: bluesky.php:367 msgid "Bluesky handle" msgstr "" -#: bluesky.php:342 +#: bluesky.php:368 msgid "Bluesky DID" msgstr "" -#: bluesky.php:342 +#: bluesky.php:368 msgid "" "This is the unique identifier. It will be fetched automatically, when the " "handle is entered." msgstr "" -#: bluesky.php:343 +#: bluesky.php:369 msgid "Bluesky app password" msgstr "" -#: bluesky.php:343 +#: bluesky.php:369 msgid "" "Please don't add your real password here, but instead create a specific app " "password in the Bluesky settings." msgstr "" -#: bluesky.php:349 +#: bluesky.php:375 msgid "Bluesky Import/Export" msgstr "" -#: bluesky.php:359 +#: bluesky.php:385 msgid "" "You are not authenticated. Please enter your handle and the app password." msgstr "" -#: bluesky.php:379 +#: bluesky.php:405 msgid "" "You are authenticated to Bluesky. For security reasons the password isn't " "stored." msgstr "" -#: bluesky.php:381 +#: bluesky.php:407 msgid "" "The communication with the personal data server service (PDS) is established." msgstr "" -#: bluesky.php:383 +#: bluesky.php:409 msgid "Communication issues with the personal data server service (PDS)." msgstr "" -#: bluesky.php:385 +#: bluesky.php:411 msgid "" "The DID for the provided handle could not be detected. Please check if you " "entered the correct handle." msgstr "" -#: bluesky.php:387 +#: bluesky.php:413 msgid "The personal data server service (PDS) could not be detected." msgstr "" -#: bluesky.php:389 +#: bluesky.php:415 msgid "" "The authentication with the provided handle and password failed. Please " "check if you entered the correct password." msgstr "" -#: bluesky.php:457 +#: bluesky.php:484 msgid "Post to Bluesky" msgstr "" diff --git a/bluesky/templates/admin.tpl b/bluesky/templates/admin.tpl new file mode 100644 index 000000000..7b752a882 --- /dev/null +++ b/bluesky/templates/admin.tpl @@ -0,0 +1,2 @@ +{{include file="field_checkbox.tpl" field=$friendica_handles}} +
diff --git a/bluesky/templates/connector_settings.tpl b/bluesky/templates/connector_settings.tpl index db5ac5d5b..f50e9cc61 100644 --- a/bluesky/templates/connector_settings.tpl +++ b/bluesky/templates/connector_settings.tpl @@ -3,6 +3,7 @@ {{include file="field_checkbox.tpl" field=$bydefault}} {{include file="field_checkbox.tpl" field=$import}} {{include file="field_checkbox.tpl" field=$import_feeds}} +{{include file="field_checkbox.tpl" field=$custom_handle}} {{include file="field_input.tpl" field=$pds}} {{include file="field_input.tpl" field=$handle}} {{include file="field_input.tpl" field=$did}} From 2ee78d2f0b771871817440e22abf96de4bc45561 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 2 Mar 2024 13:32:11 +0000 Subject: [PATCH 114/388] Bluesky: Handle media links and shared posts --- bluesky/bluesky.php | 86 ++++++++++++++++++++++-- bluesky/templates/connector_settings.tpl | 4 +- 2 files changed, 82 insertions(+), 8 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index 5fc0a4f0a..cdedb07ab 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -717,8 +717,24 @@ function bluesky_create_post(array $item, stdClass $root = null, stdClass $paren $language = ''; } - $did = DI::pConfig()->get($uid, 'bluesky', 'did'); - $urls = bluesky_get_urls(Post\Media::removeFromBody($item['body'])); + $item['body'] = Post\Media::removeFromBody($item['body']); + + foreach (Post\Media::getByURIId($item['uri-id'], [Post\Media::AUDIO, Post\Media::VIDEO, Post\Media::ACTIVITY]) as $media) { + if (strpos($item['body'], $media['url']) === false) { + $item['body'] .= "\n[url]" . $media['url'] . "[/url]\n"; + } + } + + if (!empty($item['quote-uri-id'])) { + $quote = Post::selectFirstPost(['uri', 'plink'], ['uri-id' => $item['quote-uri-id']]); + if (!empty($quote)) { + if ((strpos($item['body'], $quote['plink'] ?: $quote['uri']) === false) && (strpos($item['body'], $quote['uri']) === false)) { + $item['body'] .= "\n[url]" . ($quote['plink'] ?: $quote['uri']) . "[/url]\n"; + } + } + } + + $urls = bluesky_get_urls($item['body']); $item['body'] = $urls['body']; $msg = Plaintext::getPost($item, 300, false, BBCode::BLUESKY); @@ -756,7 +772,7 @@ function bluesky_create_post(array $item, stdClass $root = null, stdClass $paren $post = [ 'collection' => 'app.bsky.feed.post', - 'repo' => $did, + 'repo' => DI::pConfig()->get($uid, 'bluesky', 'did'), 'record' => $record ]; @@ -1646,13 +1662,59 @@ function bluesky_get_preferences(int $uid): stdClass return $data; } -function bluesky_get_did(string $handle): string +function bluesky_get_did_by_wellknown(string $handle): string { - $data = bluesky_get(BLUESKY_PDS . '/xrpc/com.atproto.identity.resolveHandle?handle=' . urlencode($handle)); - if (empty($data)) { + $curlResult = DI::httpClient()->get('http://' . $handle . '/.well-known/atproto-did'); + if ($curlResult->isSuccess() && substr($curlResult->getBodyString(), 0, 4) == 'did:') { + $did = $curlResult->getBodyString(); + if (!bluesky_valid_did($did, $handle)) { + Logger::notice('Invalid DID', ['handle' => $handle, 'did' => $did]); + return ''; + } + Logger::debug('Got DID by wellknown', ['handle' => $handle, 'did' => $did]); + return $did; + } + return ''; +} + +function bluesky_get_did_by_dns(string $handle): string +{ + $records = @dns_get_record('_atproto.' . $handle . '.', DNS_TXT); + if (empty($records)) { return ''; } - Logger::debug('Got DID', ['return' => $data]); + foreach ($records as $record) { + if (!empty($record['txt']) && substr($record['txt'], 0, 4) == 'did=') { + $did = substr($record['txt'], 4); + if (!bluesky_valid_did($did, $handle)) { + Logger::notice('Invalid DID', ['handle' => $handle, 'did' => $did]); + return ''; + } + Logger::debug('Got DID by DNS', ['handle' => $handle, 'did' => $did]); + return $did; + } + } + return ''; +} + +function bluesky_get_did(string $handle): string +{ + // Deactivated at the moment, since it isn't reliable by now + //$did = bluesky_get_did_by_dns($handle); + //if ($did != '') { + // return $did; + //} + + //$did = bluesky_get_did_by_wellknown($handle); + //if ($did != '') { + // return $did; + //} + + $data = bluesky_get(BLUESKY_PDS . '/xrpc/com.atproto.identity.resolveHandle?handle=' . urlencode($handle)); + if (empty($data) || empty($data->did)) { + return ''; + } + Logger::debug('Got DID by PDS call', ['handle' => $handle, 'did' => $data->did]); return $data->did; } @@ -1688,6 +1750,16 @@ function bluesky_get_pds(string $did): ?string return null; } +function bluesky_valid_did(string $did, string $handle): bool +{ + $data = bluesky_get(BLUESKY_DIRECTORY . '/' . $did); + if (empty($data) || empty($data->alsoKnownAs)) { + return false; + } + + return in_array('at://' . $handle, $data->alsoKnownAs); +} + function bluesky_get_token(int $uid): string { $token = DI::pConfig()->get($uid, 'bluesky', 'access_token'); diff --git a/bluesky/templates/connector_settings.tpl b/bluesky/templates/connector_settings.tpl index f50e9cc61..3ebea827b 100644 --- a/bluesky/templates/connector_settings.tpl +++ b/bluesky/templates/connector_settings.tpl @@ -3,7 +3,9 @@ {{include file="field_checkbox.tpl" field=$bydefault}} {{include file="field_checkbox.tpl" field=$import}} {{include file="field_checkbox.tpl" field=$import_feeds}} -{{include file="field_checkbox.tpl" field=$custom_handle}} +{{if $custom_handle}} + {{include file="field_checkbox.tpl" field=$custom_handle}} +{{/if}} {{include file="field_input.tpl" field=$pds}} {{include file="field_input.tpl" field=$handle}} {{include file="field_input.tpl" field=$did}} From 58cb9337790883569cdee8c788e415e923dbf2d4 Mon Sep 17 00:00:00 2001 From: Matthew Exon Date: Sun, 3 Mar 2024 17:47:42 +0800 Subject: [PATCH 115/388] do not mail dislike messages --- mailstream/mailstream.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mailstream/mailstream.php b/mailstream/mailstream.php index 968ee4c02..b513cf367 100644 --- a/mailstream/mailstream.php +++ b/mailstream/mailstream.php @@ -169,6 +169,10 @@ function mailstream_post_hook(array &$item) Logger::debug('mailstream: like item ' . $item['id']); return; } + if ($item['verb'] == Activity::DISLIKE) { + Logger::debug('mailstream: dislike item ' . $item['id']); + return; + } } $message_id = mailstream_generate_id($item['uri']); From dcafad573ea4320262e90e6107cbbd36faada2e0 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 3 Mar 2024 12:02:53 +0000 Subject: [PATCH 116/388] Pnut: Client Id/Secret can be set by admins --- pnut/README.md | 5 +- pnut/lang/C/messages.po | 74 +++++++++++++++++++++++ pnut/pnut.php | 86 ++++++++++++++++++--------- pnut/templates/admin.tpl | 3 + pnut/templates/connector_settings.tpl | 8 ++- 5 files changed, 145 insertions(+), 31 deletions(-) create mode 100644 pnut/lang/C/messages.po create mode 100644 pnut/templates/admin.tpl diff --git a/pnut/README.md b/pnut/README.md index d935efe7f..6f6a9224f 100644 --- a/pnut/README.md +++ b/pnut/README.md @@ -2,4 +2,7 @@ With this addon to friendica you can give your users the possibility to post their *public* messages to pnut.io. -No setup is needed for the admins to make it work for their users. +No setup is needed for the admins to make it work for their users, however it is possible for the admin to create a client, so that the users don't have to. + +To do so, go to https://pnut.io/dev and scroll down to "Create New Client". Enter a name of your choice and enter your Friendica host name as the website. Use https://(yourhost.name)/pnut/connect as a redirect url, replace "(yourhost.name)" with the host name of your system. +Limit the scope to "basic,files,follow,polls,presence,stream,update_profile,write_post" \ No newline at end of file diff --git a/pnut/lang/C/messages.po b/pnut/lang/C/messages.po new file mode 100644 index 000000000..89b065fdc --- /dev/null +++ b/pnut/lang/C/messages.po @@ -0,0 +1,74 @@ +# ADDON pnut +# Copyright (C) +# This file is distributed under the same license as the Friendica pnut addon package. +# +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-03-03 11:53+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: pnut.php:42 +msgid "Permission denied." +msgstr "" + +#: pnut.php:79 +msgid "You are now authenticated with pnut.io." +msgstr "" + +#: pnut.php:82 +msgid "Error fetching token. Please try again." +msgstr "" + +#: pnut.php:85 +msgid "return to the connector page" +msgstr "" + +#: pnut.php:103 +msgid "Save Settings" +msgstr "" + +#: pnut.php:104 pnut.php:150 +msgid "Client ID" +msgstr "" + +#: pnut.php:105 pnut.php:151 +msgid "Client Secret" +msgstr "" + +#: pnut.php:139 +msgid "Authenticate with pnut.io" +msgstr "" + +#: pnut.php:143 +msgid "Disconnect" +msgstr "" + +#: pnut.php:148 +msgid "Enable Pnut Post Addon" +msgstr "" + +#: pnut.php:149 +msgid "Post to Pnut by default" +msgstr "" + +#: pnut.php:152 +msgid "Access Token" +msgstr "" + +#: pnut.php:161 +msgid "Pnut Export" +msgstr "" + +#: pnut.php:203 +msgid "Post to Pnut" +msgstr "" diff --git a/pnut/pnut.php b/pnut/pnut.php index f278fb557..e84f208bc 100644 --- a/pnut/pnut.php +++ b/pnut/pnut.php @@ -2,7 +2,7 @@ /** * Name: Pnut Connector * Description: Post to pnut.io - * Version: 0.1.1 + * Version: 0.1.2 * Author: Morgan McMillian * Status: In Development */ @@ -18,12 +18,10 @@ use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\Core\System; use Friendica\DI; -use Friendica\Model\Item; use Friendica\Model\Photo; -use Friendica\Object\Image; -use Friendica\Network\HTTPClient\Client\HttpClientAccept; -use Friendica\Network\HTTPClient\Client\HttpClientOptions; -use Friendica\Util\DateTimeFormat; +use phpnut\phpnutException; + +const PNUT_LIMIT = 256; function pnut_install() { @@ -63,19 +61,25 @@ function pnut_content() function pnut_connect() { - $client_id = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'pnut', 'client_id'); - $client_secret = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'pnut', 'client_secret'); + $client_id = DI::config()->get('pnut', 'client_id'); + $client_secret = DI::config()->get('pnut', 'client_secret'); + + if (empty($client_id) || empty($client_secret)) { + $client_id = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'pnut', 'client_id'); + $client_secret = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'pnut', 'client_secret'); + } + $callback_url = DI::baseUrl() . '/pnut/connect'; $nut = new phpnut\phpnut($client_id, $client_secret); try { $token = $nut->getAccessToken($callback_url); - Logger::debug('TOKEN', [$token]); + Logger::debug('Got Token', [$token]); $o = DI::l10n()->t('You are now authenticated with pnut.io.'); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'pnut', 'access_token', $token); } catch (phpnutException $e) { - $o = DI::l10n()->t('Error fetching token. Please try again.'); + $o = DI::l10n()->t('Error fetching token. Please try again.', ['code' => $e->getCode(), 'message' => $e->getMessage()]); } $o .= '
' . DI::l10n()->t("return to the connector page").''; @@ -88,6 +92,26 @@ function pnut_load_config(ConfigFileManager $loader) DI::app()->getConfigCache()->load($loader->loadAddonConfig('pnut'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); } +function pnut_addon_admin(string &$o) +{ + $client_id = DI::config()->get('pnut', 'client_id'); + $client_secret = DI::config()->get('pnut', 'client_secret'); + + $t = Renderer::getMarkupTemplate('admin.tpl', 'addon/pnut/'); + + $o = Renderer::replaceMacros($t, [ + '$submit' => DI::l10n()->t('Save Settings'), + '$client_id' => ['pnut_client_id', DI::l10n()->t('Client ID'), $client_id], + '$client_secret' => ['pnut_client_secret', DI::l10n()->t('Client Secret'), $client_secret], + ]); +} + +function pnut_addon_admin_post() +{ + DI::config()->set('pnut', 'client_id', $_POST['pnut_client_id']); + DI::config()->set('pnut', 'client_secret', $_POST['pnut_client_secret']); +} + function pnut_settings(array &$data) { if (!DI::userSession()->getLocalUserId()) { @@ -99,12 +123,15 @@ function pnut_settings(array &$data) $enabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'pnut', 'post') ?? false; $def_enabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'pnut', 'post_by_default') ?? false; - $client_id = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'pnut', 'client_id'); - $client_secret = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'pnut', 'client_secret'); + $client_id = DI::config()->get('pnut', 'client_id'); + $client_secret = DI::config()->get('pnut', 'client_secret'); $token = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'pnut', 'access_token'); - - Logger::debug('CLIENT_ID', [$client_id]); - Logger::debug('CLIENT_SECRET', [$client_secret]); + + $user_client = empty($client_id) || empty($client_secret); + if ($user_client) { + $client_id = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'pnut', 'client_id'); + $client_secret = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'pnut', 'client_secret'); + } if (!empty($client_id) && !empty($client_secret) && empty($token)) { $nut = new phpnut\phpnut($client_id, $client_secret); @@ -118,19 +145,20 @@ function pnut_settings(array &$data) $t = Renderer::getMarkupTemplate('connector_settings.tpl', 'addon/pnut/'); $html = Renderer::replaceMacros($t, [ - '$enable' => ['pnut', DI::l10n()->t('Enable Pnut Post Addon'), $enabled], - '$bydefault' => ['pnut_bydefault', DI::l10n()->t('Post to Pnut by default'), $def_enabled], - '$client_id' => ['pnut_client_id', DI::l10n()->t('Client ID'), $client_id], - '$client_secret' => ['pnut_client_secret', DI::l10n()->t('Client Secret'), $client_secret], - '$access_token' => ['pnut_access_token', DI::l10n()->t('Access Token'), $token, '', '', 'readonly'], - '$authorize_url' => $authorize_url ?? '', + '$enable' => ['pnut', DI::l10n()->t('Enable Pnut Post Addon'), $enabled], + '$bydefault' => ['pnut_bydefault', DI::l10n()->t('Post to Pnut by default'), $def_enabled], + '$client_id' => ['pnut_client_id', DI::l10n()->t('Client ID'), $client_id], + '$client_secret' => ['pnut_client_secret', DI::l10n()->t('Client Secret'), $client_secret], + '$access_token' => ['pnut_access_token', DI::l10n()->t('Access Token'), $token, '', '', 'readonly'], + '$authorize_url' => $authorize_url ?? '', '$authorize_text' => $authorize_text ?? '', - '$disconn_btn' => $disconn_btn ?? '', + '$disconn_btn' => $disconn_btn ?? '', + 'user_client' => $user_client, ]); $data = [ 'connector' => 'pnut', - 'title' => DI::l10n()->t('Pnut Import/Export'), + 'title' => DI::l10n()->t('Pnut Export'), 'image' => 'addon/pnut/pnut.svg', 'enabled' => $enabled, 'html' => $html, @@ -152,8 +180,12 @@ function pnut_settings_post(array &$b) } else { DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'pnut', 'post', intval($_POST['pnut'])); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'pnut', 'post_by_default', intval($_POST['pnut_bydefault'])); - DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'pnut', 'client_id', $_POST['pnut_client_id']); - DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'pnut', 'client_secret', $_POST['pnut_client_secret']); + if (!empty($_POST['pnut_client_id'])) { + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'pnut', 'client_id', $_POST['pnut_client_id']); + } + if (!empty($_POST['pnut_client_secret'])) { + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'pnut', 'client_secret', $_POST['pnut_client_secret']); + } } } @@ -243,7 +275,7 @@ function pnut_post_hook(array &$b) $token = DI::pConfig()->get($b['uid'], 'pnut', 'access_token'); $nut = new phpnut\phpnut($token); - $msgarr = Plaintext::getPost($b, 256, true, BBCode::EXTERNAL); + $msgarr = Plaintext::getPost($b, PNUT_LIMIT, true, BBCode::EXTERNAL); $text = $msgarr['text']; $raw = []; @@ -275,7 +307,7 @@ function pnut_post_hook(array &$b) $picturedata = Photo::getImageForPhoto($photo); Logger::debug('PNUT photo', $photo); - $picurefile = System::getTempPath() . DIRECTORY_SEPARATOR . $photo['filename']; + $picurefile = tempnam(System::getTempPath(), 'pnut'); file_put_contents($picurefile, $picturedata); Logger::debug('PNUT got file?', ['filename' => $picurefile]); $imagefile = $nut->createFile($picurefile, $fileraw); diff --git a/pnut/templates/admin.tpl b/pnut/templates/admin.tpl new file mode 100644 index 000000000..b4cc3651f --- /dev/null +++ b/pnut/templates/admin.tpl @@ -0,0 +1,3 @@ +{{include file="field_input.tpl" field=$client_id}} +{{include file="field_input.tpl" field=$client_secret}} +
diff --git a/pnut/templates/connector_settings.tpl b/pnut/templates/connector_settings.tpl index 7d1ad3f2a..6662a5ae3 100644 --- a/pnut/templates/connector_settings.tpl +++ b/pnut/templates/connector_settings.tpl @@ -1,9 +1,11 @@

{{$status}}

{{include file="field_checkbox.tpl" field=$enable}} {{include file="field_checkbox.tpl" field=$bydefault}} -{{include file="field_input.tpl" field=$client_id}} -{{include file="field_input.tpl" field=$client_secret}} -{{include file="field_input.tpl" field=$access_token}} +{{if $user_client}} + {{include file="field_input.tpl" field=$client_id}} + {{include file="field_input.tpl" field=$client_secret}} + {{include file="field_input.tpl" field=$access_token}} +{{/if}} {{if $authorize_url}} {{$authorize_text}} {{/if}} From 90ec1bc83816518dca292db06abe6440d4425195 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 3 Mar 2024 17:10:09 +0000 Subject: [PATCH 117/388] Newlines added --- pnut/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pnut/README.md b/pnut/README.md index 6f6a9224f..798174b8a 100644 --- a/pnut/README.md +++ b/pnut/README.md @@ -4,5 +4,7 @@ With this addon to friendica you can give your users the possibility to post the No setup is needed for the admins to make it work for their users, however it is possible for the admin to create a client, so that the users don't have to. -To do so, go to https://pnut.io/dev and scroll down to "Create New Client". Enter a name of your choice and enter your Friendica host name as the website. Use https://(yourhost.name)/pnut/connect as a redirect url, replace "(yourhost.name)" with the host name of your system. +To do so, go to https://pnut.io/dev and scroll down to "Create New Client". +Enter a name of your choice and enter your Friendica host name as the website. +Use https://(yourhost.name)/pnut/connect as a redirect url, replace "(yourhost.name)" with the host name of your system. Limit the scope to "basic,files,follow,polls,presence,stream,update_profile,write_post" \ No newline at end of file From b6d706822a2c3e484d5901880492268409a4972e Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 4 Mar 2024 05:37:04 +0000 Subject: [PATCH 118/388] Blockbot: You can now allow social media agents --- blockbot/blockbot.php | 51 +++++++++++++++++++++++++----------- blockbot/lang/C/messages.po | 18 ++++++++++--- blockbot/templates/admin.tpl | 1 + 3 files changed, 50 insertions(+), 20 deletions(-) diff --git a/blockbot/blockbot.php b/blockbot/blockbot.php index 10327edf3..62a7f5669 100644 --- a/blockbot/blockbot.php +++ b/blockbot/blockbot.php @@ -27,16 +27,18 @@ function blockbot_addon_admin(string &$o) $t = Renderer::getMarkupTemplate('admin.tpl', 'addon/blockbot/'); $o = Renderer::replaceMacros($t, [ - '$submit' => DI::l10n()->t('Save Settings'), - '$good_crawlers' => ['good_crawlers', DI::l10n()->t('Allow "good" crawlers'), DI::config()->get('blockbot', 'good_crawlers'), DI::l10n()->t("Don't block fediverse crawlers, relay servers and other bots with good purposes.")], - '$block_gab' => ['block_gab', DI::l10n()->t('Block GabSocial'), DI::config()->get('blockbot', 'block_gab'), DI::l10n()->t('Block the software GabSocial. This will block every access for that software. You can block dedicated gab instances in the blocklist settings in the admin section.')], - '$training' => ['training', DI::l10n()->t('Training mode'), DI::config()->get('blockbot', 'training'), DI::l10n()->t("Activates the training mode. This is only meant for developing purposes. Don't activate this on a production machine. This can cut communication with some systems.")], + '$submit' => DI::l10n()->t('Save Settings'), + '$good_crawlers' => ['good_crawlers', DI::l10n()->t('Allow "good" crawlers'), DI::config()->get('blockbot', 'good_crawlers'), DI::l10n()->t("Don't block fediverse crawlers, relay servers and other bots with good purposes.")], + '$socialmedia_agents' => ['socialmedia_agents', DI::l10n()->t('Allow preview agents'), DI::config()->get('blockbot', 'socialmedia_agents'), DI::l10n()->t("Don't block agents from social media systems that want to generate preview data for links that had been set by their users.")], + '$block_gab' => ['block_gab', DI::l10n()->t('Block GabSocial'), DI::config()->get('blockbot', 'block_gab'), DI::l10n()->t('Block the software GabSocial. This will block every access for that software. You can block dedicated gab instances in the blocklist settings in the admin section.')], + '$training' => ['training', DI::l10n()->t('Training mode'), DI::config()->get('blockbot', 'training'), DI::l10n()->t("Activates the training mode. This is only meant for developing purposes. Don't activate this on a production machine. This can cut communication with some systems.")], ]); } function blockbot_addon_admin_post() { DI::config()->set('blockbot', 'good_crawlers', $_POST['good_crawlers'] ?? false); + DI::config()->set('blockbot', 'socialmedia_agents', $_POST['socialmedia_agents'] ?? false); DI::config()->set('blockbot', 'block_gab', $_POST['block_gab'] ?? false); DI::config()->set('blockbot', 'training', $_POST['training'] ?? false); } @@ -53,34 +55,41 @@ function blockbot_init_1() $good_agents = [ 'fediverse.space crawler', 'fediverse.network crawler', 'Active_Pods_CheckBot_3.0', 'Social-Relay/', 'Test Certificate Info', 'Uptimebot/', 'GNUSocialBot', 'UptimeRobot/', - 'PTST/', 'Zabbix', 'Poduptime/' + 'PTST/', 'Zabbix', 'Poduptime/', 'FediFetcher', 'lemmy-stats-crawler', + 'FedditLemmyverseCrawler/', 'kbinBot/', 'lemmy-explorer-crawler/', ]; - // List of known crawlers. + // List of agents from social media systems that fetch preview data via opem graph or twitter cards + $socialmedia_agents = ['Twitterbot/', 'facebookexternalhit/', 'SkypeUriPreview Preview/', + 'TelegramBot', 'WhatsApp/', 'github-camo', 'Bluesky Cardyb/', 'XING-contenttabreceiver/', + 'LinkedInBot/', 'Instagram ', 'Synapse (bot; ', 'Discordbot/']; + + // List of known unwanted crawlers. $agents = [ 'SemrushBot', 's~feedly-nikon3', 'Qwantify/Bleriot/', 'ltx71', 'Sogou web spider/', - 'Diffbot/', 'Twitterbot/', 'YisouSpider', 'evc-batch/', 'LivelapBot/', 'TrendsmapResolver/', + 'Diffbot/', 'YisouSpider', 'evc-batch/', 'LivelapBot/', 'TrendsmapResolver/', 'PaperLiBot/', 'Nuzzel', 'um-LN/', 'Google Favicon', 'Datanyze', 'BLEXBot/', '360Spider', 'adscanner/', 'HeadlessChrome', 'wpif', 'startmebot/', 'Googlebot/', 'Applebot/', - 'facebookexternalhit/', 'GoogleImageProxy', 'bingbot/', 'heritrix/', 'ldspider', + 'GoogleImageProxy', 'bingbot/', 'heritrix/', 'ldspider', 'AwarioRssBot/', 'TweetmemeBot/', 'dcrawl/', 'PhantomJS/', 'Googlebot-Image/', 'CrowdTanglebot/', 'Mediapartners-Google', 'Baiduspider/', 'datagnionbot', 'MegaIndex.ru/', 'SMUrlExpander', 'Hatena-Favicon/', 'Wappalyzer', 'FlipboardProxy/', 'NetcraftSurveyAgent/', 'Dataprovider.com', 'SMTBot/', 'Nimbostratus-Bot/', 'DuckDuckGo-Favicons-Bot/', 'IndieWebCards/', 'proximic', 'netEstate NE Crawler', - 'AhrefsBot/', 'YandexBot/', 'Exabot/', 'Mediumbot-MetaTagFetcher/', 'WhatsApp/', - 'TelegramBot', 'SurdotlyBot/', 'BingPreview/', 'SabsimBot/', 'CCBot/', 'WbSrch/', + 'AhrefsBot/', 'YandexBot/', 'Exabot/', 'Mediumbot-MetaTagFetcher/', + 'SurdotlyBot/', 'BingPreview/', 'SabsimBot/', 'CCBot/', 'WbSrch/', 'DuckDuckBot-Https/', 'HTTP Banner Detection', 'YandexImages/', 'archive.org_bot', 'ArchiveTeam ArchiveBot/', 'yacybot', 'https://developers.google.com/+/web/snippet/', - 'Scrapy/', 'github-camo', 'MJ12bot/', 'DotBot/', 'Pinterestbot/', 'Jooblebot/', + 'Scrapy/', 'MJ12bot/', 'DotBot/', 'Pinterestbot/', 'Jooblebot/', 'Cliqzbot/', 'YaK/', 'Mediatoolkitbot', 'Snacktory', 'FunWebProducts', 'oBot/', '7Siters/', 'KOCMOHABT', 'Google-SearchByImage', 'FemtosearchBot/', 'HubSpot Crawler', 'DomainStatsBot/', 'Re-re Studio', 'AwarioSmartBot/', 'SummalyBot/', 'DNSResearchBot/', 'PetalBot;', 'Nmap Scripting Engine;', 'Google-Apps-Script; beanserver;', 'woorankreview/', 'Seekport Crawler;', 'AHC/', - 'SkypeUriPreview Preview/', 'Semanticbot/', 'Embed PHP library', 'XoviOnpageCrawler;', + 'Semanticbot/', 'Embed PHP library', 'XoviOnpageCrawler;', 'Pinterest/', 'GetHPinfo.com-Bot/', 'BoardReader Favicon Fetcher', 'Google-Adwords-Instant', 'newspaper/', - 'YurichevBot/', 'Crawling at Home Project', 'InfoTigerBot/' + 'YurichevBot/', 'Crawling at Home Project', 'InfoTigerBot/', + 'AdIdxBot/', 'MicrosoftPreview/', 'masscan/' ]; if (!DI::config()->get('blockbot', 'good_crawlers')) { @@ -93,13 +102,23 @@ function blockbot_init_1() } } + if (!DI::config()->get('blockbot', 'socialmedia_agents')) { + $agents = array_merge($agents, $socialmedia_agents); + } else { + foreach ($socialmedia_agents as $socialmedia_agent) { + if (stristr($_SERVER['HTTP_USER_AGENT'], $socialmedia_agent)) { + return; + } + } + } + if (DI::config()->get('blockbot', 'block_gab')) { $agents[] = 'GabSocial/'; } foreach ($agents as $agent) { if (stristr($_SERVER['HTTP_USER_AGENT'], $agent)) { - throw new ForbiddenException('Bots are not allowed'); + throw new ForbiddenException('Bots are not allowed. If you consider this a mistake, create an issue at https://github.com/friendica/friendica'); } } @@ -125,7 +144,7 @@ function blockbot_init_1() 'lua-resty-http/', 'Tiny Tiny RSS/', 'Wget/', 'PostmanRuntime/', 'W3C_Validator/', 'NetNewsWire', 'FeedValidator/', 'theoldreader.com', 'axios/', 'Paw/', 'PeerTube/', 'fedi.inex.dev', 'FediDB/', 'index.community crawler', - 'Slackbot-LinkExpanding' + 'Slackbot-LinkExpanding', 'Firefish/', 'Takahe/', 'Akkoma ', 'Misskey/' ]; if (DI::config()->get('blockbot', 'good_crawlers')) { @@ -140,5 +159,5 @@ function blockbot_init_1() } logger::notice('Blocked bot', $logdata); - throw new ForbiddenException('Bots are not allowed'); + throw new ForbiddenException('Bots are not allowed. If you consider this a mistake, create an issue at https://github.com/friendica/friendica'); } diff --git a/blockbot/lang/C/messages.po b/blockbot/lang/C/messages.po index 6f30e845a..493719082 100644 --- a/blockbot/lang/C/messages.po +++ b/blockbot/lang/C/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-12-13 06:17+0000\n" +"POT-Creation-Date: 2024-03-04 05:35+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -32,21 +32,31 @@ msgid "" msgstr "" #: blockbot.php:32 -msgid "Block GabSocial" +msgid "Allow preview agents" msgstr "" #: blockbot.php:32 msgid "" +"Don't block agents from social media systems that want to generate preview " +"data for links that had been set by their users." +msgstr "" + +#: blockbot.php:33 +msgid "Block GabSocial" +msgstr "" + +#: blockbot.php:33 +msgid "" "Block the software GabSocial. This will block every access for that " "software. You can block dedicated gab instances in the blocklist settings in " "the admin section." msgstr "" -#: blockbot.php:33 +#: blockbot.php:34 msgid "Training mode" msgstr "" -#: blockbot.php:33 +#: blockbot.php:34 msgid "" "Activates the training mode. This is only meant for developing purposes. " "Don't activate this on a production machine. This can cut communication with " diff --git a/blockbot/templates/admin.tpl b/blockbot/templates/admin.tpl index a6de1bd3a..9f728d427 100644 --- a/blockbot/templates/admin.tpl +++ b/blockbot/templates/admin.tpl @@ -1,4 +1,5 @@ {{include file="field_checkbox.tpl" field=$good_crawlers}} +{{include file="field_checkbox.tpl" field=$socialmedia_agents}} {{include file="field_checkbox.tpl" field=$block_gab}} {{include file="field_checkbox.tpl" field=$training}}
From 3c0f4e3926768131ac4c093dc9ab1444cee3cca8 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Mon, 4 Mar 2024 01:16:49 -0500 Subject: [PATCH 119/388] [advancedcontentfilter] Stop using advancedcontentfilter_get_rules() outside of router context - This used to work with Slim v2, but the new requirements for module functions broke it --- advancedcontentfilter/advancedcontentfilter.php | 4 ++-- advancedcontentfilter/templates/settings.tpl | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/advancedcontentfilter/advancedcontentfilter.php b/advancedcontentfilter/advancedcontentfilter.php index 55bc50056..418b253ed 100644 --- a/advancedcontentfilter/advancedcontentfilter.php +++ b/advancedcontentfilter/advancedcontentfilter.php @@ -253,7 +253,7 @@ function advancedcontentfilter_content() 'cancel' => DI::l10n()->t('Cancel'), ], '$current_theme' => DI::app()->getCurrentTheme(), - '$rules' => advancedcontentfilter_get_rules(), + '$rules' => DBA::toArray(DBA::select('advancedcontentfilter_rules', [], ['uid' => DI::userSession()->getLocalUserId()])), '$form_security_token' => BaseModule::getFormSecurityToken() ]); } @@ -305,7 +305,7 @@ function advancedcontentfilter_build_fields($data) * API */ -function advancedcontentfilter_get_rules(ServerRequestInterface $request, ResponseInterface $response) +function advancedcontentfilter_get_rules(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface { if (!DI::userSession()->getLocalUserId()) { throw new HTTPException\UnauthorizedException(DI::l10n()->t('You must be logged in to use this method')); diff --git a/advancedcontentfilter/templates/settings.tpl b/advancedcontentfilter/templates/settings.tpl index c9dfbe3ae..8b82e595e 100644 --- a/advancedcontentfilter/templates/settings.tpl +++ b/advancedcontentfilter/templates/settings.tpl @@ -3,7 +3,7 @@
+ + +
+

{{$title}} - {{$page}} ({{$count}})

+

+ {{$h_newuser}} +

+
+ + + + + + + {{foreach $th_users as $k=>$th}} + {{if $k < 2 || $order_users == $th.1 || ($k==5 && !in_array($order_users,[$th_users.2.1, $th_users.3.1, $th_users.4.1])) }} + + {{/if}} + {{/foreach}} + + + + + {{foreach $users as $u}} + + + + + + {{if $order_users == $th_users.2.1}} + + {{/if}} + + {{if $order_users == $th_users.3.1}} + + {{/if}} + + {{if $order_users == $th_users.4.1}} + + {{/if}} + + {{if !in_array($order_users,[$th_users.2.1, $th_users.3.1, $th_users.4.1]) }} + + {{/if}} + + + + + + + + + {{/foreach}} + +
+
+ + +
+
+ + {{if $order_users == $th.1}} + {{if $order_direction_users == "+"}} + ↓ + {{else}} + ↑ + {{/if}} + {{else}} + ↕ + {{/if}} + {{$th.0}} + +
+ {{if $u.is_deletable}} +
+ + +
+ {{else}} +   + {{/if}} +
{{$u.name}}{{$u.email}}{{$u.register_date}}{{$u.login_date}}{{$u.lastitem_date}} + + + {{if $u.page_flags_raw==0 && $u.account_type_raw > 0}} + + {{/if}} + {{if $u.is_admin}}{{/if}} + {{if $u.account_expired}}{{/if}} + + +
+ + {{$pager nofilter}} +
+
From 7d5446a778419d67ec4df778c836b59083d5f163 Mon Sep 17 00:00:00 2001 From: Matthew Exon Date: Sun, 23 Jun 2024 15:15:06 +0200 Subject: [PATCH 190/388] Ratioed: remove unnecessary uninstall function --- ratioed/ratioed.php | 9 --------- 1 file changed, 9 deletions(-) diff --git a/ratioed/ratioed.php b/ratioed/ratioed.php index 3c88705c8..d8da9ac10 100644 --- a/ratioed/ratioed.php +++ b/ratioed/ratioed.php @@ -25,15 +25,6 @@ function ratioed_install() Logger::info("ratioed: installed"); } -/** - * @brief Uninstallation hook for ratioed plugin - */ -function ratioed_uninstall() { - Hook::unregister('moderation_users_tabs', 'addon/ratioed/ratioed.php', 'ratioed_users_tabs'); - - Logger::info("ratioed: uninstalled"); -} - /** * This is a statement rather than an actual function definition. The simple * existence of this method is checked to figure out if the addon offers a From 18e512cc8b0bd79a6be164e7fc06ec4a41f56dcd Mon Sep 17 00:00:00 2001 From: Matthew Exon Date: Sun, 23 Jun 2024 15:24:43 +0200 Subject: [PATCH 191/388] Ratioed: move panel class into separate file --- ratioed/RatioedPanel.php | 206 +++++++++++++++++++++++++++++++++++++++ ratioed/ratioed.php | 201 +------------------------------------- 2 files changed, 208 insertions(+), 199 deletions(-) create mode 100644 ratioed/RatioedPanel.php diff --git a/ratioed/RatioedPanel.php b/ratioed/RatioedPanel.php new file mode 100644 index 000000000..16f9df6f0 --- /dev/null +++ b/ratioed/RatioedPanel.php @@ -0,0 +1,206 @@ +parameters['action'] ?? ''; + $uid = $this->parameters['uid'] ?? 0; + + if ($uid) { + $user = User::getById($uid, ['username', 'blocked']); + if (!$user) { + $this->systemMessages->addNotice($this->t('User not found')); + $this->baseUrl->redirect('moderation/users'); + } + } + + switch ($action) { + case 'delete': + if ($this->session->getLocalUserId() != $uid) { + self::checkFormSecurityTokenRedirectOnError('moderation/users/active', 'moderation_users_active', 't'); + // delete user + User::remove($uid); + + $this->systemMessages->addNotice($this->t('User "%s" deleted', $user['username'])); + } else { + $this->systemMessages->addNotice($this->t('You can\'t remove yourself')); + } + + $this->baseUrl->redirect('moderation/users/active'); + break; + case 'block': + self::checkFormSecurityTokenRedirectOnError('moderation/users/active', 'moderation_users_active', 't'); + User::block($uid); + $this->systemMessages->addNotice($this->t('User "%s" blocked', $user['username'])); + $this->baseUrl->redirect('moderation/users/active'); + break; + } + $pager = new Pager($this->l10n, $this->args->getQueryString(), 100); + + $valid_orders = [ + 'name', + 'email', + 'register_date', + 'last-activity', + 'last-item', + 'page-flags', + ]; + + $order = 'last-item'; + $order_direction = '-'; + if (!empty($request['o'])) { + $new_order = $request['o']; + if ($new_order[0] === '-') { + $order_direction = '-'; + $new_order = substr($new_order, 1); + } + + if (in_array($new_order, $valid_orders)) { + $order = $new_order; + } + } + + $users = User::getList($pager->getStart(), $pager->getItemsPerPage(), 'active', $order, ($order_direction == '-')); + + $users = array_map($this->setupUserCallback(), $users); + + $header_titles = [ + $this->t('Name'), + $this->t('Email'), + $this->t('Register date'), + $this->t('Last login'), + $this->t('Last public item'), + $this->t('Type'), + $this->t('Blocked by'), + $this->t('Comments last 24h'), + $this->t('Reactions last 24h'), + $this->t('Ratio last 24h'), + ]; + $field_names = [ + 'name', + 'email', + 'register_date', + 'login_date', + 'lastitem_date', + 'page_flags', + 'blocked_by', + 'comments', + 'reactions', + 'ratio', + ]; + $th_users = array_map(null, $header_titles, $valid_orders, $field_names); + + $count = $this->database->count('user', ["`verified` AND NOT `blocked` AND NOT `account_removed` AND NOT `account_expired` AND `uid` != ?", 0]); + + $t = Renderer::getMarkupTemplate('ratioed.tpl', 'addon/ratioed'); + return self::getTabsHTML('ratioed') . Renderer::replaceMacros($t, [ + // strings // + '$title' => $this->t('Moderation'), + '$page' => $this->t('Behaviour'), + '$select_all' => $this->t('select all'), + '$delete' => $this->t('Delete'), + '$block' => $this->t('Block'), + '$blocked' => $this->t('User blocked'), + '$siteadmin' => $this->t('Site admin'), + '$accountexpired' => $this->t('Account expired'), + '$h_newuser' => $this->t('Create a new user'), + + '$th_users' => $th_users, + '$order_users' => $order, + '$order_direction_users' => $order_direction, + + '$confirm_delete_multi' => $this->t('Selected users will be deleted!\n\nEverything these users had posted on this site will be permanently deleted!\n\nAre you sure?'), + '$confirm_delete' => $this->t('The user {0} will be deleted!\n\nEverything this user has posted on this site will be permanently deleted!\n\nAre you sure?'), + + '$form_security_token' => self::getFormSecurityToken('moderation_users_active'), + + // values // + '$baseurl' => $this->baseUrl, + '$query_string' => $this->args->getQueryString(), + + '$users' => $users, + '$count' => $count, + '$pager' => $pager->renderFull($count), + ]); + } + + protected function setupUserCallback(): \Closure + { + Logger::debug("ratioed: setupUserCallback"); + $parentCallback = parent::setupUserCallback(); + return function ($user) use ($parentCallback) { + $blocked_count = DBA::count('user-contact', ['uid' => $user['uid'], 'is-blocked' => 1]); + $user['blocked_by'] = $blocked_count; + + $self_contact_result = DBA::p('SELECT admin_contact.id AS user_contact_uid FROM contact AS admin_contact JOIN contact AS user_contact ON admin_contact.`uri-id` = user_contact.`uri-id` AND admin_contact.self = 0 AND user_contact.self = 1 WHERE user_contact.uid = ?', $user['uid']); + if (DBA::isResult($self_contact_result)) { + $self_contact_result_row = DBA::fetch($self_contact_result); + $user['user_contact_uid'] = $self_contact_result_row['user_contact_uid']; + } + else { + $user['user_contact_uid'] = NULL; + } + + if ($user['user_contact_uid']) { + $post_engagement_result = DBA::p('SELECT SUM(`comments`) AS `comment_count`, SUM(`activities`) AS `activities_count` FROM `post-engagement` WHERE `post-engagement`.created > DATE_SUB(now(), INTERVAL 1 DAY) AND `post-engagement`.`owner-id` = ?', $user['user_contact_uid']); + if (DBA::isResult($post_engagement_result)) { + $post_engagement_result_row = DBA::fetch($post_engagement_result); + $user['comments'] = $post_engagement_result_row['comment_count']; + $user['reactions'] = $post_engagement_result_row['activities_count']; + if ($user['reactions'] > 0) { + $user['ratio'] = number_format($user['comments'] / $user['reactions'], 1, '.', ''); + $user['ratioed'] = (float)($user['ratio']) >= 2.0; + } + else { + if ($user['comments'] == 0) { + $user['ratio'] = '0'; + $user['ratioed'] = false; + } + else { + $user['ratio'] = '∞'; + $user['ratioed'] = false; + } + } + } + else { + $user['comments'] = 'error'; + $user['reactions'] = 'error'; + $user['ratio'] = 'error'; + $user['ratioed'] = false; + } + } + else { + $user['comments'] = 'error'; + $user['reactions'] = 'error'; + $user['ratio'] = 'error'; + $user['ratioed'] = false; + } + + $user = $parentCallback($user); + Logger::debug("ratioed: setupUserCallback", [ + 'uid' => $user['uid'], + 'blocked_by' => $user['blocked_by'], + 'comments' => $user['comments'], + 'reactions' => $user['reactions'], + 'ratio' => $user['ratio'], + 'ratioed' => $user['ratioed'], + ]); + return $user; + }; + } +} diff --git a/ratioed/ratioed.php b/ratioed/ratioed.php index d8da9ac10..8ae0d48c7 100644 --- a/ratioed/ratioed.php +++ b/ratioed/ratioed.php @@ -6,14 +6,10 @@ * Author: Matthew Exon */ -use Friendica\Content\Pager; +use Friendica\Addon\ratioed\RatioedPanel; use Friendica\Core\Hook; use Friendica\Core\Logger; -use Friendica\Core\Renderer; -use Friendica\Database\DBA; use Friendica\DI; -use Friendica\Model\User; -use Friendica\Module\Moderation\Users\Active; /** * Sets up the addon hooks and updates data in the database if needed @@ -50,206 +46,13 @@ function ratioed_users_tabs(array &$arr) { ]); } -class Ratioed extends Friendica\Module\Moderation\Users\Active -{ - protected function content(array $request = []): string - { - Friendica\Module\Moderation\Users\Active::content(); - - $action = $this->parameters['action'] ?? ''; - $uid = $this->parameters['uid'] ?? 0; - - if ($uid) { - $user = User::getById($uid, ['username', 'blocked']); - if (!$user) { - $this->systemMessages->addNotice($this->t('User not found')); - $this->baseUrl->redirect('moderation/users'); - } - } - - switch ($action) { - case 'delete': - if ($this->session->getLocalUserId() != $uid) { - self::checkFormSecurityTokenRedirectOnError('moderation/users/active', 'moderation_users_active', 't'); - // delete user - User::remove($uid); - - $this->systemMessages->addNotice($this->t('User "%s" deleted', $user['username'])); - } else { - $this->systemMessages->addNotice($this->t('You can\'t remove yourself')); - } - - $this->baseUrl->redirect('moderation/users/active'); - break; - case 'block': - self::checkFormSecurityTokenRedirectOnError('moderation/users/active', 'moderation_users_active', 't'); - User::block($uid); - $this->systemMessages->addNotice($this->t('User "%s" blocked', $user['username'])); - $this->baseUrl->redirect('moderation/users/active'); - break; - } - $pager = new Pager($this->l10n, $this->args->getQueryString(), 100); - - $valid_orders = [ - 'name', - 'email', - 'register_date', - 'last-activity', - 'last-item', - 'page-flags', - ]; - - $order = 'last-item'; - $order_direction = '-'; - if (!empty($request['o'])) { - $new_order = $request['o']; - if ($new_order[0] === '-') { - $order_direction = '-'; - $new_order = substr($new_order, 1); - } - - if (in_array($new_order, $valid_orders)) { - $order = $new_order; - } - } - - $users = User::getList($pager->getStart(), $pager->getItemsPerPage(), 'active', $order, ($order_direction == '-')); - - $users = array_map($this->setupUserCallback(), $users); - - $header_titles = [ - $this->t('Name'), - $this->t('Email'), - $this->t('Register date'), - $this->t('Last login'), - $this->t('Last public item'), - $this->t('Type'), - $this->t('Blocked by'), - $this->t('Comments last 24h'), - $this->t('Reactions last 24h'), - $this->t('Ratio last 24h'), - ]; - $field_names = [ - 'name', - 'email', - 'register_date', - 'login_date', - 'lastitem_date', - 'page_flags', - 'blocked_by', - 'comments', - 'reactions', - 'ratio', - ]; - $th_users = array_map(null, $header_titles, $valid_orders, $field_names); - - $count = $this->database->count('user', ["`verified` AND NOT `blocked` AND NOT `account_removed` AND NOT `account_expired` AND `uid` != ?", 0]); - - $t = Renderer::getMarkupTemplate('ratioed.tpl', 'addon/ratioed'); - return self::getTabsHTML('ratioed') . Renderer::replaceMacros($t, [ - // strings // - '$title' => $this->t('Moderation'), - '$page' => $this->t('Behaviour'), - '$select_all' => $this->t('select all'), - '$delete' => $this->t('Delete'), - '$block' => $this->t('Block'), - '$blocked' => $this->t('User blocked'), - '$siteadmin' => $this->t('Site admin'), - '$accountexpired' => $this->t('Account expired'), - '$h_newuser' => $this->t('Create a new user'), - - '$th_users' => $th_users, - '$order_users' => $order, - '$order_direction_users' => $order_direction, - - '$confirm_delete_multi' => $this->t('Selected users will be deleted!\n\nEverything these users had posted on this site will be permanently deleted!\n\nAre you sure?'), - '$confirm_delete' => $this->t('The user {0} will be deleted!\n\nEverything this user has posted on this site will be permanently deleted!\n\nAre you sure?'), - - '$form_security_token' => self::getFormSecurityToken('moderation_users_active'), - - // values // - '$baseurl' => $this->baseUrl, - '$query_string' => $this->args->getQueryString(), - - '$users' => $users, - '$count' => $count, - '$pager' => $pager->renderFull($count), - ]); - } - - protected function setupUserCallback(): \Closure - { - Logger::debug("ratioed: setupUserCallback"); - $parentCallback = parent::setupUserCallback(); - return function ($user) use ($parentCallback) { - $blocked_count = DBA::count('user-contact', ['uid' => $user['uid'], 'is-blocked' => 1]); - $user['blocked_by'] = $blocked_count; - - $self_contact_result = DBA::p('SELECT admin_contact.id AS user_contact_uid FROM contact AS admin_contact JOIN contact AS user_contact ON admin_contact.`uri-id` = user_contact.`uri-id` AND admin_contact.self = 0 AND user_contact.self = 1 WHERE user_contact.uid = ?', $user['uid']); - if (DBA::isResult($self_contact_result)) { - $self_contact_result_row = DBA::fetch($self_contact_result); - $user['user_contact_uid'] = $self_contact_result_row['user_contact_uid']; - } - else { - $user['user_contact_uid'] = NULL; - } - - if ($user['user_contact_uid']) { - $post_engagement_result = DBA::p('SELECT SUM(`comments`) AS `comment_count`, SUM(`activities`) AS `activities_count` FROM `post-engagement` WHERE `post-engagement`.created > DATE_SUB(now(), INTERVAL 1 DAY) AND `post-engagement`.`owner-id` = ?', $user['user_contact_uid']); - if (DBA::isResult($post_engagement_result)) { - $post_engagement_result_row = DBA::fetch($post_engagement_result); - $user['comments'] = $post_engagement_result_row['comment_count']; - $user['reactions'] = $post_engagement_result_row['activities_count']; - if ($user['reactions'] > 0) { - $user['ratio'] = number_format($user['comments'] / $user['reactions'], 1, '.', ''); - $user['ratioed'] = (float)($user['ratio']) >= 2.0; - } - else { - if ($user['comments'] == 0) { - $user['ratio'] = '0'; - $user['ratioed'] = false; - } - else { - $user['ratio'] = '∞'; - $user['ratioed'] = false; - } - } - } - else { - $user['comments'] = 'error'; - $user['reactions'] = 'error'; - $user['ratio'] = 'error'; - $user['ratioed'] = false; - } - } - else { - $user['comments'] = 'error'; - $user['reactions'] = 'error'; - $user['ratio'] = 'error'; - $user['ratioed'] = false; - } - - $user = $parentCallback($user); - Logger::debug("ratioed: setupUserCallback", [ - 'uid' => $user['uid'], - 'blocked_by' => $user['blocked_by'], - 'comments' => $user['comments'], - 'reactions' => $user['reactions'], - 'ratio' => $user['ratio'], - 'ratioed' => $user['ratioed'], - ]); - return $user; - }; - } -} - /** * @brief Displays the ratioed tab in the moderation panel */ function ratioed_content() { Logger::debug("ratioed: content"); - $ratioed = DI::getDice()->create(Ratioed::class, [$_SERVER]); + $ratioed = DI::getDice()->create(RatioedPanel::class, [$_SERVER]); $httpException = DI::getDice()->create(Friendica\Module\Special\HTTPException::class); $ratioed->run($httpException); } From 14e7413eb2f89effd151b4460c0a56cdb560c681 Mon Sep 17 00:00:00 2001 From: hankg Date: Mon, 24 Jun 2024 22:20:35 +0200 Subject: [PATCH 192/388] Add Relatica to blockbot fediverse client list --- blockbot/blockbot.php | 1 + 1 file changed, 1 insertion(+) diff --git a/blockbot/blockbot.php b/blockbot/blockbot.php index eb634b1f5..adf0a7c27 100644 --- a/blockbot/blockbot.php +++ b/blockbot/blockbot.php @@ -499,6 +499,7 @@ function blockbot_is_fediverse_client(array $parts): bool 'megalodonandroid', 'fedilab', 'mastodonapp', 'toot!', 'intravnews', 'pixeldroid', 'greatnews', 'protopage', 'newsfox', 'vienna', 'wp-urldetails', 'husky', 'activitypub-go-http-client', 'mobilesafari', 'mastodon-ios', 'mastodonpy', 'techniverse', + 'relatica', ]; foreach ($parts as $part) { From b2108c7a4c7efe5c79f8c5e762e3cae207d9e0d2 Mon Sep 17 00:00:00 2001 From: Hannes Heute Date: Thu, 27 Jun 2024 11:44:15 +0200 Subject: [PATCH 193/388] fix for curweather --- curweather/curweather.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/curweather/curweather.php b/curweather/curweather.php index 5a14a9cf0..9aa8584a3 100644 --- a/curweather/curweather.php +++ b/curweather/curweather.php @@ -152,7 +152,7 @@ function curweather_network_mod_init(string &$body) function curweather_addon_settings_post($post) { - if (!DI::userSession()->getLocalUserId() || empty($_POST['curweather-settings-submit'])) { + if (!DI::userSession()->getLocalUserId() || empty($_POST['curweather-submit'])) { return; } From 5f27f72b0d18bbf3226f4850cb4aa6f2c36482fe Mon Sep 17 00:00:00 2001 From: Matthew Exon Date: Sat, 29 Jun 2024 15:23:24 +0200 Subject: [PATCH 194/388] Streamline log lines --- mailstream/mailstream.php | 70 +++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/mailstream/mailstream.php b/mailstream/mailstream.php index b513cf367..c5cf8f3fa 100644 --- a/mailstream/mailstream.php +++ b/mailstream/mailstream.php @@ -34,7 +34,7 @@ function mailstream_install() Hook::register('post_remote_end', 'addon/mailstream/mailstream.php', 'mailstream_post_hook'); Hook::register('mailstream_send_hook', 'addon/mailstream/mailstream.php', 'mailstream_send_hook'); - Logger::info("mailstream: installed"); + Logger::info("installed mailstream"); } /** @@ -44,7 +44,7 @@ function mailstream_check_version() { if (!is_null(DI::config()->get('mailstream', 'dbversion'))) { DI::config()->delete('mailstream', 'dbversion'); - Logger::info("mailstream_check_version: old version detected, reinstalling"); + Logger::info("old version detected, reinstalling"); mailstream_install(); Hook::loadHooks(); Hook::add( @@ -105,7 +105,7 @@ function mailstream_generate_id(string $uri): string $host = DI::baseUrl()->getHost(); $resource = hash('md5', $uri); $message_id = "<" . $resource . "@" . $host . ">"; - Logger::debug('mailstream: Generated message ID ' . $message_id . ' for URI ' . $uri); + Logger::debug('generated message ID', ['id' => $message_id, 'uri' => $uri]); return $message_id; } @@ -114,20 +114,20 @@ function mailstream_send_hook(array $data) $criteria = array('uid' => $data['uid'], 'contact-id' => $data['contact-id'], 'uri' => $data['uri']); $item = Post::selectFirst([], $criteria); if (empty($item)) { - Logger::error('mailstream_send_hook could not find item'); + Logger::error('could not find item'); return; } $user = User::getById($item['uid']); if (empty($user)) { - Logger::error('mailstream_send_hook could not fund user', ['uid' => $item['uid']]); + Logger::error('could not find user', ['uid' => $item['uid']]); return; } if (!mailstream_send($data['message_id'], $item, $user)) { - Logger::debug('mailstream_send_hook send failed, will retry', $data); + Logger::debug('send failed, will retry', $data); if (!Worker::defer()) { - Logger::error('mailstream_send_hook failed and could not defer', $data); + Logger::error('failed and could not defer', $data); } } } @@ -145,32 +145,32 @@ function mailstream_post_hook(array &$item) mailstream_check_version(); if (!DI::pConfig()->get($item['uid'], 'mailstream', 'enabled')) { - Logger::debug('mailstream: not enabled.', ['item' => $item['id'], ' uid ' => $item['uid']]); + Logger::debug('mailstream not enabled.', ['item' => $item['id'], 'uid' => $item['uid']]); return; } if (!$item['uid']) { - Logger::debug('mailstream: no uid for item ' . $item['id']); + Logger::debug('no uid', ['item' => $item['id']]); return; } if (!$item['contact-id']) { - Logger::debug('mailstream: no contact-id for item ' . $item['id']); + Logger::debug('no contact-id', ['item' => $item['id']]); return; } if (!$item['uri']) { - Logger::debug('mailstream: no uri for item ' . $item['id']); + Logger::debug('no uri', ['item' => $item['id']]); return; } if ($item['verb'] == Activity::ANNOUNCE) { - Logger::debug('mailstream: announce item ', ['item' => $item['id']]); + Logger::debug('ignoring announce', ['item' => $item['id']]); return; } if (DI::pConfig()->get($item['uid'], 'mailstream', 'nolikes')) { if ($item['verb'] == Activity::LIKE) { - Logger::debug('mailstream: like item ' . $item['id']); + Logger::debug('ignoring like', ['item' => $item['id']]); return; } if ($item['verb'] == Activity::DISLIKE) { - Logger::debug('mailstream: dislike item ' . $item['id']); + Logger::debug('ignoring dislike', ['item' => $item['id']]); return; } } @@ -221,7 +221,7 @@ function mailstream_do_images(array &$item, array &$attachments) try { $curlResult = DI::httpClient()->fetchFull($url, HttpClientAccept::DEFAULT, 0, $cookiejar); } catch (InvalidArgumentException $e) { - Logger::error('mailstream_do_images exception fetching url', ['url' => $url, 'item_id' => $item['id']]); + Logger::error('exception fetching url', ['url' => $url, 'item_id' => $item['id']]); continue; } $attachments[$url] = [ @@ -322,13 +322,12 @@ function mailstream_subject(array $item): string } $contact = Contact::selectFirst([], ['id' => $item['contact-id'], 'uid' => $item['uid']]); if (!DBA::isResult($contact)) { - Logger::error( - 'mailstream_subject no contact for item', - ['id' => $item['id'], - 'plink' => $item['plink'], - 'contact id' => $item['contact-id'], - 'uid' => $item['uid']] - ); + Logger::error('no contact', [ + 'item' => $item['id'], + 'plink' => $item['plink'], + 'contact id' => $item['contact-id'], + 'uid' => $item['uid'] + ]); return DI::l10n()->t("Friendica post"); } if ($contact['network'] === 'dfrn') { @@ -365,17 +364,16 @@ function mailstream_subject(array $item): string function mailstream_send(string $message_id, array $item, array $user): bool { if (!is_array($item)) { - Logger::error('mailstream_send item is empty', ['message_id' => $message_id]); + Logger::error('item is empty', ['message_id' => $message_id]); return false; } if (!$item['visible']) { - Logger::debug('mailstream_send item not yet visible', ['item uri' => $item['uri']]); + Logger::debug('item not yet visible', ['item uri' => $item['uri']]); return false; } if (!$message_id) { - Logger::error('mailstream_send no message ID supplied', ['item uri' => $item['uri'], - 'user email' => $user['email']]); + Logger::error('no message ID supplied', ['item uri' => $item['uri'], 'user email' => $user['email']]); return true; } @@ -432,13 +430,15 @@ function mailstream_send(string $message_id, array $item, array $user): bool if (!$mail->Send()) { throw new Exception($mail->ErrorInfo); } - Logger::debug('mailstream_send sent message', ['message ID' => $mail->MessageID, - 'subject' => $mail->Subject, - 'address' => $address]); + Logger::debug('sent message', [ + 'message ID' => $mail->MessageID, + 'subject' => $mail->Subject, + 'address' => $address + ]); } catch (phpmailerException $e) { - Logger::debug('mailstream_send PHPMailer exception sending message ' . $message_id . ': ' . $e->errorMessage()); + Logger::debug('PHPMailer exception sending message', ['id' => $message_id, 'error' => $e->errorMessage()]); } catch (Exception $e) { - Logger::debug('mailstream_send exception sending message ' . $message_id . ': ' . $e->getMessage()); + Logger::debug('exception sending message', ['id' => $message_id, 'error' => $e->getMessage()]); } return true; @@ -468,7 +468,7 @@ function mailstream_html_wrap(string &$text) function mailstream_convert_table_entries() { $ms_item_ids = DBA::selectToArray('mailstream_item', [], ['message-id', 'uri', 'uid', 'contact-id'], ["`mailstream_item`.`completed` IS NULL"]); - Logger::debug('mailstream_convert_table_entries processing ' . count($ms_item_ids) . ' items'); + Logger::debug('processing items', ['count' => count($ms_item_ids)]); foreach ($ms_item_ids as $ms_item_id) { $send_hook_data = array('uid' => $ms_item_id['uid'], 'contact-id' => $ms_item_id['contact-id'], @@ -476,10 +476,10 @@ function mailstream_convert_table_entries() 'message_id' => $ms_item_id['message-id'], 'tries' => 0); if (!$ms_item_id['message-id'] || !strlen($ms_item_id['message-id'])) { - Logger::info('mailstream_convert_table_entries: item has no message-id.', ['item' => $ms_item_id['id'], 'uri' => $ms_item_id['uri']]); - continue; + Logger::info('item has no message-id', ['item' => $ms_item_id['id'], 'uri' => $ms_item_id['uri']]); + continue; } - Logger::info('mailstream_convert_table_entries: convert item to workerqueue', $send_hook_data); + Logger::info('convert item to workerqueue', $send_hook_data); Hook::fork(Worker::PRIORITY_LOW, 'mailstream_send_hook', $send_hook_data); } DBA::e('DROP TABLE `mailstream_item`'); From f3db763c599cfeb830fdf95a8de5738c183be30b Mon Sep 17 00:00:00 2001 From: Matthew Exon Date: Tue, 9 Jul 2024 20:13:00 +0100 Subject: [PATCH 195/388] More comprehensible check for root user contact --- mailstream/mailstream.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mailstream/mailstream.php b/mailstream/mailstream.php index c5cf8f3fa..b86c4e2a3 100644 --- a/mailstream/mailstream.php +++ b/mailstream/mailstream.php @@ -144,12 +144,12 @@ function mailstream_post_hook(array &$item) { mailstream_check_version(); - if (!DI::pConfig()->get($item['uid'], 'mailstream', 'enabled')) { - Logger::debug('mailstream not enabled.', ['item' => $item['id'], 'uid' => $item['uid']]); + if ($item['uid'] === 0) { + Logger::debug('mailstream: root user, skipping item ' . $item['id']); return; } - if (!$item['uid']) { - Logger::debug('no uid', ['item' => $item['id']]); + if (!DI::pConfig()->get($item['uid'], 'mailstream', 'enabled')) { + Logger::debug('mailstream: not enabled.', ['item' => $item['id'], ' uid ' => $item['uid']]); return; } if (!$item['contact-id']) { From 589cf712cc92911d5288b1dfff06bd8c9d4cfb78 Mon Sep 17 00:00:00 2001 From: Matthew Exon Date: Sun, 14 Jul 2024 18:56:22 +0200 Subject: [PATCH 196/388] Remove old version conversion code --- mailstream/mailstream.php | 44 --------------------------------------- 1 file changed, 44 deletions(-) diff --git a/mailstream/mailstream.php b/mailstream/mailstream.php index b86c4e2a3..8bce2529e 100644 --- a/mailstream/mailstream.php +++ b/mailstream/mailstream.php @@ -37,25 +37,6 @@ function mailstream_install() Logger::info("installed mailstream"); } -/** - * Enforces that mailstream_install has set up the current version - */ -function mailstream_check_version() -{ - if (!is_null(DI::config()->get('mailstream', 'dbversion'))) { - DI::config()->delete('mailstream', 'dbversion'); - Logger::info("old version detected, reinstalling"); - mailstream_install(); - Hook::loadHooks(); - Hook::add( - 'mailstream_convert_table_entries', - 'addon/mailstream/mailstream.php', - 'mailstream_convert_table_entries' - ); - Hook::fork(Worker::PRIORITY_LOW, 'mailstream_convert_table_entries'); - } -} - /** * This is a statement rather than an actual function definition. The simple * existence of this method is checked to figure out if the addon offers a @@ -142,8 +123,6 @@ function mailstream_send_hook(array $data) */ function mailstream_post_hook(array &$item) { - mailstream_check_version(); - if ($item['uid'] === 0) { Logger::debug('mailstream: root user, skipping item ' . $item['id']); return; @@ -462,29 +441,6 @@ function mailstream_html_wrap(string &$text) return $text; } -/** - * Convert v1 mailstream table entries to v2 workerqueue items - */ -function mailstream_convert_table_entries() -{ - $ms_item_ids = DBA::selectToArray('mailstream_item', [], ['message-id', 'uri', 'uid', 'contact-id'], ["`mailstream_item`.`completed` IS NULL"]); - Logger::debug('processing items', ['count' => count($ms_item_ids)]); - foreach ($ms_item_ids as $ms_item_id) { - $send_hook_data = array('uid' => $ms_item_id['uid'], - 'contact-id' => $ms_item_id['contact-id'], - 'uri' => $ms_item_id['uri'], - 'message_id' => $ms_item_id['message-id'], - 'tries' => 0); - if (!$ms_item_id['message-id'] || !strlen($ms_item_id['message-id'])) { - Logger::info('item has no message-id', ['item' => $ms_item_id['id'], 'uri' => $ms_item_id['uri']]); - continue; - } - Logger::info('convert item to workerqueue', $send_hook_data); - Hook::fork(Worker::PRIORITY_LOW, 'mailstream_send_hook', $send_hook_data); - } - DBA::e('DROP TABLE `mailstream_item`'); -} - /** * Form for configuring mailstream features for a user * From c0535db74214eb0983c7bd145702d9600fc169f2 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 5 Aug 2024 20:37:58 +0000 Subject: [PATCH 197/388] Statistics: inbound / outbound for Tumblr and Bluesky --- bluesky/bluesky.php | 2 ++ tumblr/tumblr.php | 2 ++ 2 files changed, 4 insertions(+) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index 6994b3e36..9f21674f3 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -1946,6 +1946,7 @@ function bluesky_post(int $uid, string $url, string $params, array $headers): ?s return null; } + Item::incrementOutbound(Protocol::BLUESKY); try { $curlResult = DI::httpClient()->post($pds . $url, $params, $headers); } catch (\Exception $e) { @@ -1982,6 +1983,7 @@ function bluesky_xrpc_get(int $uid, string $url, array $parameters = []): ?stdCl function bluesky_get(string $url, string $accept_content = HttpClientAccept::DEFAULT, array $opts = []): ?stdClass { + Item::incrementInbound(Protocol::BLUESKY); try { $curlResult = DI::httpClient()->get($url, $accept_content, $opts); } catch (\Exception $e) { diff --git a/tumblr/tumblr.php b/tumblr/tumblr.php index f0c68f332..945f8f35d 100644 --- a/tumblr/tumblr.php +++ b/tumblr/tumblr.php @@ -1326,6 +1326,7 @@ function tumblr_get_contact_by_url(string $url, int $uid): ?array */ function tumblr_get(int $uid, string $url, array $parameters = []): stdClass { + Item::incrementInbound(Protocol::TUMBLR); $url = 'https://api.tumblr.com/v2/' . $url; if ($uid == 0) { @@ -1355,6 +1356,7 @@ function tumblr_get(int $uid, string $url, array $parameters = []): stdClass */ function tumblr_post(int $uid, string $url, array $parameters): stdClass { + Item::incrementOutbound(Protocol::TUMBLR); $url = 'https://api.tumblr.com/v2/' . $url; $curlResult = DI::httpClient()->post($url, $parameters, ['Authorization' => ['Bearer ' . tumblr_get_token($uid)]]); From 46a55f13f7bd2566e0ede5bdb5df6d78c42fdab4 Mon Sep 17 00:00:00 2001 From: Matthew Exon Date: Mon, 22 Jul 2024 18:23:23 +0200 Subject: [PATCH 198/388] Ratioed: add help text --- ratioed/RatioedPanel.php | 7 +++ ratioed/templates/help.tpl | 92 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 ratioed/templates/help.tpl diff --git a/ratioed/RatioedPanel.php b/ratioed/RatioedPanel.php index 16f9df6f0..e25c7f341 100644 --- a/ratioed/RatioedPanel.php +++ b/ratioed/RatioedPanel.php @@ -6,6 +6,7 @@ use Friendica\Content\Pager; use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\Database\DBA; +use Friendica\DI; use Friendica\Model\User; use Friendica\Module\Moderation\Users\Active; @@ -18,6 +19,11 @@ class RatioedPanel extends Active { Active::content(); + if (isset(DI::args()->getArgv()[1]) and DI::args()->getArgv()[1] === 'help') { + $template = Renderer::getMarkupTemplate('/help.tpl', 'addon/ratioed/'); + return Renderer::replaceMacros($template, array('$config' => DI::baseUrl() . '/settings/addon')); + } + $action = $this->parameters['action'] ?? ''; $uid = $this->parameters['uid'] ?? 0; @@ -111,6 +117,7 @@ class RatioedPanel extends Active return self::getTabsHTML('ratioed') . Renderer::replaceMacros($t, [ // strings // '$title' => $this->t('Moderation'), + '$help_url' => $this->baseUrl . '/ratioed/help', '$page' => $this->t('Behaviour'), '$select_all' => $this->t('select all'), '$delete' => $this->t('Delete'), diff --git a/ratioed/templates/help.tpl b/ratioed/templates/help.tpl new file mode 100644 index 000000000..fee47e34b --- /dev/null +++ b/ratioed/templates/help.tpl @@ -0,0 +1,92 @@ +
+
+

Ratioed Plugin Help

+

+ This plugin provides administrators with additional statistics about + the behaviour of users. These may be useful as early warning signs + that warrant more carefully watching the behaviour of a user. They + are not suitable as a trigger for instantly blocking, + muting, or reporting a user, since they lack context. +

+

+ The name of the plugin comes + from "The + Ratio", a well-known quick rule of thumb: +

+
+ If the Replies:RT ratio is greater than 2:1, you done messed up. +
+

+ To "get ratioed" is to receive a large number of comments in a short + space of time, with relatively few likes or boosts. If commenters + were enthusiastic about the posts, they would also have liked or + boosted them. Receiving many comments without such likes or boosts + indicates the comments were probably angry. This anger may or may + not be justified, but either way this is probably something + moderators should be aware of. +

+

+ This plugin allows viewing of an actual ratio, calculated over the + last 24 hours. This is a useful timeframe for sudden dogpiling + events that administrators might not otherwise notice. The plugin + also calculates other statistics. +

+

Explanation of Statistics

+

Blocked by

+

+ This summarises the number of users on remote servers that have + blocked this user. +

+

+ Note that the ActivityPub spec expressly says that + implementations "SHOULD NOT" forward such block messages to + remote servers. Nevertheless some implementations do this + anyway, notably Mastodon. This statistic can only count block + messages from servers that do this, as well as blocks from local + users. As such, it is usually an undercount. +

+

+ The reason the spec recommends against forwarding these messages + is that they can lead to retaliation. For this reason, this + plugin deliberately does not provide any way to investigate + exactly who blocked the user. +

+

Comments last 24h

+

+ This gives the number of comments made on the top-level posts that + this user made within the last 24 hours. +

+

Reactions last 24h

+

+ This collects the number of likes, boosts, or other "one-click" + interactions made on the user's top-level posts within the last 24 + hours. +

+

Ratio last 24h

+

+ This is the ratio between "Comments last 24h" and "Reactions last + 24h". It is intended to approximate the traditional ratio as + understood on Twitter. +

+

Performance

+

+ The statistics are computed from scratch each time the page loads. + It's possible that this might put a heavy load on the database. and + the page may take a long time to load. +

+

Extending

+

+ Suggestions for additional statistics are welcome, especially from + moderators. This plugin should be considered a sandbox for + experimentation, so it is not necessary to prove that any statistic + is correlated with unwanted behaviour. +

+

+ However, this plugin does deal with potentially sensitive + information. Even if moderators do in principle have access to all + information, it should not necessarily be highlighted. Statistics + should be kept anonymous and neutral. Also, they should be + presented only to moderators, not to the users themselves. +

+
+
From 4bfdb45e81c8550ab89381670c068455d780bcf5 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 12 Aug 2024 20:20:32 +0000 Subject: [PATCH 199/388] Bluesky/Tumblr: Improved statistics --- bluesky/bluesky.php | 23 +++++++++++++---------- tumblr/tumblr.php | 22 +++++++++++++--------- 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index 9f21674f3..19466a420 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -294,9 +294,9 @@ function bluesky_block(array &$hook_data) $activity = bluesky_xrpc_post($hook_data['uid'], 'com.atproto.repo.createRecord', $post); if (!empty($activity->uri)) { - $cdata = Contact::getPublicAndUserContactID($hook_data['contact']['id'], $hook_data['uid']); - if (!empty($cdata['user'])) { - Contact::remove($cdata['user']); + $ucid = Contact::getUserContactId($hook_data['contact']['id'], $hook_data['uid']); + if ($ucid) { + Contact::remove($ucid); } Logger::debug('Successfully blocked contact', ['url' => $hook_data['contact']['url'], 'uri' => $activity->uri]); } @@ -975,6 +975,7 @@ function bluesky_upload_blob(int $uid, array $photo): ?stdClass return null; } + Item::incrementOutbound(Protocol::BLUESKY); Logger::debug('Uploaded blob', ['return' => $data, 'uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size]); return $data->blob; } @@ -1048,8 +1049,8 @@ function bluesky_process_reason(stdClass $reason, string $uri, int $uid) $item['owner-link'] = $item['author-link']; $item['owner-avatar'] = $item['author-avatar']; if (Item::insert($item)) { - $cdata = Contact::getPublicAndUserContactID($contact['id'], $uid); - Item::update(['post-reason' => Item::PR_ANNOUNCEMENT, 'causer-id' => $cdata['public']], ['uri' => $uri, 'uid' => $uid]); + $pcid = Contact::getPublicContactId($contact['id'], $uid); + Item::update(['post-reason' => Item::PR_ANNOUNCEMENT, 'causer-id' => $pcid], ['uri' => $uri, 'uid' => $uid]); } } @@ -1537,8 +1538,7 @@ function bluesky_fetch_missing_post(string $uri, int $uid, int $fetch_uid, int $ Logger::debug('Reply count', ['level' => $level, 'uid' => $uid, 'uri' => $uri]); if ($causer != 0) { - $cdata = Contact::getPublicAndUserContactID($causer, $uid); - $causer = $cdata['public'] ?? 0; + $causer = Contact::getPublicContactId($causer, $uid); } return bluesky_process_thread($data->thread, $uid, $fetch_uid, $post_reason, $causer, $level, $last_poll); @@ -1936,7 +1936,11 @@ function bluesky_create_token(int $uid, string $password): string function bluesky_xrpc_post(int $uid, string $url, $parameters): ?stdClass { - return bluesky_post($uid, '/xrpc/' . $url, json_encode($parameters), ['Content-type' => 'application/json', 'Authorization' => ['Bearer ' . bluesky_get_token($uid)]]); + $data = bluesky_post($uid, '/xrpc/' . $url, json_encode($parameters), ['Content-type' => 'application/json', 'Authorization' => ['Bearer ' . bluesky_get_token($uid)]]); + if (!empty($data)) { + Item::incrementOutbound(Protocol::BLUESKY); + } + return $data; } function bluesky_post(int $uid, string $url, string $params, array $headers): ?stdClass @@ -1946,7 +1950,6 @@ function bluesky_post(int $uid, string $url, string $params, array $headers): ?s return null; } - Item::incrementOutbound(Protocol::BLUESKY); try { $curlResult = DI::httpClient()->post($pds . $url, $params, $headers); } catch (\Exception $e) { @@ -1983,7 +1986,6 @@ function bluesky_xrpc_get(int $uid, string $url, array $parameters = []): ?stdCl function bluesky_get(string $url, string $accept_content = HttpClientAccept::DEFAULT, array $opts = []): ?stdClass { - Item::incrementInbound(Protocol::BLUESKY); try { $curlResult = DI::httpClient()->get($url, $accept_content, $opts); } catch (\Exception $e) { @@ -1996,5 +1998,6 @@ function bluesky_get(string $url, string $accept_content = HttpClientAccept::DEF return null; } + Item::incrementInbound(Protocol::BLUESKY); return json_decode($curlResult->getBodyString()); } diff --git a/tumblr/tumblr.php b/tumblr/tumblr.php index 945f8f35d..dd34bd415 100644 --- a/tumblr/tumblr.php +++ b/tumblr/tumblr.php @@ -133,6 +133,7 @@ function tumblr_item_by_link(array &$hookData) Logger::debug('Got post', ['blog' => $matches[1], 'id' => $matches[2], 'result' => $result->response->posts]); if (!empty($result->response->posts)) { $hookData['item_id'] = tumblr_process_post($result->response->posts[0], $hookData['uid'], Item::PR_FETCHED); + Item::incrementInbound(Protocol::TUMBLR); } } @@ -203,9 +204,9 @@ function tumblr_block(array &$hook_data) $hook_data['result'] = ($result->meta->status <= 399); if ($hook_data['result']) { - $cdata = Contact::getPublicAndUserContactID($hook_data['contact']['id'], $hook_data['uid']); - if (!empty($cdata['user'])) { - Contact::remove($cdata['user']); + $ucid = Contact::getUserContactId($hook_data['contact']['id'], $hook_data['uid']); + if ($ucid) { + Contact::remove($ucid); } } } @@ -238,9 +239,7 @@ function tumblr_get_contact_uuid(array $contact): string * existence of this method is checked to figure out if the addon offers a * module. */ -function tumblr_module() -{ -} +function tumblr_module() {} function tumblr_content() { @@ -756,6 +755,7 @@ function tumblr_fetch_tags(int $uid, int $last_poll) $post = Post::selectFirst(['uri-id'], ['id' => $id]); $stored = Post\Category::storeFileByURIId($post['uri-id'], $uid, Post\Category::SUBCRIPTION, $tag); Logger::debug('Stored tag subscription for user', ['uri-id' => $post['uri-id'], 'uid' => $uid, 'tag' => $tag, 'stored' => $stored]); + Item::incrementInbound(Protocol::TUMBLR); } } } @@ -795,6 +795,7 @@ function tumblr_fetch_dashboard(int $uid, int $last_poll) Logger::debug('Importing post', ['uid' => $uid, 'created' => date(DateTimeFormat::MYSQL, $post->timestamp), 'id' => $post->id_string]); tumblr_process_post($post, $uid, Item::PR_NONE, $last_poll); + Item::incrementInbound(Protocol::TUMBLR); DI::pConfig()->set($uid, 'tumblr', 'last_id', $last); } @@ -1167,6 +1168,7 @@ function tumblr_get_contact_fields(stdClass $blog, int $uid, bool $update): arra Logger::notice('Error fetching blog info', ['meta' => $info->meta, 'response' => $info->response, 'errors' => $info->errors]); return $fields; } + Item::incrementInbound(Protocol::TUMBLR); $avatar = $info->response->blog->avatar; if (!empty($avatar)) { @@ -1231,6 +1233,8 @@ function tumblr_get_blogs(int $uid): array return []; } + Item::incrementInbound(Protocol::TUMBLR); + $blogs = []; foreach ($userinfo->response->user->blogs as $blog) { $blogs[$blog->uuid] = $blog->name; @@ -1287,10 +1291,11 @@ function tumblr_get_contact_by_url(string $url, int $uid): ?array if ($info->meta->status > 399) { Logger::notice('Error fetching blog info', ['meta' => $info->meta, 'response' => $info->response, 'errors' => $info->errors, 'blog' => $blog, 'uid' => $uid]); return null; - } else { - Logger::debug('Got data', ['blog' => $blog, 'meta' => $info->meta]); } + Logger::debug('Got data', ['blog' => $blog, 'meta' => $info->meta]); + Item::incrementInbound(Protocol::TUMBLR); + $baseurl = 'https://tumblr.com'; $url = $baseurl . '/' . $info->response->blog->name; @@ -1326,7 +1331,6 @@ function tumblr_get_contact_by_url(string $url, int $uid): ?array */ function tumblr_get(int $uid, string $url, array $parameters = []): stdClass { - Item::incrementInbound(Protocol::TUMBLR); $url = 'https://api.tumblr.com/v2/' . $url; if ($uid == 0) { From a55f80cb39ea8737a56e265cb9edda6739cc2755 Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Thu, 15 Aug 2024 06:44:57 +0200 Subject: [PATCH 200/388] updated translations --- curweather/lang/fr/messages.po | 7 ++++--- curweather/lang/fr/strings.php | 2 +- geonames/lang/fr/messages.po | 7 ++++--- geonames/lang/fr/strings.php | 2 +- gnot/lang/fr/messages.po | 7 ++++--- gnot/lang/fr/strings.php | 2 +- gravatar/lang/fr/messages.po | 7 ++++--- gravatar/lang/fr/strings.php | 2 +- ijpost/lang/fr/messages.po | 7 ++++--- ijpost/lang/fr/strings.php | 2 +- krynn/lang/fr/messages.po | 7 ++++--- krynn/lang/fr/strings.php | 2 +- 12 files changed, 30 insertions(+), 24 deletions(-) diff --git a/curweather/lang/fr/messages.po b/curweather/lang/fr/messages.po index 57ed6b8bf..21e60c546 100644 --- a/curweather/lang/fr/messages.po +++ b/curweather/lang/fr/messages.po @@ -5,6 +5,7 @@ # # Translators: # bob lebonche , 2021 +# cracrayol, 2024 # Hypolite Petovan , 2022 # Hypolite Petovan , 2016 # ea1cd8241cb389ffb6f92bc6891eff5d_dc12308 <70dced5587d47e18d88f9298024d96f8_93383>, 2015 @@ -15,8 +16,8 @@ msgstr "" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-11-21 19:14-0500\n" "PO-Revision-Date: 2014-06-22 11:34+0000\n" -"Last-Translator: Hypolite Petovan , 2022\n" -"Language-Team: French (http://www.transifex.com/Friendica/friendica/language/fr/)\n" +"Last-Translator: cracrayol, 2024\n" +"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -45,7 +46,7 @@ msgstr "Vent" #: curweather.php:140 msgid "Last Updated" -msgstr "Dernière mise-à-jour" +msgstr "Dernière mise à jour" #: curweather.php:141 msgid "Data by" diff --git a/curweather/lang/fr/strings.php b/curweather/lang/fr/strings.php index be5c1ba5e..268b3a42a 100644 --- a/curweather/lang/fr/strings.php +++ b/curweather/lang/fr/strings.php @@ -10,7 +10,7 @@ $a->strings['Current Weather'] = 'Météo actuelle'; $a->strings['Relative Humidity'] = 'Humidité relative'; $a->strings['Pressure'] = 'Pression'; $a->strings['Wind'] = 'Vent'; -$a->strings['Last Updated'] = 'Dernière mise-à-jour'; +$a->strings['Last Updated'] = 'Dernière mise à jour'; $a->strings['Data by'] = 'Données de'; $a->strings['Show on map'] = 'Montrer sur la carte'; $a->strings['There was a problem accessing the weather data. But have a look'] = 'Une erreur est survenue lors de l\'accès aux données météo. Vous pouvez quand même jeter un oeil'; diff --git a/geonames/lang/fr/messages.po b/geonames/lang/fr/messages.po index b1cd8ce11..9fe03bdb6 100644 --- a/geonames/lang/fr/messages.po +++ b/geonames/lang/fr/messages.po @@ -6,6 +6,7 @@ # Translators: # bob lebonche , 2021 # ButterflyOfFire, 2020 +# cracrayol, 2024 # Hypolite Petovan , 2016 msgid "" msgstr "" @@ -13,8 +14,8 @@ msgstr "" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-11-21 19:14-0500\n" "PO-Revision-Date: 2014-06-23 08:27+0000\n" -"Last-Translator: bob lebonche , 2021\n" -"Language-Team: French (http://www.transifex.com/Friendica/friendica/language/fr/)\n" +"Last-Translator: cracrayol, 2024\n" +"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -29,7 +30,7 @@ msgstr "Remplacer les coordonnées par le nom de la localité la plus proche dan #: geonames.php:136 msgid "Enable Geonames Addon" -msgstr "Activer l'application complémentaire Geonames" +msgstr "Activer l'extension Geonames" #: geonames.php:141 msgid "Geonames Settings" diff --git a/geonames/lang/fr/strings.php b/geonames/lang/fr/strings.php index 297e3b73f..802dd118c 100644 --- a/geonames/lang/fr/strings.php +++ b/geonames/lang/fr/strings.php @@ -6,5 +6,5 @@ function string_plural_select_fr($n){ if (($n == 0 || $n == 1)) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } }} $a->strings['Replace numerical coordinates by the nearest populated location name in your posts.'] = 'Remplacer les coordonnées par le nom de la localité la plus proche dans votre publication.'; -$a->strings['Enable Geonames Addon'] = 'Activer l\'application complémentaire Geonames'; +$a->strings['Enable Geonames Addon'] = 'Activer l\'extension Geonames'; $a->strings['Geonames Settings'] = 'Paramètres Geonames'; diff --git a/gnot/lang/fr/messages.po b/gnot/lang/fr/messages.po index 3ce82e7f9..8a9285446 100644 --- a/gnot/lang/fr/messages.po +++ b/gnot/lang/fr/messages.po @@ -6,6 +6,7 @@ # Translators: # bob lebonche , 2021 # ButterflyOfFire, 2020 +# cracrayol, 2024 # Hypolite Petovan , 2016 msgid "" msgstr "" @@ -13,8 +14,8 @@ msgstr "" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-11-21 19:14-0500\n" "PO-Revision-Date: 2014-06-23 08:30+0000\n" -"Last-Translator: bob lebonche , 2021\n" -"Language-Team: French (http://www.transifex.com/Friendica/friendica/language/fr/)\n" +"Last-Translator: cracrayol, 2024\n" +"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -29,7 +30,7 @@ msgstr "Permettre le filtrage des notifications de commentaires par courriel sur #: gnot.php:64 msgid "Enable this addon?" -msgstr "Activer cette application complémentaire ?" +msgstr "Activer cette extension ?" #: gnot.php:69 msgid "Gnot Settings" diff --git a/gnot/lang/fr/strings.php b/gnot/lang/fr/strings.php index c498f7e83..531043497 100644 --- a/gnot/lang/fr/strings.php +++ b/gnot/lang/fr/strings.php @@ -6,6 +6,6 @@ function string_plural_select_fr($n){ if (($n == 0 || $n == 1)) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } }} $a->strings['Allows threading of email comment notifications on Gmail and anonymising the subject line.'] = 'Permettre le filtrage des notifications de commentaires par courriel sur Gmail et l\'anonymisation de l\'objet.'; -$a->strings['Enable this addon?'] = 'Activer cette application complémentaire ?'; +$a->strings['Enable this addon?'] = 'Activer cette extension ?'; $a->strings['Gnot Settings'] = 'Paramètres Gnot'; $a->strings['[Friendica:Notify] Comment to conversation #%d'] = '[Friendica:Notify] Commentaire vers conversation #%d'; diff --git a/gravatar/lang/fr/messages.po b/gravatar/lang/fr/messages.po index f8a64a1b0..6ffa62146 100644 --- a/gravatar/lang/fr/messages.po +++ b/gravatar/lang/fr/messages.po @@ -5,6 +5,7 @@ # # Translators: # bob lebonche , 2021 +# cracrayol, 2024 # Marie Olive , 2018 # ea1cd8241cb389ffb6f92bc6891eff5d_dc12308 <70dced5587d47e18d88f9298024d96f8_93383>, 2015 msgid "" @@ -13,8 +14,8 @@ msgstr "" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-02-01 18:15+0100\n" "PO-Revision-Date: 2014-06-23 08:33+0000\n" -"Last-Translator: bob lebonche , 2021\n" -"Language-Team: French (http://www.transifex.com/Friendica/friendica/language/fr/)\n" +"Last-Translator: cracrayol, 2024\n" +"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -50,7 +51,7 @@ msgid "" "Libravatar addon is installed, too. Please disable Libravatar addon or this " "Gravatar addon.
The Libravatar addon will fall back to Gravatar if " "nothing was found at Libravatar." -msgstr "L'application complémentaire Libravatar est aussi installée. Merci de désactiver l'application complémentaire Libravatar ou cette application complémentaire Gravatar. L'application complémentaire se repliera sur Gravatar si rien n'est trouvé dans Libravatar." +msgstr "L'extension Libravatar est aussi installée. Merci de désactiver l'extension Libravatar ou cette extension Gravatar. L'extension se repliera sur Gravatar si rien n'est trouvé dans Libravatar." #: gravatar.php:102 msgid "Save Settings" diff --git a/gravatar/lang/fr/strings.php b/gravatar/lang/fr/strings.php index b826ab65a..930d7169f 100644 --- a/gravatar/lang/fr/strings.php +++ b/gravatar/lang/fr/strings.php @@ -11,7 +11,7 @@ $a->strings['monster face'] = 'Face de monstre'; $a->strings['computer generated face'] = 'visage généré par ordinateur'; $a->strings['retro arcade style face'] = 'Face style retro arcade'; $a->strings['Information'] = 'Information'; -$a->strings['Libravatar addon is installed, too. Please disable Libravatar addon or this Gravatar addon.
The Libravatar addon will fall back to Gravatar if nothing was found at Libravatar.'] = 'L\'application complémentaire Libravatar est aussi installée. Merci de désactiver l\'application complémentaire Libravatar ou cette application complémentaire Gravatar. L\'application complémentaire se repliera sur Gravatar si rien n\'est trouvé dans Libravatar.'; +$a->strings['Libravatar addon is installed, too. Please disable Libravatar addon or this Gravatar addon.
The Libravatar addon will fall back to Gravatar if nothing was found at Libravatar.'] = 'L\'extension Libravatar est aussi installée. Merci de désactiver l\'extension Libravatar ou cette extension Gravatar. L\'extension se repliera sur Gravatar si rien n\'est trouvé dans Libravatar.'; $a->strings['Save Settings'] = 'Sauvegarder les paramètres.'; $a->strings['Default avatar image'] = 'Image par défaut d\'avatar'; $a->strings['Select default avatar image if none was found at Gravatar. See README'] = 'Sélectionner l\'avatar par défaut, si aucun n\'est trouvé sur Gravatar. Voir Lisezmoi.'; diff --git a/ijpost/lang/fr/messages.po b/ijpost/lang/fr/messages.po index bc322337a..6f29cad7f 100644 --- a/ijpost/lang/fr/messages.po +++ b/ijpost/lang/fr/messages.po @@ -5,6 +5,7 @@ # # Translators: # bob lebonche , 2021 +# cracrayol, 2024 # Hypolite Petovan , 2016 msgid "" msgstr "" @@ -12,8 +13,8 @@ msgstr "" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-11-21 19:17-0500\n" "PO-Revision-Date: 2014-06-23 08:37+0000\n" -"Last-Translator: bob lebonche , 2021\n" -"Language-Team: French (http://www.transifex.com/Friendica/friendica/language/fr/)\n" +"Last-Translator: cracrayol, 2024\n" +"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -26,7 +27,7 @@ msgstr "Publier sur Insanejournal" #: ijpost.php:61 msgid "Enable InsaneJournal Post Addon" -msgstr "Activer l'application complémentaire InsaneJournalPost" +msgstr "Activer l'extension InsaneJournal" #: ijpost.php:62 msgid "InsaneJournal username" diff --git a/ijpost/lang/fr/strings.php b/ijpost/lang/fr/strings.php index d8e3e95d6..d2fafc92a 100644 --- a/ijpost/lang/fr/strings.php +++ b/ijpost/lang/fr/strings.php @@ -6,7 +6,7 @@ function string_plural_select_fr($n){ if (($n == 0 || $n == 1)) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } }} $a->strings['Post to Insanejournal'] = 'Publier sur Insanejournal'; -$a->strings['Enable InsaneJournal Post Addon'] = 'Activer l\'application complémentaire InsaneJournalPost'; +$a->strings['Enable InsaneJournal Post Addon'] = 'Activer l\'extension InsaneJournal'; $a->strings['InsaneJournal username'] = 'Identifiant du InsaneJournal'; $a->strings['InsaneJournal password'] = 'Mot de passe du InsaneJournal'; $a->strings['Post to InsaneJournal by default'] = 'Publier sur le InsaneJournal par défaut'; diff --git a/krynn/lang/fr/messages.po b/krynn/lang/fr/messages.po index a96af8de5..8a306eb12 100644 --- a/krynn/lang/fr/messages.po +++ b/krynn/lang/fr/messages.po @@ -5,14 +5,15 @@ # # Translators: # bob lebonche , 2021 +# cracrayol, 2024 msgid "" msgstr "" "Project-Id-Version: friendica\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-11-21 19:14-0500\n" "PO-Revision-Date: 2015-07-07 15:14+0000\n" -"Last-Translator: bob lebonche , 2021\n" -"Language-Team: French (http://www.transifex.com/Friendica/friendica/language/fr/)\n" +"Last-Translator: cracrayol, 2024\n" +"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -21,7 +22,7 @@ msgstr "" #: krynn.php:127 msgid "Enable Krynn Addon" -msgstr "Activer l'application complémentaire Krynn" +msgstr "Activer l'extension Krynn" #: krynn.php:132 msgid "Krynn Settings" diff --git a/krynn/lang/fr/strings.php b/krynn/lang/fr/strings.php index 3c3574d00..84293f796 100644 --- a/krynn/lang/fr/strings.php +++ b/krynn/lang/fr/strings.php @@ -5,5 +5,5 @@ function string_plural_select_fr($n){ $n = intval($n); if (($n == 0 || $n == 1)) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; } }} -$a->strings['Enable Krynn Addon'] = 'Activer l\'application complémentaire Krynn'; +$a->strings['Enable Krynn Addon'] = 'Activer l\'extension Krynn'; $a->strings['Krynn Settings'] = 'Paramètres de Krynn'; From 276c27678feb7f2660efb7b199c40346abdb5bb3 Mon Sep 17 00:00:00 2001 From: Philipp Date: Tue, 20 Aug 2024 18:07:51 +0200 Subject: [PATCH 201/388] [CI] Add safe.directory config --- .woodpecker/.code_standards_check.yml | 3 +++ .woodpecker/.continuous-deployment.yml | 3 +++ .woodpecker/.messages.po_check.yml | 3 +++ .woodpecker/.phpunit.yml | 3 +++ .woodpecker/.releaser.yml | 3 +++ 5 files changed, 15 insertions(+) diff --git a/.woodpecker/.code_standards_check.yml b/.woodpecker/.code_standards_check.yml index 8e0f7dc7f..fb5be33c5 100644 --- a/.woodpecker/.code_standards_check.yml +++ b/.woodpecker/.code_standards_check.yml @@ -4,6 +4,9 @@ pipeline: clone_friendica_base: image: alpine/git commands: + - git config --global user.email "no-reply@friendi.ca" + - git config --global user.name "Friendica" + - git config --global --add safe.directory $CI_WORKSPACE - git clone https://github.com/friendica/friendica.git . - git checkout $CI_COMMIT_BRANCH when: diff --git a/.woodpecker/.continuous-deployment.yml b/.woodpecker/.continuous-deployment.yml index d1202978b..4d3bc5b78 100644 --- a/.woodpecker/.continuous-deployment.yml +++ b/.woodpecker/.continuous-deployment.yml @@ -9,6 +9,9 @@ pipeline: clone_friendica_base: image: alpine/git commands: + - git config --global user.email "no-reply@friendi.ca" + - git config --global user.name "Friendica" + - git config --global --add safe.directory $CI_WORKSPACE - git clone https://github.com/friendica/friendica.git . - git checkout $CI_COMMIT_BRANCH when: diff --git a/.woodpecker/.messages.po_check.yml b/.woodpecker/.messages.po_check.yml index ea9fa4d50..aa40ab4ee 100644 --- a/.woodpecker/.messages.po_check.yml +++ b/.woodpecker/.messages.po_check.yml @@ -4,6 +4,9 @@ pipeline: clone_friendica_base: image: alpine/git commands: + - git config --global user.email "no-reply@friendi.ca" + - git config --global user.name "Friendica" + - git config --global --add safe.directory $CI_WORKSPACE - git clone https://github.com/friendica/friendica.git . - git checkout $CI_COMMIT_BRANCH when: diff --git a/.woodpecker/.phpunit.yml b/.woodpecker/.phpunit.yml index 0c25a2bd7..887e897e0 100644 --- a/.woodpecker/.phpunit.yml +++ b/.woodpecker/.phpunit.yml @@ -21,6 +21,9 @@ pipeline: clone_friendica_base: image: alpine/git commands: + - git config --global user.email "no-reply@friendi.ca" + - git config --global user.name "Friendica" + - git config --global --add safe.directory $CI_WORKSPACE - git clone https://github.com/friendica/friendica.git . - git checkout $CI_COMMIT_BRANCH clone_friendica_addon: diff --git a/.woodpecker/.releaser.yml b/.woodpecker/.releaser.yml index 68bdfb216..f12697b93 100644 --- a/.woodpecker/.releaser.yml +++ b/.woodpecker/.releaser.yml @@ -9,6 +9,9 @@ pipeline: clone_friendica_base: image: alpine/git commands: + - git config --global user.email "no-reply@friendi.ca" + - git config --global user.name "Friendica" + - git config --global --add safe.directory $CI_WORKSPACE - git clone https://github.com/friendica/friendica.git . - git checkout $CI_COMMIT_BRANCH when: From 50930c301d3d736fb204a69d1cafd778af819ca8 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 1 Sep 2024 11:39:59 +0000 Subject: [PATCH 202/388] Bluesky: Improve DID detection for custom PDS --- bluesky/bluesky.php | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index 19466a420..101568c7e 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -1793,23 +1793,19 @@ function bluesky_get_did(string $handle): string $handle .= '.' . BLUESKY_HOSTNAME; } - // Deactivated at the moment, since it isn't reliable by now - //$did = bluesky_get_did_by_dns($handle); - //if ($did != '') { - // return $did; - //} - - //$did = bluesky_get_did_by_wellknown($handle); - //if ($did != '') { - // return $did; - //} - $data = bluesky_get(BLUESKY_PDS . '/xrpc/com.atproto.identity.resolveHandle?handle=' . urlencode($handle)); - if (empty($data) || empty($data->did)) { - return ''; + if (!empty($data) && !empty($data->did)) { + Logger::debug('Got DID by PDS call', ['handle' => $handle, 'did' => $data->did]); + return $data->did; } - Logger::debug('Got DID by PDS call', ['handle' => $handle, 'did' => $data->did]); - return $data->did; + + // Possibly a custom PDS. + $did = bluesky_get_did_by_dns($handle); + if ($did != '') { + return $did; + } + + return bluesky_get_did_by_wellknown($handle); } function bluesky_get_user_did(int $uid, bool $refresh = false): ?string From 2f9076bffdede3add6feeae7e66e4ca095105a2c Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 3 Sep 2024 11:28:49 +0000 Subject: [PATCH 203/388] Bluesky: probing for bluesky handles --- bluesky/bluesky.php | 146 +++++++++++++++++++++++++++++++++----------- 1 file changed, 112 insertions(+), 34 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index 101568c7e..9145fc32c 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -45,10 +45,12 @@ use Friendica\Model\Tag; use Friendica\Model\User; use Friendica\Network\HTTPClient\Client\HttpClientAccept; use Friendica\Network\HTTPClient\Client\HttpClientOptions; +use Friendica\Network\HTTPClient\Client\HttpClientRequest; use Friendica\Object\Image; use Friendica\Protocol\Activity; use Friendica\Protocol\Relay; use Friendica\Util\DateTimeFormat; +use Friendica\Util\Network; use Friendica\Util\Strings; const BLUESKY_DEFAULT_POLL_INTERVAL = 10; // given in minutes @@ -129,8 +131,13 @@ function bluesky_probe_detect(array &$hookData) if (parse_url($hookData['uri'], PHP_URL_SCHEME) == 'did') { $did = $hookData['uri']; - } elseif (preg_match('#^' . BLUESKY_WEB . '/profile/(.+)#', $hookData['uri'], $matches)) { - $did = bluesky_get_did($matches[1]); + } elseif (parse_url($hookData['uri'], PHP_URL_PATH) == $hookData['uri'] && strpos($hookData['uri'], '@') === false) { + $did = bluesky_get_did($hookData['uri'], $pconfig['uid']); + if (empty($did)) { + return; + } + } elseif (Network::isValidHttpUrl($hookData['uri'])) { + $did = bluesky_get_did_by_profile($hookData['uri']); if (empty($did)) { return; } @@ -148,19 +155,14 @@ function bluesky_probe_detect(array &$hookData) return; } - $hookData['result'] = bluesky_get_contact_fields($data, 0, $pconfig['uid'], false); - - $hookData['result']['baseurl'] = bluesky_get_pds($did); + $hookData['result'] = bluesky_get_contact_fields($data, 0, $pconfig['uid'], true); // Preparing probe data. This differs slightly from the contact array - $hookData['result']['about'] = HTML::toBBCode($data->description ?? ''); $hookData['result']['photo'] = $data->avatar ?? ''; - $hookData['result']['header'] = $data->banner ?? ''; $hookData['result']['batch'] = ''; $hookData['result']['notify'] = ''; $hookData['result']['poll'] = ''; $hookData['result']['poco'] = ''; - $hookData['result']['pubkey'] = ''; $hookData['result']['priority'] = 0; $hookData['result']['guid'] = ''; } @@ -177,21 +179,21 @@ function bluesky_item_by_link(array &$hookData) return; } - if (!preg_match('#^' . BLUESKY_WEB . '/profile/(.+)/post/(.+)#', $hookData['uri'], $matches)) { - return; - } - - $did = bluesky_get_did($matches[1]); + $did = bluesky_get_did_by_profile($hookData['uri']); if (empty($did)) { return; } - Logger::debug('Found bluesky post', ['url' => $hookData['uri'], 'handle' => $matches[1], 'did' => $did, 'cid' => $matches[2]]); + if (!preg_match('#/profile/.+/post/(.+)#', $hookData['uri'], $matches)) { + return; + } - $uri = 'at://' . $did . '/app.bsky.feed.post/' . $matches[2]; + Logger::debug('Found bluesky post', ['url' => $hookData['uri'], 'did' => $did, 'cid' => $matches[1]]); + + $uri = 'at://' . $did . '/app.bsky.feed.post/' . $matches[1]; $uri = bluesky_fetch_missing_post($uri, $hookData['uid'], $hookData['uid'], Item::PR_FETCHED, 0, 0, 0); - Logger::debug('Got post', ['profile' => $matches[1], 'cid' => $matches[2], 'result' => $uri]); + Logger::debug('Got post', ['did' => $did, 'cid' => $matches[1], 'result' => $uri]); if (!empty($uri)) { $item = Post::selectFirst(['id'], ['uri' => $uri, 'uid' => $hookData['uid']]); if (!empty($item['id'])) { @@ -1678,10 +1680,14 @@ function bluesky_get_contact_fields(stdClass $author, int $uid, int $fetch_uid, return $fields; } - $fields['baseurl'] = bluesky_get_pds($author->did); - if (!empty($fields['baseurl'])) { - GServer::check($fields['baseurl'], Protocol::BLUESKY); - $fields['gsid'] = GServer::getID($fields['baseurl'], true); + $data = bluesky_get(BLUESKY_DIRECTORY . '/' . $author->did); + if (!empty($data)) { + $fields['baseurl'] = bluesky_get_pds('', $data); + if (!empty($fields['baseurl'])) { + GServer::check($fields['baseurl'], Protocol::BLUESKY); + $fields['gsid'] = GServer::getID($fields['baseurl'], true); + } + $fields['pubkey'] = bluesky_get_public_key('', $data); } $data = bluesky_xrpc_get($fetch_uid, 'app.bsky.actor.getProfile', ['actor' => $author->did]); @@ -1748,6 +1754,42 @@ function bluesky_get_preferences(int $uid): ?stdClass return $data; } +function bluesky_get_did_by_profile(string $url): string +{ + try { + $curlResult = DI::httpClient()->get($url, HttpClientAccept::HTML, [HttpClientOptions::REQUEST => HttpClientRequest::CONTACTINFO]); + } catch (\Throwable $th) { + return ''; + } + if (!$curlResult->isSuccess()) { + return ''; + } + $profile = $curlResult->getBodyString(); + + $doc = new DOMDocument(); + @$doc->loadHTML($profile); + $xpath = new DOMXPath($doc); + $list = $xpath->query('//p[@id]'); + foreach ($list as $node) { + foreach ($node->attributes as $attribute) { + if ($attribute->name == 'id') { + $ids[$attribute->value] = $node->textContent; + } + } + } + + if (empty($ids['bsky_handle']) || empty($ids['bsky_did'])) { + return ''; + } + + if (!bluesky_valid_did($ids['bsky_did'], $ids['bsky_handle'])) { + Logger::notice('Invalid DID', ['handle' => $ids['bsky_handle'], 'did' => $ids['bsky_did']]); + return ''; + } + + return $ids['bsky_did']; +} + function bluesky_get_did_by_wellknown(string $handle): string { $curlResult = DI::httpClient()->get('http://' . $handle . '/.well-known/atproto-did'); @@ -1757,7 +1799,6 @@ function bluesky_get_did_by_wellknown(string $handle): string Logger::notice('Invalid DID', ['handle' => $handle, 'did' => $did]); return ''; } - Logger::debug('Got DID by wellknown', ['handle' => $handle, 'did' => $did]); return $did; } return ''; @@ -1776,14 +1817,13 @@ function bluesky_get_did_by_dns(string $handle): string Logger::notice('Invalid DID', ['handle' => $handle, 'did' => $did]); return ''; } - Logger::debug('Got DID by DNS', ['handle' => $handle, 'did' => $did]); return $did; } } return ''; } -function bluesky_get_did(string $handle): string +function bluesky_get_did(string $handle, int $uid): string { if ($handle == '') { return ''; @@ -1793,19 +1833,39 @@ function bluesky_get_did(string $handle): string $handle .= '.' . BLUESKY_HOSTNAME; } + // At first we use the user PDS. That should cover most cases. + $pds = DI::pConfig()->get($uid, 'bluesky', 'pds'); + if (!empty($pds)) { + $data = bluesky_get($pds . '/xrpc/com.atproto.identity.resolveHandle?handle=' . urlencode($handle)); + if (!empty($data) && !empty($data->did)) { + Logger::debug('Got DID by user PDS call', ['handle' => $handle, 'did' => $data->did]); + return $data->did; + } + } + + // Then we query the DNS, which is used for third party handles (DNS should be faster than wellknown) + $did = bluesky_get_did_by_dns($handle); + if ($did != '') { + Logger::debug('Got DID by DNS', ['handle' => $handle, 'did' => $did]); + return $did; + } + + // Then we query wellknown, which should mostly cover the rest. + $did = bluesky_get_did_by_wellknown($handle); + if ($did != '') { + Logger::debug('Got DID by wellknown', ['handle' => $handle, 'did' => $did]); + return $did; + } + + // And finally we use the default PDS from Bluesky. $data = bluesky_get(BLUESKY_PDS . '/xrpc/com.atproto.identity.resolveHandle?handle=' . urlencode($handle)); if (!empty($data) && !empty($data->did)) { - Logger::debug('Got DID by PDS call', ['handle' => $handle, 'did' => $data->did]); + Logger::debug('Got DID by system PDS call', ['handle' => $handle, 'did' => $data->did]); return $data->did; } - // Possibly a custom PDS. - $did = bluesky_get_did_by_dns($handle); - if ($did != '') { - return $did; - } - - return bluesky_get_did_by_wellknown($handle); + Logger::notice('No DID detected', ['handle' => $handle]); + return ''; } function bluesky_get_user_did(int $uid, bool $refresh = false): ?string @@ -1822,7 +1882,7 @@ function bluesky_get_user_did(int $uid, bool $refresh = false): ?string return null; } - $did = bluesky_get_did($handle); + $did = bluesky_get_did($handle, $uid); if (empty($did)) { return null; } @@ -1853,9 +1913,11 @@ function bluesky_get_user_pds(int $uid): ?string return $pds; } -function bluesky_get_pds(string $did): ?string +function bluesky_get_pds(string $did, stdClass $data = null): ?string { - $data = bluesky_get(BLUESKY_DIRECTORY . '/' . $did); + if (empty($data)) { + $data = bluesky_get(BLUESKY_DIRECTORY . '/' . $did); + } if (empty($data) || empty($data->service)) { return null; } @@ -1869,6 +1931,22 @@ function bluesky_get_pds(string $did): ?string return null; } +function bluesky_get_public_key(string $did, stdClass $data = null): ?string +{ + if (empty($data)) { + $data = bluesky_get(BLUESKY_DIRECTORY . '/' . $did); + } + if (empty($data) || empty($data->verificationMethod)) { + return null; + } + foreach ($data->verificationMethod as $method) { + if (!empty($method->publicKeyMultibase)) { + return $method->publicKeyMultibase; + } + } + return null; +} + function bluesky_valid_did(string $did, string $handle): bool { $data = bluesky_get(BLUESKY_DIRECTORY . '/' . $did); From 0dfb345f85d0b8016fd6b0c25be48e26a49e94fd Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 4 Sep 2024 11:46:33 +0000 Subject: [PATCH 204/388] "fetchFull" is replaced by "get" --- mailstream/mailstream.php | 30 +++++++++++-------- mastodoncustomemojis/mastodoncustomemojis.php | 4 +-- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/mailstream/mailstream.php b/mailstream/mailstream.php index cc283789d..ae57c4dd8 100644 --- a/mailstream/mailstream.php +++ b/mailstream/mailstream.php @@ -6,7 +6,6 @@ * Author: Matthew Exon */ -use Friendica\App; use Friendica\Content\Text\BBCode; use Friendica\Core\Hook; use Friendica\Core\Logger; @@ -16,12 +15,11 @@ use Friendica\Core\Worker; use Friendica\Database\DBA; use Friendica\DI; use Friendica\Model\Contact; -use Friendica\Model\Item; use Friendica\Model\Post; use Friendica\Model\User; use Friendica\Network\HTTPClient\Client\HttpClientAccept; +use Friendica\Network\HTTPClient\Client\HttpClientOptions; use Friendica\Protocol\Activity; -use Friendica\Util\DateTimeFormat; /** * Sets up the addon hooks and the database table @@ -53,10 +51,12 @@ function mailstream_addon_admin(string &$o) { $frommail = DI::config()->get('mailstream', 'frommail'); $template = Renderer::getMarkupTemplate('admin.tpl', 'addon/mailstream/'); - $config = ['frommail', + $config = [ + 'frommail', DI::l10n()->t('From Address'), $frommail, - DI::l10n()->t('Email address that stream items will appear to be from.')]; + DI::l10n()->t('Email address that stream items will appear to be from.') + ]; $o .= Renderer::replaceMacros($template, [ '$frommail' => $config, '$submit' => DI::l10n()->t('Save Settings') @@ -101,7 +101,7 @@ function mailstream_send_hook(array $data) $user = User::getById($item['uid']); if (empty($user)) { - Logger::error('could not find user', ['uid' => $item['uid']]); + Logger::error('could not find user', ['uid' => $item['uid']]); return; } @@ -198,10 +198,13 @@ function mailstream_do_images(array &$item, array &$attachments) $cookiejar = tempnam(System::getTempPath(), 'cookiejar-mailstream-'); try { - $curlResult = DI::httpClient()->fetchFull($url, HttpClientAccept::DEFAULT, 0, $cookiejar); + $curlResult = DI::httpClient()->get($url, HttpClientAccept::DEFAULT, [HttpClientOptions::COOKIEJAR => $cookiejar]); if (!$curlResult->isSuccess()) { Logger::debug('mailstream: fetch image url failed', [ - 'url' => $url, 'item_id' => $item['id'], 'return_code' => $curlResult->getReturnCode()]); + 'url' => $url, + 'item_id' => $item['id'], + 'return_code' => $curlResult->getReturnCode() + ]); continue; } } catch (InvalidArgumentException $e) { @@ -361,7 +364,7 @@ function mailstream_send(string $message_id, array $item, array $user): bool return true; } - require_once (dirname(__file__) . '/phpmailer/class.phpmailer.php'); + require_once(dirname(__file__) . '/phpmailer/class.phpmailer.php'); $item['body'] = Post\Media::addAttachmentsToBody($item['uri-id'], $item['body']); @@ -406,10 +409,11 @@ function mailstream_send(string $message_id, array $item, array $user): bool $item['body'] = BBCode::convertForUriId($item['uri-id'], $item['body'], BBCode::CONNECTORS); $item['url'] = DI::baseUrl() . '/display/' . $item['guid']; $mail->Body = Renderer::replaceMacros($template, [ - '$upstream' => DI::l10n()->t('Upstream'), - '$uri' => DI::l10n()->t('URI'), - '$local' => DI::l10n()->t('Local'), - '$item' => $item]); + '$upstream' => DI::l10n()->t('Upstream'), + '$uri' => DI::l10n()->t('URI'), + '$local' => DI::l10n()->t('Local'), + '$item' => $item + ]); $mail->Body = mailstream_html_wrap($mail->Body); if (!$mail->Send()) { throw new Exception($mail->ErrorInfo); diff --git a/mastodoncustomemojis/mastodoncustomemojis.php b/mastodoncustomemojis/mastodoncustomemojis.php index 561262f13..fcb8feeaa 100644 --- a/mastodoncustomemojis/mastodoncustomemojis.php +++ b/mastodoncustomemojis/mastodoncustomemojis.php @@ -1,5 +1,4 @@ fetchFull($api_url); + $fetchResult = DI::httpClient()->get($api_url); if ($fetchResult->isSuccess()) { $emojis_array = json_decode($fetchResult->getBodyString(), true); From 3dc77b21023c1258d2a7a23033f6ff6d0300b215 Mon Sep 17 00:00:00 2001 From: loma-one Date: Sat, 7 Sep 2024 21:04:43 +0200 Subject: [PATCH 205/388] unicode_smilies/unicode_smilies.php aktualisiert MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addition of the unicode character ‘asterism’ & ‘outlines white star’ --- unicode_smilies/unicode_smilies.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/unicode_smilies/unicode_smilies.php b/unicode_smilies/unicode_smilies.php index 3bd306449..22ee3439c 100644 --- a/unicode_smilies/unicode_smilies.php +++ b/unicode_smilies/unicode_smilies.php @@ -1293,6 +1293,8 @@ function unicode_smilies_smilies(array &$b) Smilies::add($b, ':microscope:', '🔬'); Smilies::add($b, ':telescope:', '🔭'); Smilies::add($b, ':satellite antenna:', '📡'); + Smilies::add($b, ':asterism:', '⁂'); + Smilies::add($b, ':outlines white star:', '⚝'); // medical Smilies::add($b, ':syringe:', '💉'); From 712edf42366d0ad118116be0f23cc20ea2b6bbdd Mon Sep 17 00:00:00 2001 From: loma-one Date: Sat, 7 Sep 2024 21:10:02 +0200 Subject: [PATCH 206/388] invidious/invidious.php aktualisiert Further addresses have been added, which are now redirected. --- invidious/invidious.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/invidious/invidious.php b/invidious/invidious.php index 7153aab96..033ecce59 100644 --- a/invidious/invidious.php +++ b/invidious/invidious.php @@ -96,6 +96,8 @@ function invidious_render(array &$b) $b['html'] = preg_replace("~https?://(?:www\.)?youtube\.com/watch\?v=(.*?)~ism", $server . '/watch?v=$1', $b['html']); $b['html'] = preg_replace("~https?://(?:www\.)?youtube\.com/embed/(.*?)~ism", $server . '/embed/$1', $b['html']); $b['html'] = preg_replace("~https?://(?:www\.)?youtube\.com/shorts/(.*?)~ism", $server . '/shorts/$1', $b['html']); + $b['html'] = preg_replace ("/https?:\/\/music.youtube.com\/(.*?)/ism", $server . '/watch?v=$1', $b['html']); + $b['html'] = preg_replace ("/https?:\/\/m.youtube.com\/(.*?)/ism", $server . '/watch?v=$1', $b['html']); $b['html'] = preg_replace("/https?:\/\/youtu.be\/(.*?)/ism", $server . '/watch?v=$1', $b['html']); if ($original != $b['html']) { From 14e1c9677527118c73e999a221c006dd698a2b79 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 10 Sep 2024 10:26:05 +0000 Subject: [PATCH 207/388] Bluesky: Fix for the handling of invalid profiles --- bluesky/bluesky.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index 9145fc32c..181e8d2db 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -1765,9 +1765,16 @@ function bluesky_get_did_by_profile(string $url): string return ''; } $profile = $curlResult->getBodyString(); + if (empty($profile)) { + return ''; + } $doc = new DOMDocument(); - @$doc->loadHTML($profile); + try { + @$doc->loadHTML($profile); + } catch (\Throwable $th) { + return ''; + } $xpath = new DOMXPath($doc); $list = $xpath->query('//p[@id]'); foreach ($list as $node) { From 10521115c4f51b4e773e94f3a8149711c125701e Mon Sep 17 00:00:00 2001 From: loma-one Date: Sun, 8 Sep 2024 18:12:13 +0200 Subject: [PATCH 208/388] More and updated icons for the smiley pack --- smiley_pack/icons/commercial/facebook.gif | Bin 0 -> 269 bytes smiley_pack/icons/commercial/github.png | Bin 0 -> 4720 bytes smiley_pack/icons/commercial/google.gif | Bin 0 -> 270 bytes smiley_pack/icons/commercial/instagram.gif | Bin 0 -> 1302 bytes smiley_pack/icons/commercial/signal.gif | Bin 0 -> 339 bytes smiley_pack/icons/commercial/telegram.gif | Bin 0 -> 627 bytes smiley_pack/icons/commercial/threads.png | Bin 0 -> 1025 bytes smiley_pack/icons/commercial/threema.png | Bin 0 -> 4777 bytes smiley_pack/icons/commercial/tiktok.gif | Bin 0 -> 257 bytes smiley_pack/icons/commercial/whatsapp.gif | Bin 0 -> 1353 bytes smiley_pack/icons/commercial/windows.png | Bin 0 -> 3584 bytes smiley_pack/icons/fediverse/diaspora.gif | Bin 79 -> 1147 bytes smiley_pack/icons/fediverse/diaspora.png | Bin 0 -> 4656 bytes smiley_pack/icons/fediverse/fediverse.gif | Bin 0 -> 444 bytes smiley_pack/icons/fediverse/friendica.png | Bin 0 -> 4719 bytes smiley_pack/icons/fediverse/funkwhale.gif | Bin 0 -> 471 bytes smiley_pack/icons/fediverse/gnusocial.gif | Bin 0 -> 135 bytes smiley_pack/icons/fediverse/hubzilla.png | Bin 0 -> 4563 bytes smiley_pack/icons/fediverse/lemmy.gif | Bin 0 -> 418 bytes smiley_pack/icons/fediverse/misskey.gif | Bin 405 -> 1177 bytes smiley_pack/icons/fediverse/peertube.gif | Bin 0 -> 137 bytes smiley_pack/icons/fediverse/pixelfed.gif | Bin 1064 -> 1262 bytes smiley_pack/icons/fediverse/pleroma.gif | Bin 100 -> 180 bytes smiley_pack/icons/fediverse/plume.gif | Bin 0 -> 410 bytes smiley_pack/icons/fediverse/writefreely.gif | Bin 0 -> 112 bytes smiley_pack/icons/noncommercial/bluesky.png | Bin 0 -> 4766 bytes smiley_pack/icons/noncommercial/invidious.gif | Bin 0 -> 908 bytes smiley_pack/icons/noncommercial/vivaldi.png | Bin 0 -> 4945 bytes smiley_pack/icons/opensource/archlinux.png | Bin 0 -> 4598 bytes smiley_pack/icons/opensource/debian.png | Bin 0 -> 5357 bytes smiley_pack/icons/opensource/fdroid.png | Bin 0 -> 7919 bytes smiley_pack/icons/opensource/fedora.png | Bin 0 -> 1408 bytes smiley_pack/icons/opensource/firefox.png | Bin 0 -> 12229 bytes .../icons/opensource/firefoxnightly.png | Bin 0 -> 4987 bytes smiley_pack/icons/opensource/foss.png | Bin 0 -> 4981 bytes smiley_pack/icons/opensource/jabber.png | Bin 0 -> 4301 bytes smiley_pack/icons/opensource/kde.png | Bin 0 -> 4678 bytes smiley_pack/icons/opensource/linux.png | Bin 0 -> 5149 bytes smiley_pack/icons/opensource/matrix.png | Bin 0 -> 4347 bytes smiley_pack/icons/opensource/mint.png | Bin 0 -> 8663 bytes smiley_pack/icons/opensource/opensuse.png | Bin 0 -> 12271 bytes smiley_pack/icons/opensource/raspi.png | Bin 0 -> 4534 bytes smiley_pack/icons/opensource/thunderbird.png | Bin 0 -> 4661 bytes smiley_pack/icons/opensource/tutanota.png | Bin 0 -> 5011 bytes smiley_pack/icons/opensource/ubuntu.png | Bin 0 -> 5067 bytes smiley_pack/icons/opensource/xmpp.png | Bin 0 -> 4985 bytes smiley_pack/icons/respect/cc.png | Bin 0 -> 4461 bytes smiley_pack/icons/respect/cc0.png | Bin 0 -> 4669 bytes smiley_pack/icons/respect/ccby.png | Bin 0 -> 4407 bytes smiley_pack/icons/respect/ccsa.png | Bin 0 -> 4848 bytes smiley_pack/smiley_pack.php | 242 +++++++++++++----- 51 files changed, 175 insertions(+), 67 deletions(-) create mode 100644 smiley_pack/icons/commercial/facebook.gif create mode 100644 smiley_pack/icons/commercial/github.png create mode 100644 smiley_pack/icons/commercial/google.gif create mode 100644 smiley_pack/icons/commercial/instagram.gif create mode 100644 smiley_pack/icons/commercial/signal.gif create mode 100644 smiley_pack/icons/commercial/telegram.gif create mode 100644 smiley_pack/icons/commercial/threads.png create mode 100644 smiley_pack/icons/commercial/threema.png create mode 100644 smiley_pack/icons/commercial/tiktok.gif create mode 100644 smiley_pack/icons/commercial/whatsapp.gif create mode 100644 smiley_pack/icons/commercial/windows.png create mode 100644 smiley_pack/icons/fediverse/diaspora.png create mode 100644 smiley_pack/icons/fediverse/fediverse.gif create mode 100644 smiley_pack/icons/fediverse/friendica.png create mode 100644 smiley_pack/icons/fediverse/funkwhale.gif create mode 100644 smiley_pack/icons/fediverse/gnusocial.gif create mode 100644 smiley_pack/icons/fediverse/hubzilla.png create mode 100644 smiley_pack/icons/fediverse/lemmy.gif create mode 100644 smiley_pack/icons/fediverse/peertube.gif create mode 100644 smiley_pack/icons/fediverse/plume.gif create mode 100644 smiley_pack/icons/fediverse/writefreely.gif create mode 100644 smiley_pack/icons/noncommercial/bluesky.png create mode 100644 smiley_pack/icons/noncommercial/invidious.gif create mode 100644 smiley_pack/icons/noncommercial/vivaldi.png create mode 100644 smiley_pack/icons/opensource/archlinux.png create mode 100644 smiley_pack/icons/opensource/debian.png create mode 100644 smiley_pack/icons/opensource/fdroid.png create mode 100644 smiley_pack/icons/opensource/fedora.png create mode 100644 smiley_pack/icons/opensource/firefox.png create mode 100644 smiley_pack/icons/opensource/firefoxnightly.png create mode 100644 smiley_pack/icons/opensource/foss.png create mode 100644 smiley_pack/icons/opensource/jabber.png create mode 100644 smiley_pack/icons/opensource/kde.png create mode 100644 smiley_pack/icons/opensource/linux.png create mode 100644 smiley_pack/icons/opensource/matrix.png create mode 100644 smiley_pack/icons/opensource/mint.png create mode 100644 smiley_pack/icons/opensource/opensuse.png create mode 100644 smiley_pack/icons/opensource/raspi.png create mode 100644 smiley_pack/icons/opensource/thunderbird.png create mode 100644 smiley_pack/icons/opensource/tutanota.png create mode 100644 smiley_pack/icons/opensource/ubuntu.png create mode 100644 smiley_pack/icons/opensource/xmpp.png create mode 100644 smiley_pack/icons/respect/cc.png create mode 100644 smiley_pack/icons/respect/cc0.png create mode 100644 smiley_pack/icons/respect/ccby.png create mode 100644 smiley_pack/icons/respect/ccsa.png diff --git a/smiley_pack/icons/commercial/facebook.gif b/smiley_pack/icons/commercial/facebook.gif new file mode 100644 index 0000000000000000000000000000000000000000..45488a5b5147f33b9237402acee364ec90062e08 GIT binary patch literal 269 zcmZ?wbhEHblwgoxXc1?yikx8`Iit2~L+gai^Oqmou>H)I-52&8ymau`^>Y{RK6>){ z@zdAOUc7tp^8Jff?_Yw@hj$;oeEa_E$IstCfBpIM=kNdj|0SiBa3RHig3d*$i6yBi z3gww484B*6z5xu1KUo;L7~~mr7=Qre5C+!L2kLz(ne$Q?tb4I@UxD@^lkRIQ$&nXc zUuwC#PEh$OQ}6G{@6j#vIbr5d>brml}1xFoc_Dev7nyK2dYUe*vl|J70-tWEld+&Rd zFNHDD;V#bZ&JYB-$RlL2;6B3gb+iXpV+_9@+-fqFGpSfK9X1&C1euJ(RE7bEaWhFk zkokr-<}26Ju;Yh^BPZwC_uVsYi{lZI~87Ce!H|^iCGyd7% zzYIK<=IJ;|v8=@O?-C9DtGe`(i#8!Ig~olCa~{3rt#1reGQ&EToieg0mz?+Pr3E$K zD%&Kt4rKV|e40I$J+VRe>|H)SCH@37?ELD>YxXl`522QDxxLLm z&4fEkvU2ARYhG_V=uEbfeLZdj?Fjkyv3m5Vl>Ko&!TB*0k33E=wvOhJ5wUYSz9HzTci zH7n-K5dU(v;_2a&-0cK&@>JURFX|TTf6d;v-o2fdGN*w$Kl-J|bdf&g>U@{0$GvmV z-MfF7WGW#Blao|V!(~2+TbH^gdnGo=%UACFu(lxQr;aK2W6#CejjOeJdl23=0TH&Wx?|FoxV1#M?0L3_ok zsguy#j-8;xq*_9s;io_ph7dfFjL0!J2sM*w9JFLaLE>myRu-GDzh=p)i91a6$FiaUb3NSh7(!7`%;7MqE%v|3hg3lkNZ20*$4`a=to66{h|EN;@L z8ZkUH4cAfQdPAtO9(zNoG1;1q8e`$fxE83IfLC@Om*H|nOpk?y0u8A(SgioreKaYO z_(WEp*eom7bb1E@%zJSAXn)MzstmLg3b9O&rCP$1%OrG*f3aGRk!rE^5kUwwiU@HA zn^374JWPl&gj@lKArkOKLbaOUarwMnP;#A#LUkB!fdb%665#MuC@x^51cOfy0tQcj zh!`S1!DSF^p@3lX*|>_!=>;*>NP@0JlY2*Hfl>n~g6l`{__%H(PEw0%aF#)*u`XB$7YD`2C3FrG`6P)+MkxXqNa#_d zF4g>LK}l-yX%uQA2AZI?;m3Mwr|#LM&wwgJb})sHIN< zfYk!zA`UU)D5WXBJTW2^v;CADwwNOnb2$?c zju`2suUC^q#{bf`Y#!LZtK<=+3HZ;jin?~xG(4s2t?Mn{M|Zn^l#_qZ3K(0Ba@c%6Lyd7U22aG}F+?0Ln}G{NTt1&8SG_}cO$_mq*fcOU#T`04~& zaH#)cOkbahWV#(PHRQw(YzrA1utH`bC0^R_}s5jpQSd^Ekn$k9ptOw zjFe`lg3~tiss&yd{+6f|_`@~|IIsmj-vBo&9v#<0}Rv%agnoS5Gy zO{{;GcJpn^^NUsbYVq{T$Y8hSVYAVr2X9tr(i^Kzm{{82D@OCH2?fdY+){d|VLr-V6BIO*Hf~jPna856w#CPnyZU?=Y1;g-eBKXO*_D)& zhc_&9*{k$@rHPMR_n^A*m8t&WtLT~hB3kXXQlF_=rnr}?@^dZ)r=R;qHFi8VR@7_P fcCP;IdePZ{i!aO>NYRW;;1`mIM#~NcC*=JX_GaJF literal 0 HcmV?d00001 diff --git a/smiley_pack/icons/commercial/google.gif b/smiley_pack/icons/commercial/google.gif new file mode 100644 index 0000000000000000000000000000000000000000..5855c74d745237a6fa3c8d17f4c630c9350b38d8 GIT binary patch literal 270 zcmZ?wbhEHblwgoxXc1$0?IkyGmz$Ie&weYb6<9k5t1*ye-JXvMldYAp1Ex)gjyuV%J=T^RtyTpI*VU?6t!h;n52|5?0CYGe8D3oWG zWGJ|M`UWs4{$yd~VvuLhVE_V)!r)_wNk} zM+F(!5~q5(I9PK{7H<1IbIk#^8*9X(edD%2SXau*SHA!0o8?}WKK2hvT`xK8*}jO& yrSXOTN2S`PGRMNk<~l77c9y8FjtRBgtPutiCvvheJ5HbIH@7KYd7gnHgEas)?q!Yu literal 0 HcmV?d00001 diff --git a/smiley_pack/icons/commercial/instagram.gif b/smiley_pack/icons/commercial/instagram.gif new file mode 100644 index 0000000000000000000000000000000000000000..f15e6ee8a2df5f527707ba988a3026bd3087283b GIT binary patch literal 1302 zcmdVZ|1;Zn0LSsq`y(NIlqBc~vxL}u7oCOp5|J+=p}s`#w(DWsO1tC6b#|szO^7eU zG-!Hmxcas+#gJL++Y&=WJEj|*J8nf?u^-y#%;%k*)#A_C>mK*~4_;zPY#1lY8F5B- ze?lOE013n+OZy{B@{yJOkrmm9y=lbUU)s7GZQT!S-Cx+fwMX{dKjrr)*=LvH|AI{4 zqxkJp{BR1`aC+}0g#jtZGY2-L0Gx{8RPfv}V9P0V`&8KW*)Zq`Hk~=^G~qf;v_TVY z&_wI5q77H!ihIfm-AuMhPg$kQp3r404B10w`ih5a)gyJ0nX$yoSoAXcaLFs<8mI3% zr~f)ph^GYLzAQO~Eepebf zR2n%v=l_W|ut*zNERWJCqBQ!zTy0RXHt3ozs94U`D7YgEu0|VNTpm4I&NKUAETm#A zq;f2zYCNQ}BIZFw%-92V#b{{N7`svv)-c4mJtJYf{ALuM5XZl zP`G*|yrEh+{)K3=Ml@9;`mvAOb&uPAkK57DZ6Arc)6eawi`DfH=@brrE9k73%-oX9bczO5(m9n>-(YUMnZ6-@ zu1zx0m|$p?PPR&?niA%l5)4fV3wO@X-%gx|5(G*BlmeIrOlIi-<^xl{xkOk1Oat@~6yr5Ta5X!tF#8g{=;OjGbg|@oGQuzsfDLkj_#@_>9t9!2Moz4c zd!8qH#J2^CWV1bqEv&S5|NY>COw~IXYdbN@g5SDh6?>5z)Cy~RH;bY*vdrsDYYppU z>M=EYL84$@{Fz17^zi)R3XjW|vxGK^)N|XMHHiaL_2~|2wu~uOT6z$k7=ypYTA~s{ zqy80KUX1=qYQy~8n6Ip*@f%Ce`0d}l8;*{pS+jWURjnbVnJXV%rtp(aY>8Cw9E^yd zE{@qLo;lwrlZb=X7RoZ7gsse6!B(sf}`nr1n+_`>{f!V%CPn zZ#|CC?5cQ)>WdxJIPWPQ<{&TNUq#giYF=C3w$u+*$l|E3B&D1nnlmOjq?Sxu=C>JM z)$qFH9tJYwFr=L9Y+bk wCC~D7lf{qx2ZtITsyuTFE}?dEd6{jnsS~Tc(RohlEx%H{gSuUCBqI_30Z9t(Y5)KL literal 0 HcmV?d00001 diff --git a/smiley_pack/icons/commercial/signal.gif b/smiley_pack/icons/commercial/signal.gif new file mode 100644 index 0000000000000000000000000000000000000000..db5aea12ec33b315e405aa7871c8403e2dc420b3 GIT binary patch literal 339 zcmZ?wbhEHblwgoxSZcxm1k&M$tja!EmVE${#@TQ5vR}cumZcwbvL9HLf}~9I-u*iFh(swWhSOHKk2)zgDGAVj# zSpsCdHwPK`-U4JeNTZ~*5<#T+Ptdt2HL)Z$MWH;iBtya7(>H)Y@h1x-7lS>64#;~T zk20`DADCa@AtJ$gWXY%U5VPqQl!a!^@mhavsc5yR-`torm!+RooquX1JlCv#X0D;N zp4p+7vDW+g?mTa=D{CmP&dzSEO=&4iZ*PsN=q>J!ZEK$15;8L=A%8}we}E%{H2|4w Bj4}WK literal 0 HcmV?d00001 diff --git a/smiley_pack/icons/commercial/telegram.gif b/smiley_pack/icons/commercial/telegram.gif new file mode 100644 index 0000000000000000000000000000000000000000..6ab4851ad4169b691ed355562ba2172e84516493 GIT binary patch literal 627 zcmZ?wbhEHblwgoxIOf2>JnISbtf$PgpD@n`lFwLxO8P~jL-1D9Z zEqpGr=(*UU=Tb|a%Po5$zwCw5@)yc0UZ}2kp|R?v)~c7r>t30ze`UVmmBZ%Oj$2;4 zZF>{F?_J#fcgY9eXB>W?b>u_YiH}X^K25y*Wy;krb8dW{d*kc8n_m~){JQ+kw{4HU z?|l4Y*OMQ6p8PoQ?8ng;KaaimdHm(i6EA;WefRtN``=H${(1iG?~8AL-~IUe<@dku zfByac`~UC1|Ns7jfTXn2kVcCC1f7dg6H8K46v{J8G8EiBeFGR2f3h%gF*q>jFaQB4 zq8QkBH#jskH#4&`w=uVL_b_$zPhe*0>7F>Pe@fHz*=E ze8$(UIVUon?dO$K;u12wZf`X0#WW7H5B4h4CeP-xx3XJTy5R~}P^*lj#T^Z|MuiE! x{5lFv9}cnYWn|#$w0dwLW<}5hjm9HWI8z#Yn)TdHbrel(Ok-6`EX>4Tx04R}tkv&MmKpe$iQ^g{cqIOVm$WWc^q9Ts93Pq?8YK2xEOfLO`CJjl7 zi=*ILaPVWX>fqw6tAnc`2!4P#J2)x2NQwVT3N2ziIPS;0dyl(!fKV?p&FYE)nr@q^ zL|n{dSH+%J1Q5ai`Y|js%b1g-Bsz|-d-(Wz7v))<&;2?2)SSftpGX{IhG`RT5YKGd z2Iqa^Fe}O`@j3B?Nf#u3C`-Nm{=^dvC_t@XllgM#1U1~DPPEV zta9Gstd*;*c~AbrU`}6I<~q$$B(R7jND!f*iW17O5v5fp#X^eq;~o4Xu3sXTLaq`R zITlcX2HEw4|H1EWt^CxamlTWx-7k*wF$VPP0*#vEd>=bb;{@U#SDLpQP7X zTI2`_Z37qAElt@2E_Z;TCqp)6SMt*o@_FF>jJ_!g4Bi60YhG{7eVjf3Y3eF@0~{Oz z;|0oI@9^$GdvE`qY4-O6Z8mbG3y)5n00006VoOIv02lyr0HVfz8O8tr010qNS#tmY z3ljhU3ljkVnw%H_000McNliru=m-xI5hy1flq>)M0scuuK~y-)t&}lqB2f^>=PKbi z?gOMrlRi~o7sMi;KuEDjDtlYI1PftBQl?53@KW3@+~JZ!k-(OLEDPDnMjJ)8G00oV z5_V&L*TlV(i)+F;@Zilb{N6C{KO-XYSwy~x2>*G0h{#vj5^Q;XeR{pTX}MfZYPFi| z?d^$(NDu_#IF7X2ZOO7XU$bqSD2f1hd3oXa`5A!4V!{3WJ({MitMcEV>$=2oOt06Y zR4S!$P19(#S}3JZN^y92xEXkHaRGp7nrnM?e0+>j3g7oP1A`#I^E^ZZUDt6OhcFCD zl7zuvK)GB-L@-SgAobq_9vvO6RCj)UP8`Q{yIm~HA_xMe(`lOD?RKeDD(ivGW)ol~ zVcC4cFesHu05lqnEb07lEX!H}YMO@UdBkzd-`4N<(RKafK*w>2qKK=jD^5;MsMqVM zbd*x$^Z9Jx+1c3&a6BI4x^C)Mt5pC_PfwZ8=Qxg&4P5qU`6<`e*XgI&wvAGX;c$qE zaCdjdWHNc5Y;JFFQ~&1XhKGj-!Z5`5eF}vFB7*PxDLfN+d3m`}*yVDWBuTJs`(vYL z+cw2wF^%u<@28_T8jUzOICvj$DcYx}CjcHFADPW&scc-=UAr7I*O#vAVi<<(?Cgk$ v$ZR%~PN%bReSP2Jg8eBX^5yli4cP8)Z#s&ArhdKc00000NkvXXu0mjfzromS literal 0 HcmV?d00001 diff --git a/smiley_pack/icons/commercial/threema.png b/smiley_pack/icons/commercial/threema.png new file mode 100644 index 0000000000000000000000000000000000000000..897230aa06fedcc0189c81925c89430f8ff703f9 GIT binary patch literal 4777 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 literal 0 HcmV?d00001 diff --git a/smiley_pack/icons/commercial/whatsapp.gif b/smiley_pack/icons/commercial/whatsapp.gif new file mode 100644 index 0000000000000000000000000000000000000000..59898b09bffb5b83fd36b4a9bc1753bf93f725c8 GIT binary patch literal 1353 zcmWlYX;70_6o%sxYY{C8E~vD!s2~OjvY3Pb+4qfXBqW4<9|>EkLxt*8>Qqt00*cnL zP^PvPYpuYv2B%c{Q&C)o!P-t~OIt(;kU&CKl8}}39<{^^U>7)ri$y?ChngXk2CAUo#7SK4 zJPQozSWY=~m@tXMnYjlIB!*MQbjp$^@tAoI6a!7FO_F6~uw3#;Btmx-L${C`+f~9_ zQgW9RN9Ng(g3wczV`B2%r6qnXBulkR4jbuE7SSq%{1kaqd1fBXE`>Z~&e23(wJKPZ zW+3KU_)t+rpkn`20mD(8F-tu(OTjE~IIa@OG9XOJfu5s@y@1%OF7}nMJ;sndi4ivTmvM$b|4W?t%aVd87t-ql(R)C^f2s)pFrp_RB8`81dXcCLxF=QUR5D+j_grGZMiL&|i@u?yU?U{%6v9NQ)5tagT#ZDatU8me8I zV`6calzg|c$WunPi4=Y<(JB&o%l1tb~S6 zW0sOWLrIw`z*~7Kkg>@;xlbeTsDSY53!-PKfk@C3@d|yaJrmfK$cn;WQM?Q~R-ESW z;#}A?8Jd0^croZ78V~*Vd+^V4|FMzaE7fw%SDri9+&7w+uH6pw=^Up{J6r1Qja`B6 z9&i7>;6RnX?!IsE&ve8P98&@PbrL6!YzxvdUw=aQU4 zsjX6O)@j_eIcBEVug*6K`6e*OLeDT!Dl;)CFES$((ppq>TyiL(&`y$OqXS%A;|4`%sO-Vp2 z3xEP2DDgH3eU*tT2=Z|)P_NY_oUE>|N}w~j0$8Gd{hBCP1crh^WA&rJHm<-TZ--7M z!J|@9C*p~Ql-QU|eE&pIcI{LWayKs?*I5fZX-3#X*sLprvvG0MPNK7IT;DM=Kxt%r z|10Bc(cT-wUOpFPkngM`|B-%`K+3<66)Y zj_Iu(Y2Zg`an+jZO&wZ2_@Nf5f7z)Ypt(us$c(1OqrYHUb1d+f!PtM%SHA1nzFB?0 z-VcAj<>?M>a?8%`S~W+?lz>2c5S#WxNLWHf4b$WY~cKFD#UXbwe4hY{4FB9GrdlN%*WqsMd4(w;q?vi zw?_E!pIxD+_ukW<+ZGe(?$~lzIer0M5!P(lHQv{~NlldLY47|ze0=i^osw03xCEAPCp6*VwQYQyN6)$OPr2Z;b1 zJeqJ8sSJD@mHtED@zz5>O(9#wLrTQcuGDbsTVFnK_j8ed$N$lVx<6)MBjU~vJ^LEI zaqRg`<%TtMWEi+}?u-p^Y}n1)Tz?lC{{k_b8WT7&d?$9@h($ literal 0 HcmV?d00001 diff --git a/smiley_pack/icons/commercial/windows.png b/smiley_pack/icons/commercial/windows.png new file mode 100644 index 0000000000000000000000000000000000000000..33109cfa72a07cb5637e72dbe3e3b26ba976d7ed GIT binary patch literal 3584 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 literal 79 zcmZ?wbhEHb6krfwXkcUj0!e8l#h)yUTnvm1Iv_qshJi_~hrjal#0!tQb5DI;5SaJu eeyx&uUxa7tw3JPYR;TvtS<4Zgtr^O|U=0A+vKN~G diff --git a/smiley_pack/icons/fediverse/diaspora.png b/smiley_pack/icons/fediverse/diaspora.png new file mode 100644 index 0000000000000000000000000000000000000000..06c32f6bfa29412330007d7c1f429f18816cbe37 GIT binary patch literal 4656 zcmeHLdsGuw8Xwv!h@w~!A7yn;q!z>^lVL)bG2s~=aSet?QK=OslL<`CYm)&IJYq$u z0xhnJZAGbXd8jC$i1gU7RO5LlER5i;~8Is~h;bI}HcF`VWV*;L?;CKaY(iGhl;JuVyqf z%vuaIOq&@s1evdD71vxE5vSi$@(PkC*E|Y{UN`H;mbUSZp6|!-9uJ$+G3vxG&$3#C z!QSxUPnexv%Q5B$?)P^(W>Ra5pPyXQxO=qs8hBkqjQc0KPs`fKmU>-G;KX|~-#st9 z)ar0~V~qIJ_Ni6LF55jKW`FbbU(%=euHW?^@yV*4zCVl^)mpcB%Cw#%@z-t^$yM9F z(8^C=Xm$Blz+2b33hItBCpD?v^IOkz9*+-{jCk_)-G9%An;p3h5ah6e2@6xm!opr9 z1k%{FWQ`=MG1#*y>7%CUxzJ32V;zu@~ESoNr-c1l;Lr1Pf3i-?>u^;}Pd@O;z&8Sj;Kr|!Yy_u98LW_>f!AH8R3MJg2!k`FJRe@>BGk~=l8Jmz@N{i>6e z{OZKA%6~|H9T{fP(i`q$k!wzIzJxTd)?u)&Fs0qd-?=7CwW6%Dcy2Bxx=I5Bh%tV58JvO&MM}Xz1Py> zI)NYiOWm0x%ZraaU%czetue!bjkl-#dcg%Wo|yp+HcvjAp!8ZEsnRQHo>^-Eod-eU zAhUs_7SSxMq*EB3gwu7To&z%~31_ZQj>rvRbSe{-X{6&aqvNT}MHH^$1O+;a%>*FO z(kuy^wHlp?FiSXgUIN_P%zO@Php>wzoOyBu9HuwYFvi1p2shl!q@$cbXIN}hsfk!= zL>~osl5kR4)9mfWI*>v|_4^yrj2e47DvD2QXf1%6z^sBnQ%1_|yO5lfyRLB4-na;$LI*PVY0dgJ#co2~Yr~Gk> z>nFm6T+Cmo2mI*ui6Y6?WCAIKfW{ZJeeV!bijy%T7o33Q^3Q-JXNFuS|0ECfgf z2us@f6cE_$AQvLcNRzDI7_ZlBBpe$BZ1e0NmV@P_B3V*OvNRw?P>etV2!VgRKtKq= zjh`=q6376&Ud5;_{|jwfJg~U8AV z(`l7GPQcYWM5U6t6dLRveeL?n&ip|u2n4taQ3_GeLp09CC>-Mkpr9X6l}aGOMQRkI zsln_fy_(G+jdVx~&=F__+S9HT>}@ZU&tP;$Ds8I*5R8iiaDOitzb|3FZO?d>v6%lm zO~iJF7%YorvK02!fer?V!W29^XXTjE<~K9`4xT*! zOHEx~CZf1@LB;ckyQ^w1S*_NI)z;4wc86D6kH)x;UYXmZtX;sne6PFn=E8c*q4ob9 z2_0R?Uq7p9RCGz)3fI!|yo&o1K3mp!8)>s@zFfGkr{|`sa^|j!?G#a5q(5?_pu8L^ zEw2mPai3Tg+;Xe<$UoW#B9M}m@$EvY{^q1rL& zWkl)O{JTGUCnWBvnTLgE>X!WG1=sYv%=@Y8^uEnO$7fAm-R@osEfjC5>^iYBC^dXb U{*8DK3n)7z3y+pogeGVI7lk^>ga7~l literal 0 HcmV?d00001 diff --git a/smiley_pack/icons/fediverse/fediverse.gif b/smiley_pack/icons/fediverse/fediverse.gif new file mode 100644 index 0000000000000000000000000000000000000000..498b57426b264f7d09e8e72465e00b2148ef9a3d GIT binary patch literal 444 zcmZ?wbhEHblwgoxSZc~JmEr#qwzvNo82&Rbc8UMGAkiOf_Hwzwj=kE;cj>R%YC3DX z>9ljUQWwG{r$(Rt706Ind2@EfB!iaH*sel~~e#zNuh{UQ_himcx$ba0zc`w8LOn*{Ff$ZF?z#n>=Ht%j`K^^PP&EMD>@IS=<{Cs}z>Cn*os+4JXa zmtG@v%>6|2T2YbJM|~MN1-BpBTy)-t;jzGxO$9O+JRUQ!u(7%D2?~-D_Tbl`3it_JYO-VF*cjXd>kW*CPNQHp zOHaX+nbts%`MOs1+0a_p@pZeKY-zCA>~ndS=ww(yqT?vn8|7`BeHGjTCljNONgeHW z@~>y7*1_|!!A{=~sJ{?Lwns|*i|^|>NwmsUy^4qK@jd4*GkZBBS;r}Qdx^N2Wo`1b7v_0`jL@pB#K zhB?26(lhlj?7E?EH@VF_W7hvtV0!*{(<5j}#ktsuWOtSS`LjC;pMp`xr-$AhX4_3>5lKdV;k{%Xg{(wV11+Yi-bt*V$;R`E>s zyHl;5mMXe0ZdhBx-3U+4$;ZZ*)J)Ewv)awo^Lljli--|bk^G{BVTfVkHv3_PZ4Phq zZr$8cr}#z5@yl)TxY0G-VQJ;0z4(n=4M%QbHnxq`8=9UpZ>j#t@80S)?lN2Zqq(c@ zuNm{mW>Zl0*{}JYg}!zvFIR=%ev^M{+>k-HY~Q5nn1_ptL!kJM@ryt4@v(IseQv>X zv#F%==#s|oU%j$&!Iht~lj%j9|2UoMhA#->lVxwu7MHP_rHm^?Gh&JCR6K>3J3s}=N(FtXv9fTSm(KaDWPf<-Ebp^Qw1 zfuO=ODIM$Emx3gE>yoVwi{Mz8DoVx`@{#uzRT|D}K!A)poz`WT z-#cPyEj5e9Eo!2HLXiYPr6Lp+1xf=%??H1YgAsJ1g%d^iBC*wDnHCHb1BAsbeF_My zc2El@H&8gs7-AVFO~$pP1Y06|-Ab^WNSwtLI7M+gPu-7cv~?-Luys*jIMH2#5znMZYo36s z+eM_{x?~FM9zE^)&QAYHE2slCh$K)$@d5}5$`d1~kS9^25*~@8LXA)=6;Wijti9|; zM#GwL0~MAGbOc&~_OxmRkF`$JxDRtNrBIex0D|!l3Ga`B33>_^SoVx}6$cCcph>V5 z&}WkYaosksd4au9(7PG-Xa@5AD?dGR@mCH3!~KJNl)n9P^~?293Val}zq|V7`X~iH z3f$ja|2Mff?~hZI4!i}Kz+owO_%Q=GXxXc$MJS-*kOA6W|Al8gung2k#v38X3H%x0 zP4#2d-N> zMLA$JIz{D0;M)T-y$JPg_h(HZ-mdq`nwQV<8i%;EoE1a%A?a-s?AJP9qrN=p^t`3W zIPuvEZ}BK`*N;CI{oYtC5PeNR^$iV-2Fr7pKO$Rk#yws|Er-d*g74O^mfe)J zr?<3izm)L9f^6`T-+ASZ;kdWotD1|y=H^tJRSqW>Ur?S|6sq_1Tj_CH8Z8Z#cRqZ> ztDLjB($ulYFRYVsmNan&{x+W~9($oVM-~xZwDpJ7ymQT6$UR-aOr|{V$bWWRU4MM~ zGLO0y;?6@iOxMc!)8$u&jMf%>+Koi@Pg!|X*Z4GxRn=*20{)QKR3UqVMuJzMQ zSkd**Pt@%>w`^lt^to?`&Q5D9dC3cZh$%83bAx79^B2y=Gb?LqCxnZGF5him;5|lE z8qT;hU5s5xhkNww(?R5uX(0(?H*a|3Sw7;y;ZZYw&fl;)E~_g*ez0|R2QmzyI$WtV&ho*xI>j_UQ!YotQnMB+Sw}K7}GfE>Ex%$hs$kdyTos8 gJiouLq52xLcS6CCT$hWwc6x=<10~i#4vM_Qn z*fZ#Wya)0q1Ka%r^9w9^B>Imm`E(*jYw}r*Pd_I|F`s|@^igM(-ki*jD`xuGi9ddt z{LbL`@t&Q!GyToZWfePboUK_=877u0ER-2k6(*jR7~an)EHS}dQISzmlTlk!UQ|sPD_RMTZt)tRkfV4$&3N0m`mEl^WKQD5(nqL$WlRXu%0 zjahD8dl}U7G8zLe85kqoiVRU6=Aa`kWXdp*PO;7+K`2+z9 z0096j000007yuXm00K#jfvKD34516Lw!`Sso8Rmqm~u?O_;r)nNh_L?=+mmT42BVW pjx25y(SSE0$n|pVR!fVsr+W&A(&_8!!D?q)?WLQvg2$@@06T;qHFf|1 literal 0 HcmV?d00001 diff --git a/smiley_pack/icons/fediverse/hubzilla.png b/smiley_pack/icons/fediverse/hubzilla.png new file mode 100644 index 0000000000000000000000000000000000000000..c5fc6278e937629bba214062056c09fe2a4c6d7c GIT binary patch literal 4563 zcmeHKdsGzH8DD%N2!bM7fjCTJ4Cw6c%mmVEv?|Wd%q|o5#qKODRC%Zv z1Zy6|C`21+ebje}^#O{gV7G=EHJBn&Z7L+RJ+&(_N*<-=&MpF;=A0hRY5rr+nVp$? zf8X!>zTfxVd**IUO<5G+H_J~T5CmwF6Vt$bI=F&;$AJIFZfiTZT`SDU2pd zbQV@Q&du)t(DSu-rf_Lpr0k5mc<^G9;g*fvDf~!sX1_yyq(iY&bFj(5eR%X zvk3{QnuLUBiGg%>Z+Kgs+#DBvB`baZ{)~`+LigXQB|4IlS`IC*^_?Dn?8f0uSNCV# z*cZv>=7y~H4=kF$JYw~3hr>F3+@&c&hKX~NW<>QCYig6WO?34;^WC|9fk8FX53E$@ z#iRz$}^~=zQ70`sBG2(f6>#nMOAu3n9dj0yw%HH{Id-3)dsRg|_cdDzJ{8PES z{GdE%LeGZ#zVog|_bPkOYG%At)ZK9Z%dnnbHIKQzZCCYIs@%<)^YiLHxpI_#y(PWn zwPkHlS$}9aYP)y;=(2wt-LUjOm#u5FR(?TT3x27td`@yu?cVKJ^lu^;9!aSvlRTKK z`gim8EO=-9acrhCG_`C(NAISmm)z!Km%BH=ACe+y6rJuz{l?{$E^j{F^rq>YW6akd zl+J7HIw32qUiwK`1X4KeE6dm!?Gf6JvBLb4+PMibX3>{zA%5dO>)&=EYU1R3V``;m z&OC`pnO!p3v7^B!FtD@^W={P4{HwR`b~YLA^!E!kW!a8>oppTzXh0_m8ZA@1grF=Y zAxT?wjL>Paf({f2RIyGgN#!scq+<-MSq;0-HNg-|tKk(=typVKV6xfdLK~A_n36#i z=1@u+j*anCISD{uVmK0Vnv7;U;Z(yOUIIMx!y*{+K)4(=oT*KP5-c_bk_aV2F_PqD z^DsEZ4^r7^J&~5UaDW25so`vnvl1dvety0%9~W9|1`(=MDn(*UgkcCkAoc-L+ z{Y9R_%aO>~DI06$Sc@6rIZ2(x!Kq;w%tO!OGg-CTL3*=&Kn0+O$Vpm7s8B32nMA`a z>|9bFAQ=eg2QBOwV7-dc7`w$`qnM;T#>~AqoPwqX?X3=*(UT5Mi5Mee0#G~fiazIZ zkw%+3Xu(ThU`+h0+A@?G@_G{N<>e~X$7i~C{P(Qj7np+bEKJKcq%|H zWC4#Jrzois*CRSyjv^8{g(FHFXAoLOGq_YQSKxZdFp8x%7IY@FCE0#%2ed$aA7%A@0qF zFAD*Z0m71ep8^7p1;~X+urVZOv1M2+Mm5Zb1o4)G(^{~cXp$onNsa-ez$YPA5U4Bz z#RxG<;OIOtco>Ga(5$}Tf1&xs1F5_vPiF1Fe}QMnyQ0#WT<@Fr)yR655(Ie`1wm5Y z6zpUk<5d`Nd8eps(rjSB?lI7=&&JswXaxmMQgRxTAqqJtqJ-4Zh(a%=5fsNs95e!n z>b%`F$ZogjxqQ;bEHD5afmWbBJz7DpcnTHe(QFW%pUv=90D>W61u`TUJ|LKAAYl=| zXFSVTCHgN-R35;vO$OL`$H3+V_CnF%W;mc3h~UTk4bhqJ-aB1ajaCR=!BreEMwEm*1uHtfB(3YnyN5=d2P7k@1R(>ikX5*fU zbzNbZ<(cFCvo3!0`{=SzpSJSy+Z|iWd>5yU+c^h@Z$7S2+dk}Y_N~BQeT1Gohx<{J zgW=78?6GUx(hg;01nydLrt_M38%G4hE&KFlHdnuTUp4%6eay~QrhawkN8pIr`r*I& zzMETgrt{P)B=JbvA)_p8lDom&^cUCDTjn!wy1J$mH?DPc<*HuTdEn)#TRV&kqaLd) zb(!6dzJVm+fl>PvA6!3e>O8$>erWS~W~KY?@%EgekAvGC#qQZfxZsyPjgKz4{hJPK zsV;21XOz|VgImHz|IdE_ zlq1|g?0LCLQ#!REK3SYxbD;MdT#Fw*e7pEWdyZsQU8WJM=73}biiwJfii(hske!{KpP!$gprE0lp`xLpqobpyrlzN-r>Ll? zsi~=|s;aH6t*)-Fva+(ZwY9dkw!Xf;zrVl4#KgtL#m2_Q$;rvf%gfBn%+Aiv&(F`% z(b3-C-r?cl=H}+-=jZ6?=<4d~>+9?6?CkCB?eFjJ@bK{W_xJkx`u+X={{H^|{{R2~ z{}~%1A^s6Va%Ew3Wn>_CX>@2HM@dak03rDV0SW*=04x9i000;O7ytkUs=%LcNGuwU z$fR<~Y&xG%CBj5fFc+i}VhFhTzMOzzVoI4ki2#T9y#a)d@3%A3$?vGo{UHR{zAGkd zcXur(Up8+-2Q)qsgM@btJ~LZH01z6HksJ{LNF1Al97+{FJt{JHH7sltN(DMF026l^ z05LfPN&y%?EsZrbJ~%Bt6`x3op*|oYAs{|G8$!uR0Sqq|Ul%S5icHB0Iywv0Q9l9$ M=~O8@`> literal 0 HcmV?d00001 diff --git a/smiley_pack/icons/fediverse/misskey.gif b/smiley_pack/icons/fediverse/misskey.gif index 84982750c6ffcc159c88b23e461aee4596f8f555..a4d6bb340edc3d19574a397ed51940eeffb6824e 100644 GIT binary patch delta 979 zcmXxiZA=?=90%~b_GquAv`BHQ(DATgDU3}9LlDSHXMi>_5tt@(0mIP55R+|jD1|c0 zRvua&T6*_C1_ig4r!K^8Y#<8Q_BuscdiOu-T-=N@GZSY_Os2*JLeg1Y_{%5Xd|!ND z{wV&K$W*PbDtYa!0#P7Oy~sruYM4X}lW6M{^6@nC$u!a$%b6I|FoU%3L5(wrVK#(mr0oXM9y7-`ekSOMxh3elozOX-V7eo0y_?;&AiumIzp^ATf01Hd zmYJ6mJHO2DT+TOjugH2gh@s>HG?>|M#|`%2R1m07*G)hq7z;{85+z$dW! z`GY>p>W{a0vj_bGv#-$XJ8q#9EWYd^8tbQ%Y&6#GFS64-dw@3_;0*+hTD~r|uk&r+ zD(yj@J%|mh9Ul(K93lDeM*K(!9b7*#Xj<2dY@j0>{Gnh4!JxLFmS8X3X&BQObQWJk!(C*UL@HBl9iIIjAUOR*(8#c zlWg)R%X4hRmitCojAZwdtb$}yNH&#Z^2Q)WhD}-kl>i=~SQUV2fXxLk9l#6#GXXp_ z#>D}c1>nnoJ?7*v096E237{Il8~}4krV7A30FMB86u?5jY5*)I*=hhw04xQ2rJUkk zp}1odS1=xlqqst6L^K`|P+Sqky-IP#6j!37xKfHMqqx}g1jT76u7cvU6sL23C#N|5 z#C^fYrvB3h!fOvi&hN9X{~&Tb6uTaYuRlt3{}?~{lVs}Wq^T|G^p@1&D0jGy{7>Lu zQ%%p2JS28|zlGpY9NpCNoshDg`^j$C`A* zFD~I3Ix|yQr&y$oGW?lcklJ!1psBqO=#k^v#)Eu*LsuY9`uXoq2J(H1M5OFLs?xj$ delta 331 zcmbQqIhDEI-P6s&GEss-f?=sP14G9uhRziXohuo-fM^v%*J`G&mCRi$7`j(7bgyFQ zUd_wlM9*bC-X8( z*V{AbFaQC_VGL|@56my{(2?ptv83o^j+7)9D_dqqSsN$o!{eQ9%x*2=3xB%q5jY+3 zQPJw!@^~|;oohr@A3oOmRk=s4tXxyEoU7JJ%c-fYtwTXv#J;CDyH+_)Wy;jJ+GK&* zbK32bOBYRB61QwB>x!jQqLb|flIN|O!ldUUoommsb!EvE2DjosjkHz5aooIa%*pJN a<0Oj$g*+m8MV$i${O&(^_~@Y{gEau$?t9<> diff --git a/smiley_pack/icons/fediverse/peertube.gif b/smiley_pack/icons/fediverse/peertube.gif new file mode 100644 index 0000000000000000000000000000000000000000..0cfeee9c3e965236fad3af30caf570285a0f4de8 GIT binary patch literal 137 zcmZ?wbhEHblwgoxSjfzvD6ddlT>LSES5jI@@t>e`QEFmIYKlU6W=V#EyQgmegW^vX zMlJ?s1|0?<0BK@ia-Gw^^7PpUix>mUyxty)RPL)3w%|~Twx9U{bJMM1Hy;T)w oSsXWY|EM#bm;AzbkI9LYbC-O&W|=W>%2G{YzqR&zGy{V*0P)i<(EtDd literal 0 HcmV?d00001 diff --git a/smiley_pack/icons/fediverse/pixelfed.gif b/smiley_pack/icons/fediverse/pixelfed.gif index da5c1e97bed58f41233e32428537f70cd9c1b665..b42d26b5ce5d3e5fcf32a8e476c6cc98cba7fd3b 100644 GIT binary patch delta 1241 zcmV;~1Sb2a2<{1gM@dFFIbj$87y#$~07r04i+p|ZRxQ|N7XO45|AiF)h7&P%n3-+Bt6wT zGfucU3g=W0-AVO{4&M?=?h#P$6i@IMP30$1?Fv%v4pH$NO!6U0@g7U_BuLaOIuO}K z>;_cyC`S-~+eQ)BL-j31)-*Tk8(r-ZPxdoH?GI4@YYr39Jn>^&} zb$k5u?f?J(_}s=A$vGI!H}!M~+$mkqCuY1RgsvxlnW8AFnj)v6CAE$amAP=em?*!V zD7~2~!;&h>voX2CF{;Efvdb~7%P*wFEStS9q0BS0&@!*pFsrs4kI{Cy2;o%5HMz+& zw!}8P3ENS@H@*kcP`^0Ar{}&1$V7JCo4Gm1yg9@?%XbXcM&$VL2);fG%TTsD$}7uc zvpday!S3P%k@~Pa&>F;60F(Y7&L|JTd;*jGtv%BRy`lh;`2dvusy@~T$%Fuq{s6Al zs6N>b#$W)e`~ax@SjgEo%*s5xU<9r+0ITf)kNu`U+XBJ80L#lB$;1Go{Q#x>0Mpd~ zyXFAd-Uskr7|<;Ntl|LP=K#(34%0&bp#1=U*7g9~^#GFo4b?XQo$!v+-vFJv0OIce z;PU{|_W+&!)Ox}Lr_KPG{Q$`L0G0j#!}tKb`2e^20JHl5uKTV!#yEr00FnQ$Jjq&K z&UaSCzdFLIL9qah|F=5Eusq1KJI#$sy%u)q0Eqtpkn`RyqyU8V0Cf7%GOp?>o6Rx} zu^evVdQQaRES~iyl9LAmD1R6L7ytkW{s8|895}E60t5*ZEFj3Rp#%vLAUrULK!L@E z4JQZ?AYuRn2nQG(RJa18z#>(MXeq)(K*R?j4;C1K@yL-ONRm8}!i2^{i6IlLXu{CQ zO(IH`NU_po%7hFMfo^D$V&D-YLXa+bV#Ugr8#F?MfEwX}1*!wF5`W3LGtHd0Z`rsR z`+!1|7Fh(|WGkgh965jk$C*231r)shgbYEN1W%$ofg{VAGseOQC@8XsS*!$4pFo86 zNEUpCLk-Me#H`H&S`s5fqXEb1@!~X!)JWb0+Egi0KG?BKQK}6kN@^vEPKmlSX;Gor zpGL7@aoV`8C52j%;(s(r(sRJ2O1ELs1Ok!|>OYLT`bQ`hDc+I3=Q?(5RWlbST(F3d zew9E&wJ3KtMnoeA-}XD3U`LgcMUYpVABmSvNQw6D!^pJ z%0RWa$D1U|JOd3j%ya`zIO5zwj5FN8!cZ&%MuN^a9)2_9I6}7!lZ`j#U}Pb8fAk_F zjpN{gBP{Hg^v`>hNRkdN;Sfp8k>*rs6O84v(F DFu+Gr literal 1064 zcmZ?wbhEHb6krfwc)pflfkx9i(SVs+lirK^zZdiWAnvzHv+k{=&j(4r4^qAhb!UB) z_Wda1^Ip#9BM`}Zzfy9)sha#r!TXbf&nHE%XR09&)T1tGXYSUU_gTgBv#RGC4cE_V z9=G+a@95iXHr{YXckUNW_b*!RpS4|gnC;zTw&%3*#+wF9uNkhqY_#Tr@%jruH71+S znruF4y6u4Zfn#Pn&zo#GX143F`QCk&hhO7VvkE*~nS zMYo4DZ1^Rz)AK{6G{eSU^QR~Na z`SU#r;CmdPa3^)urdWo%4;k)!;dvI!^E`y%-WQ%1p~BB%xn4zby@_IY`nl`qvCrE| zCfr#4Xy5g_hpxWZfAjH?+gt7&J%07pzQ>R5etG)$*SCLv|NQ^^_y7O@lF~{e6Dj@^ zbS_FwEJ;mKD9CR@Sj140SG`Dg@NM(!+%bZ6VH4ljpKLl#Qf0b zo~TjyY>TGxGOok*(tIWj4;FIDT4bKmNHj5UU}O`q=y{=V?A&qHW;US+1;^$N8LJsD z4koLgoa_9bO{HRjqRWiXH4#gHO*!ta?DSv2VnqT&!-^%Ip_wxuaRe%`39=+G2y$g# z@|-3oDP-c<*eRm!Hq&+K%S(%0YIJG}7BaDFhAsDMoV4X-kcw-b-js%mO0AmyQ~rJV za9C4V#U%RQ#2F8hSOtvc8hkZWV(FT!%^ZIqA<)@(scXZlIWL`_o^X(wQ}{t+i#wl$ gPEc3Ol!K4hCYi>qv5_n)OyH5Wu474*5MZzd0RKgqy#N3J diff --git a/smiley_pack/icons/fediverse/pleroma.gif b/smiley_pack/icons/fediverse/pleroma.gif index 7be5eca482992d966a37bd6cc8f7662fdcb48547..88b362395249c8b9aa41da0089e69a8ced223aeb 100644 GIT binary patch literal 180 zcmZ?wbhEHblwgoxc+AbfAfPNHrLr>5enYY2;Rg3}?VgXP1U#7<@O44x&&6TCmxN17 zDc5k^=nu8oXg+l)NhJq8DB}0h@IOn#C8d>sNbx5NBNqcZgAM}_fYdTD zYgTCK+}4`+Ol`_E+uoP!CQWagsL^&ka+&z4#8~e2@BiG)TY679=hU8HCI)K&0KXPh_z{vYttjwr$=r` zkKC9ZxhW%Rb4JwG%&2Xd(c814cVH)Y@h1x-7lS>6 z4g(N?Jj%ef=)n8}4;?8+kHwQDI!ZirP86Nw*qL@iI3bFqB<042R%@56Ll3Vt{0Vm8 zGcYkb9JfJE=I0v`1^EzTW$hvjw&-96wJKvnc_#K0=_+kG4iQz(7#_na6{T?D7zUN@ zM2Qr^r4h>)sV>!Dn8LSIlRL*=vC2@kHit#ONNL-4d$B})1>Pf04C;n*LfNOCM2v(k ZyRc}B-f)p!bJw0#y#3+RhxU#P)&Ml;m(&0N literal 0 HcmV?d00001 diff --git a/smiley_pack/icons/fediverse/writefreely.gif b/smiley_pack/icons/fediverse/writefreely.gif new file mode 100644 index 0000000000000000000000000000000000000000..baeb03b0ff7dc3b862c1d0492f49552a1ab2d3ba GIT binary patch literal 112 zcmZ?wbhEHblwgoxXkcWxcI}#^w36aKLFb~>#FEq$h4Rdj31pDc`A42%pq z3_t)<&cI~U)4%fcTmHp!w%j`1U}yb>tzzND*2SMIPjJrDoV`*-re4s<1XYv?#f-bCMl2!Fzk=-UY6Y6 zUiLQ0B|s4@Euey^u@%z}C>BPY&~!qPajZ!Z6seWzh|yNSA{A`4NNpem2K(K;BqXCV zPG;&~&CTtP@B6;@dGCF`@B8Myw=G&(G0mE9MG$0KC>W@M&m4GVXHA6nyRO7vgpb~~ zniYB#*McTBRg&WX)mxJQ1!-AAko2FGXkGTi?_}M)mgk*7tSZ^@Y2vZ7dtM{%{rL;Z z{Kh#w5BWW355|sovYri|>F$502VKQZ%e8K5q&9bSSi)Tw?wnJLF6lZmXYX&<`##Tl zFgLrppWnCh-uL?!{p{a;MB(-aUoPxhm)}qG+b8_0cWc+4rZb&|?_Zpho4=pg)~S5) z>Qjn(@apv3f`_Ia|HF)Fzn)uE5E2_t%O@`{&ADl5Y))3`yJlQoV#WFOpQYzsd^z>v<<Cir?&muWGYzNNhQ1RUXWK3npIo`$yFG7a*Q6;}-rGMY{kH48{`Y+=UO%b_RfOJNL%Qy^G@A3&&(D4=WM6eGJm|*^CKMBZ!P+`WarEA4y6{-KDX^B;9L?%qG$|3q8+?=0Ebo36|N2XEZG@9i^(H=gUhac$z%DcT0Fh`j=fE-l02 zS`i7ef~wd!QRRUxtt4U9AxMcYo#ccDprbs9$q6rZ`K4DdR2IG1a%Y5$B+Ed(9Bk7- zbz5bP(AFS$M9jC)T9RfVfC6+5O)K$4icNbl6PJbWhM2%mQ$=s^Vk;t1v`p0iO511~ ziI=D4W(r$qMN2eMVygm+2O;3di`DCTk|l_imKIx!!=`F6!tU{S2$CWw3Wpkasx_f= zX*`iCG$1k<0gw_jIjPHP0yQu>UTxC77zXFjq4<^|0Ckp1{4Ih$q+|y zIRw&0x^bt&?Z9c^;c*Y+rf|_EcwC}~k!Z?20%EBq!>Z)sBcn2)Lt->KqM0}bHX5;Esch}7-h=@Zc3tY zPM4s87YoaYru1#q8d(9=I%lwHcT)~GO*0fpQ63kSab#LA16m4JqJe2AZ4TNrH$Hu{gO+5LJSeB2|5j6!*-_P?F*C{xPW;UH&5+xZ4RgKO~(dVtX5PR7LVI9=m(jfsIVDUVmzI9+36U`)#6 z)%8E4%X<4b1rqRAPzyXP?RAvyg=gYh(Qr+9JGrbP87^9Vb^QB($iVS6?>-8T+!np6 zvKsM!^e+5s2eI%=DgwyXI|_nuFeMqRO(DpgxyEHdc6ZE%!pV9lQa<@o*7O-jUfqF{ zFF_F#3Y6Al^(i~+tO%KP^!xwZc**|Rp-SJYlOA8-|KY6JKgpwix`(;rIZN@0|2RLq i{>B&IYWQU^?$docXIk+7{;I_g0|}K^209n5+5BJDr0P5X literal 0 HcmV?d00001 diff --git a/smiley_pack/icons/noncommercial/invidious.gif b/smiley_pack/icons/noncommercial/invidious.gif new file mode 100644 index 0000000000000000000000000000000000000000..deb471fe9c741ce4e47fd93f20fa8aa4fb4dc9cb GIT binary patch literal 908 zcmdUu*-z2|9Ke5OhpUIuTIsZ-?u2<2Y8DI zc!45FJ3^ zqeDVMqNAgelaq6Eb4yE0Yierh>+74Fn_F61T3cHi8yjnDYbz@&i;9XeGcywt6NyA( zKtO*`s{QdnWCnpsOMR0KN^z`)n z{Jcmcij9rsa=9BD8xn~mK0cn!W|x8F;o*si2^x(?rBW*@DspmihK7bVH#fJp zw+jmkDHKXsSs9&9UszbEuCCVW^=9VJ{}-+P7~2!EXcE@nG6qk=Svoj5|3Iv+ZW`Q0 z^oT8T&A(9)qhE-jk%i+x6F1%H;cL%%f?_KBfw^6V<0YDxXR3cAs(FtVe6}zqTHp!R v!ZfSzCe~&q?ZTqBKQXpf#8=LgNB1{GHbj-6`pNIxN*e}!rPaak2J-1IzTnMy literal 0 HcmV?d00001 diff --git a/smiley_pack/icons/noncommercial/vivaldi.png b/smiley_pack/icons/noncommercial/vivaldi.png new file mode 100644 index 0000000000000000000000000000000000000000..17d09db33a04906c325e1c0c92390d3421698a81 GIT binary patch literal 4945 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 Js$$dT{t8o%qb&dc literal 0 HcmV?d00001 diff --git a/smiley_pack/icons/opensource/debian.png b/smiley_pack/icons/opensource/debian.png new file mode 100644 index 0000000000000000000000000000000000000000..b9b8a16b300e65fea37a1e065c2a1f2278083a4d GIT binary patch literal 5357 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 O0000X1^@s6D=Y3@001ZCdQ@0+Qek%> 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 -%Km!a0WU8%-`a^r~M{&vog?*f!4afNi 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 MXRc$<;-ZKC1S>)FzW@LL literal 0 HcmV?d00001 diff --git a/smiley_pack/icons/opensource/kde.png b/smiley_pack/icons/opensource/kde.png new file mode 100644 index 0000000000000000000000000000000000000000..6a6ff9ac7a5460d0ca7a7a791cc556e7ded3f434 GIT binary patch literal 4678 zcmeHKc~BEs8gEe%L1#f3Wfe6B1x1o{Cm~7q5R{uB!7OAH@uJh+freZr4MbTGqpYK_ z&N#3GQeNXRqJqO}%^)5th~PDfQ!?CXGtGgGx?)y{vU(#QLb-}}Db z``%am)~aG6Mmmpkh9GF9A~G}a>nLW-w@A+8 z9h~#IXaQ;5bXexI2U#m|Yx?l(zw3-eHQ7J+~US|Vx*p#(F9$Bk$ z&z-a2t1w^Zbl0V)Rhut|g?XmFzfLu|(YYKeKKl4iCE_X5`Ri?|H8or7_O8l1xc|NV zHcr>z*1Ih`Z*r$L6}cyz>}q)!cp>wKsW~g>_(2_t_`{b>_%3r(~Q~9574FG zY;#;YsfvH(d3{w|#nzjsmjDB1&_lc@+J;ib)~v4 zEu!FQ&bbMRZHl51XEr#fUuxW}Gj|xz4z8`7^{V89$|q>dq#VEVzFC7kJsn0*J-hg+ zHKR1s@T!S!=oprrX5J^#mM#WWXQe@P#VeyR!l>utq)|iht$GtEI|vGxX*Jav$Eb2x7C(3ulpCbd{>Xm~FK7|FTG z3}eCsf{cs|euju|G$#oV6h#HFP#_fYfCbO8%)sDQp26b9LiAvSQWnBYn;6TIuyg>@8_@51Skz#X3SudX zG0jX+Vd<2C@#+sj5`F%rG_%g04oL_o9i<1R7BDOF)|3$nrK-<^r67sco9teI?6)i# zTKk5qw_;;8_H_CO0^Iv>-?Dz4yWJRADV12Lkw|01Q-sR7?EDyMBxn+|zltSNRE8pA z9)Z9To>+nqJX|9a^H35DxR!x=4bkaMGHLz?xC zLQU(bI0k3gM5IEIREEM*R4NkrBj_8Wxs=%gDv`xRV7^Ff*Racifn)%&I9sOxz%B>5 zU?FA-XN+dG(WsMi*^oG_XP;ULwiAgncqq?2RO? zUG~4M+0DZV=vnee+5+ZZW*7DBs5okA&!}gpqwQOX!?AA)3@3V0u;A$wX^#_N^{9ws z+>k_p?$KMWujTablme+i5D_XB@<zx>QC*y(Y8ldZ)7x3~jH^{&PK$3^zs2w?L4~X!aTem2C0= z!eNX;88+;uldGfK2Nj(gi@<66fg&_WEjzcXK%VR#>xZ|FXs`RJu_i1JS3R|!5a)Rwa-YQMwv>U*)sv%qlzZlZ(7 zApXNw{?6`Eb#0?^@~esS_gCH%UfnHq!Xz&0Z;CZe-0&Q~>iUxhJ`oO`_t1MyMwDdN zklHNovFqz>-3QhMl}d|N`APY88(-dq=cnJg`L|HirI`||sX{NW^Y zq4Va|aY99x92t7Km{H0F=}_rAj=717(KT(>oO zA-Ypvh<~nVTK!0lU0ai2?J8?pSl#72{>am)|I8^V+&v+I`SDoDsm^V&X^~Th+|z&h zymQGuoqNitj-heIKXHSP{IX>Iql4{nhlt!uvPzExG{M)qJ1uP*l$oPzymO{<jE) literal 0 HcmV?d00001 diff --git a/smiley_pack/icons/opensource/linux.png b/smiley_pack/icons/opensource/linux.png new file mode 100644 index 0000000000000000000000000000000000000000..0340301df931cfba0f78c5c8119d0dfe051a7e79 GIT binary patch literal 5149 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 Ia@IHe2RrI31ONa4 literal 0 HcmV?d00001 diff --git a/smiley_pack/icons/opensource/mint.png b/smiley_pack/icons/opensource/mint.png new file mode 100644 index 0000000000000000000000000000000000000000..83617fcd313b54a3ec540664f04895ea11de933b GIT binary patch literal 8663 zcmV;|At>I7P) zaB^>EX>4U6ba`-PAZ2)IW&i+q+O3;ulH{tAh5xgPUV@lmIgDn#gI<1r2Pq<_n)+E+ z-J4k%k`UnTX8_Wy|M~B2{)<03mt;cZYfb6mPpF}~#y`q+|GB^0E1a+Q53g(X>*wZu z!SRvjyT5-->$$)2dHi@Fhv)PD^>dTQ(@uFBdM>;g^m?=7AM@$t(~x)f=l1#8RCoWQ zrBB0o{x9{sQxDyjzWp3BlQARhd1u`6)?eqVyKnOP-}%P(%va|FH(tK*@94w%8h_58 zc~9LhCh+~QZ}WGJ=X3ut9d|>oVWn^L^n7mPujlW~(&rvo_kOec+@t91ygvW=G=F=~ zviG`2*8+J|LwW}F8p`<>H+H7epT`n^Gyg~aozLIO-*UBU5VgrrySX|)RO^`WZG)Y* z*=^VPKJ1{2!7Z2h?%Z(xd{%sR)eQn*nSB1*?XvOJPa@*{Aab6M-McULytnFoysYr% zX}Qx`8nY*|pZ=QfAN;3(zcjSB(%jmsyyuF3Ipr7KP~`NLy9kKg&z#0Hzt-H}uJ3;o zSWg7wndZU(+tu$TdbA(8#i4@=hFaF#JeM%v7QKA$@*xMy|Q!JTIR73 zpGMD>_MHgWXri0+(gp7m!6{Df=9z5Iy)L@@W8j5AM4u>|LVy~<3L%C>y%kcZ844%F z7*ou##2Q=jDWsTE%1JoYvdtVxCQv-I=p_)qwa0#zn?j+IeR%I$jMmW8y=LomuNC61RuB2zQ(JlWYV!(tk5r(PRDN-@n$qp&AMgKb&%Wp3L5JI;x!#E^j!7k24|jDpNA0?pPx0~AJ#=5iB4Tm;;4XuD*QSPBd&=!rB+H{w z*GBH1;L#LIi=P;d0Y zjj*T#l|+xJ&XnhwBjEgWJcHYnS+8sM2yRaZ&V|w)WSQo!;kwbO$5(yvO3I6`G;6Ht zYwS5_rrRA`n{;b21K(=K=TizlDq)lc2f0%s%TEYo!aJkzOzinR)Sj;uaTOu?He)6r zeO@tHbQ7XzjDnVhJ`q}>uUTDg8OF2 zmMnMKoa!}E0iEl6&OqO$CrE*e?yUmf&7X$jnhsq63;LnUubYjd7b^nx?L`BdF`(X4 z0l!cRu}-MfB6-2G?G7##2E%0BZ@5EX;*S046^^3vqH8q-rT=JJLm>FPjEKCMW%V3} zpDlzbWnv;#I8h`dW%6%u$IXP52&SCN-HWa#%Nbc}%r4Uvy}CuLd7(LjS(Dil&F%N_ zh!w-D=;Fjn?j%-3%9hNW>_OmS4yMsKu z%gD9TQeA_oxF>e4P7&m-=7jVvC{Mf4pQ{6|v!~WlhUO2a5tPD|#5$m?=$CD3s6v3u zV4U}?keMVtVLoF(hb;xk8S;>{YMyEFu{*iyy!KTqwn%uhcs>X~8-pEj(r-yXW*?BD zwrdQ|CW;pM26%y4c`h^xG6R{YDx{`AmtYDp^#yjE!IIQeJTZ3Va;dj7w0K6=T8&Aw zG2?-Y+**s-PDVRM${p)l#a z+Gy$vcYG08|LS2VS1|!^tsY*Jn|eUg4hrOb4>t5mD^2d4O0b2{F*Rs7(zw@TDz)AN zLYe8*^3km8Iv2-nk9{7#3$~WE|JGbGbeY^buSKcFfW_v#-{YSX+x^Vo$pI^4s!sWMckkJ zDTEFVUNa?BUD~hQ`2MQ6^Ac#j2tJ zF}@h1(6MDWu}-dbVnc#2x}QL%j~pP7PAc3Wk79Fh^3=O5=!{=2C6@usv9@} z_*9D>`G$zqynuw1m5W(k5yBZ*O`O`8M71_ELDu|2st=s1qc=Orz5$kYjeni_z(&`a z7j>NdI1`3=b4Wdt5CIpamn1lI+yq)b@Q(t8@xw(g%YXp=Oebk(k#1trmPt;lx4xHhRc}iiy@z9eCx%d!s^J$G*r%GK(n-06?5I zi2d;5RqF=XnO2Hcmf)BQeny)S413xH6}TASY{-^5E6_EFj^b!9#Q_LRWL5%ryHDnx z5n}2G&?t68NI7&7Imkod$$^tIFGzSNRUbPc} zW}hW5NbF9rZJxzdAuGtkfigJ^agm;bY$g1#D5_u{ze_$zJK&7#1ET)NC!`A;E852A{R;y@^oY42KfGtKnKEv3K%SB4z9D>a--^-;?tNROR6iNv6p-F=W7qxm5w z_N!zYf~3G>2Ji-13POdfXVwVf#7%(?m%A#^owC+@u}I>Nu?7T;fKigci^v{4n5>sk zMcI8DwC1K2>g?0;g+b|YIfN=vM=@-6xfS|9HbF|5s77U)%IE7 zFp`W3w{XAi1f(;dgnK}IWvJUqzNoAn7chi?|H~1QoHLP$-XbPaP@-?@_*T>i4`I`{2Uc?O-dH_dMiIJ+-_KVca01mRB)J)?koN}iR2$>5L!jL5{ zoi7ctbwIym-e(8Zj)Dv~r!ne?MN3+{oG59(gFV$3ta-6~^*76hlXh7WsiLk#A}A#O z381zjuhk0huXdfmaX{{3I9)Uz@>e+rn&=89) zOQs?yGlAMTCs?z~7sHzRO0C&5mlrChO<1*HX6BvQ&!v9zrdyS-fnp;`tU9#?Wuyqj zcb%bqu0~LAw#E}tiS$V2uJ?XI0H5e0CV)%@$YeZ**-x0NEnzQb$J94QLgi8)$K6sS ziR_>tBC1*$abB++?%;MrJ3&WwmVwPZm;>%2i>5Ga@TyIULdqRyrlsK~FM9!gT2@JY z^bwI6XduxDd33zUNr8E?wFwFknQEd|CRJI;9A8Js$NM6B5Fn=zQHq!N$>0?o>KxmH zFkqf$=Kc&J^SIWseaKlmrFLf!F)s>@w%d~ba=BCDS{fbMR3!zur$i;?qoTmL91IJx zWm0$^p0NyId(b#T8ySsH3aqIXNi&R`k@`vEo%J&ORL-o|sABqJt7^)srq&YeduxM?Z-PMuzsG$iH2Z)$F<)I4$_=zugL{UcNxCo2xgYA6Y<$TB!S&^sHXSpE}x_~ z|K^H{Knvry443hJ#9|i?w{WX(DnC$wr}C-L@)XZgo>(|$lmw<|>%orCG66|}Af}SM z$g&@@q#}BAXL9M)3$_vxe<#fHOk{wPxBv_;9p+cey^ z=Q6kkVBsd|npT$klP4uy9?iM$zFx8mTCaLKAi54;uF<1(`ckAM6r+h3LxU{UCi&l} zA*7Ye!(F}*6q#Sw$WTl2HO)aab|_mKyMDG!Eo0qfNsnTTH{_x(LM#jOJj?s%M>DBC1h?2;RifKfpyXUUKD{61D?iutD+ARhiXkd zJevpmmYaDz39wcq^M+h8f)slym}s9+A~~tKjY^^mUVU7}+}-1ygvOKK!ZNV1_Tl@J z&B}Q#r>O@5JUGDD@7IhjqUfdBJX38g9-ViG$4-#|{cuWj_reEg-YUrlynUfg^Ly_6 zzfq_8%AEsqriv;)`5SG<8T-P|G5|~Uq3W%wE#08%aH>>QHD8MpJ#^hw2XfUfG)XRN zvPF&9f&N8uK*Od}6>+LIy1h;D+rU40GMe^=`>S*x9fG0mnZ(obWrs-(2wc4Qs0bVt z$b+0Km&{DtS`0wz!Bx1e-A~d*EaaO{+W~$*3#GfX zGOoo3?L?n-ucrin5t0^t6I=hd9CpKsSgCOAQAJ=j`%NH0fOvV>^^~#MoB}QS>D1ZjZWgx~p z^>ecgd6ea04)XYi63Z_N6c|ww!TLYg(f;;I`oWtD|L>^tH_WM;Uk|%|W>1sTtGAT$von%qgsy4O%n7c}+9*2oh2p>iP-8JJl1uDw^s858GfUUo4;6qug z#AIXJMUCU}ZV#~G2R{@p()F%E^rCqeVbn!e&U5o?{PqG=!l{6Hxagg%McnEvrF}(n; zF75bD?K=#n8@xq+W6vEf$6o`r6#(Bz(H;krsurFnad29!(*k@eQ3?$G=n6j1EzrHy zmS)g$1fvgHeWSK2W-le}F!)p$c0#04qN5x1WpY=umcrB8ci!+6K5Crz+*@5tI9#O- z-?_DcgS_Fd5upZczEIjJOW4YA4 z0S5wLRGVWQ_-~KeXBvXn9=0FltS!=XO=tc4EPv-hh3JsaS~%P4u|3*5>VYmZ=kPx$nJpcW*cr4Y$I}C~bgOop5`|v3B)g->!e)c1A z3Z))des8UcEzM1rGfLTizxZ6E#+8M;yB8;`g1h(mEGXbUQ9)W^zb}-_mDh{Dk}}w* z^>#}h46Dte4RaB>2Jztz#;Cx%(Rmzf)STM);S;wro};(Kq@2mUr{z6iI))-gMX_#D zsORAz6ehc+P%uH#twjrWJ^F%*7C?aZPD{QZz!&HY+Id?ZtrcFIS+kheS}UQM*I7=7 z`6vs2ugIzm^qp41-wU^`MQEm@Xk7t)vZ`ep7qrBhi*Zd!F5>I9b{x{< zqE`=j)~a0yP_a0#vtwI=NE>1ie;!_(WMP>e6RoZ*QY(=6ET!UGF=(QLVba0_q0QDY^ zpfpm_I+PGUPCig~Qwn;_{aQWNx>(jminmNxf3J$|W9|BJkm;**3H*Q;x>7G%oCrD_ zh=}uN#t7v(NF^5~byl=fcAs4^=kP)-F*M)_=qzNnPq|`V58G)ih8ph|v|2*7+~BNB z(ajG=Bt<6RFD48Ajh|(n?V`JgnGoRCQz%y5>^gntwW546?~p}dEOtp=Ahh}sLyMnp zGk$_qZ#xK3@3b)GP*6^oPYW}E8_!Dbr)6G4Mr>`Su2e7TODBpiIn{gC9l^uv*aSF- zb=4|oI?nE~HX748ZdKk#V)muj-Me{TqKE#{$qA~2!ipAv+0x2i&LEXWjN39g1{Rmo zLBn%YNGwN;ZkmR<-VS4ESKRv>8N~}k1qv_ZPK-;xV?a8a470$}v z^NS5er7zQ$w%2034jM_Mq1$g`HNF@tnNc$5T+1uI&SUsQk6>AJR;Kn*dwGt_gVHDg zJbBg524M?s6dh`{n8*O)(z)BHC#|~Dk5s3*7F4I5rjD-lgvfyu!h1}B@B?&v)>4@R z&=N;g)6)8JoY<;@Ma>PZZR*)KzfsbEItmFv0g9?Ql&t-9z7{vBgEu~&lQ(1zls8&6 z+X78Tj`sZNSd2SoDzy`Jj?A?AY|NjRFoPt7XG+2>3=G9HjJC>)4u;lGM?CMdGcv6} z9H8RfXJdP9^0A3wp~{imI+cPz$wnpk?OZM9+w9)>pY7T1zNa{J+A_akUx&+YIS?*eLBa+NAWz@(LD%VZJbSQ0>4={ zA+*uJ$f$@(L!Q$xRur`LBm=m>k0wh;i(Jwnsx|F}K+T6|K_uy0?7A!fA{B8Q+&OHU$J9nQ8hK7xN$vZEq|ICCx@r9YNn7PAw0(zy%z&lw z7Ac!&pX*-mS@zmz#W?FY7L1|8lw@$us4-Wow$rd{0aXq5=DXt3gbvCjq)_B{6?7bmQBzj6{Dp&b4 z*t=MvppJc2JCEA})sMauzf&PPOD6N-i#bFgJY&KGI=Zaz&_LBYofCK0rOk?|wZHRw z5Urn+C%d16UWX^lO%wt~&rEAu7}C%}@p(d~PNx9o=VP=7_Crda59402$oj>-4>5he z``0(0Tg|`S`}c;;-@5#-4V%Ap`Cl70zr5ScuN#+XqHa(Uwp@{l6xgGd5dvNZO@#Ez zlqDu=`t{Y{eD4;lpU!DDgNlo)0l2RabL!e^4SomY@vYo1gt|`5>ulXonjh!ouLIza zo3h_DdxIq^re&o9B@*C%( z!+xF_HZtjX;xMsL>|nWrS;$1Xmi?dp(vDQ8L3qyHrWtrjn z`(qRc?gGuaZGRuzcJl-XJOfu++h1(}GoPf_+gkJp7}y3buG^Zt2VCv|ktba;Bu5I+ z^cM=i`x$*x4j8-z`qtduTKhPC05a57>IOJC1jdS#z3%bu-p=0sJ=5y%2d9E^ytkJT z7XSbN24YJ`L;x888vr6vphNip000SaNLh0L01FZT01FZU(%pXi00007bV*G`2j&MD z1~xYyXt|dF00c`(L_t(Y$F-GBY*bYg$A9 z#)TUb+4>P&z}m#EiE9#IX=I}-*@3|@F-B{ov{3~4n3mR-DNH*s(&>D@d+%{Eo#_-? z62ES8l6!M+&hPxsdG8!0BK)5#I5svm+0@ijJ*)alrIZhpwblSRYb{!9lu|hW5h0(? zXMiN|^}xWu*wE0>dO{+Rkbk?1#iAsWNf{p>|M}9TOD~HERa1#XLZZY7=pKO3yo7|}$-hk3U3Rr>q;@jUNzJRZ-Dj*gyn9xsZB#aNANn`OJ&N3#srdcb<~ zYy01_=QwxwV=|@tL?RLT`ufhqGhxIyYwmLivhqGOQ~E|B8ES7;f7`S6A1Y!AvGonwpvdP+eVJ z4J}(bl(8i-rUDQvXzjDr9b{koQ58@@1rTZ6L8Ng3A!K0CrM5KuvGXRgTS)9;ch%nHEl@^v|V z>n-N8H)sfioZ+U|WW~=^(jE>gXQRK*7{lWVJZDSgYb(wBCBML8e%1#_r4=BfAQ)R#xvGI|~@=Q*Akw|Ai+5w9!;kBqC_7E1p(?zShVpz=~k3 zX0w*IDWIyLlA<*S)qb?5K+smRS%8_oB3zhv_MMV5*QR~w(p_r7v( zKN#nsop!7>EEaBaGd;#)KB4Nvt_S$l!ZxaI%DNl?XmLASZ8WLeHAD;+qpWDs{tdO5 zzlJEQyhaCCHLy~CK*?rtoY01VU(4mP0RoZmF0LeNXM=K+ka!nQ=hK>J%lD ztu;TCus!@V-QgjuSeDASBochC*7j9>?yg?FdVXYNXic;lJ(2{>zU zOh23?Q%r7{@5J&I`Mvn98f9%oG+65)K-k^F?!H$DI>C(r02eM?ptZI2gWlfWPrAFi+g;cFM+1LTK%JUK;7BAA pIoRCXJOX%s2awHXpA7gf)}JI)8i+{yE`|UA002ovPDHLkV1lq$-hBW7 literal 0 HcmV?d00001 diff --git a/smiley_pack/icons/opensource/opensuse.png b/smiley_pack/icons/opensource/opensuse.png new file mode 100644 index 0000000000000000000000000000000000000000..0be8f1bdb9160105fc71eb47dd09c21ee9308251 GIT binary patch literal 12271 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 JPDHLkV1hSIF`57X literal 0 HcmV?d00001 diff --git a/smiley_pack/icons/opensource/raspi.png b/smiley_pack/icons/opensource/raspi.png new file mode 100644 index 0000000000000000000000000000000000000000..c07eff2e7caed932cf7c078e395f8a204d07ef08 GIT binary patch literal 4534 zcmeHKYfuzd7H)iip!mQL5D|KZ7?jx4^XPFNGQc>)W5Ce~paGRYPd|p%c{$U-fF>x4 zfz>F+Yz1AdauZp6fUB;QSwSO$NYRYUzAM5QE-~~aDw>D0b2<{WPYm7Vi5B~854sNINl2h13JO{Sftu$kz zU^drA!IYDsA;{Tg)?f9m6O8FL{&CaEv*Ux#Fo}DovfXp%?fbk_8!`UidH*Zv7d*Zl zG0$u9>-#Ggv6;;c*9vb$MV9I(oFBD7c=<+i23j0DW$)#h{I5MjL+>8==jq1#ttoe6 znjarULxNO>Pn(tmRAD|r-tlWAP83$P+Mk~~c5B>JkAjxlhw>ktK6=zQKejaI4=UrN zX(QtTM|beQ+P1qsdh<1TSoGrU&*t`Yc8scVyD~l1Z*g9`6@uK>GHSJ6t5)}C19I5$ z-WFwCT~y%d^rW)ruxV|o-RkvsNk88e6$@v~E!4kt^uC_qgyg-zZnDI-c-gR+l4x6JC`mIvMH{np$_TNLpl^UFm-3y_+-k zH-Q@eRKVah0Qb58>=hq z?KdkfZ?9Onpy!nS?ex^!igW&#QtEx)DAG4+d?hJyP5ZVQcnLqxobY1Ltxp=uO7?rj zY#QD27gcum_526bOa6{YI^HZyJb8VCIe(+unzUWbhdaB7tM_+6J;v+tUC-{BGoEaH zylBCOV7D9Q>o<>;&s=%(`|*NDEhXNqTe`8rL{DerXVx%i%aV-DbDfpdo0~o0*fh$r zdaXL6W?t*Ppsw*xo<8Z?X33ANd0?;4{_)KZK+`!H&|E3Hc?!a6=HsN*K=GYs8|XR+ z3XgQ!aAG;d!UoF7Sd_f3>MwXOLn?XiNOS_7O-*Goad~zsDQ|u2w417Dt~7Ko8W3+fX52fSS$dP!9(ioefC(0{T@C zM>1HWXd>mXX4wfUI-9bvAwwxhV!+>)WjDFfAqkW+QDy*jfLVnvO&P1z=?6SG35<-{ z=JEn!zl3BNdQhyFV&g_!=?o17xDW8YgznGX1qLXcPNA_9SzLHpjgrUBuOO`iLn>U4 zG785jjKUDHK_oyhg2WKHL4qTsftJZ=Aw}b}@gY=Ni-W~21jSJSay|oiWJ0-NHX)*r z*)ow7!6;ge7~~iY80AvRAQt0NOg@BSft>+eiJOK-#Zi%fijoQ?Qn7$W3}P9DU=lHn z;4-NU!Q>K5h6`jOOoF+nNJ0@~wVQEJPR5KIDb!{$x&}DG6)L?}$rJGfgBHCBXKCP| z7xI92E3bmcWS*tzSYBec&Tu3nIIWVjP%ZbEUT!XU|AQgx(g+QhdN|HrFg-E85 z$lnr(6oMgmE6LEgzlG)&4;mJ$rR7KH*QdQ))V z*%axD6L9qo5t+EfNP*p>uU-4?%&)WpArT8fL*WQ5C&dURl;Mb+qA>&))1(-qMS|J# z-mC`L9afsn!R?gF2y_Hmf%bH11O+Mv~_l4WNLKROgYQZ;e?7w2|*dLCug zt#%u$4b84?*p)WUFnz{P6C(=BCfo=~8C5aM5T9E8aaf11rXa(oM7+J~O7%HQP5qjg z*>q3qvpd0Si0bmJ&J$e+@(ihgFk4$S+4J4KZeMRI`*7W9XwSVP+Vk|Nnuu}5VbTBX zbo+i;@uSxp_D=_oZw7uqA_0h#S?O&2faU<5RcPszw&oM~}!pi@k7lpo6nH%R6k@XFq6XnnTMGCei zxEGf{a?g8s;`aU8PcAfW%ZeK7_XGcOT3gNY5&Jfl*1Zs=`G5jI+UWV319LM9{s)I9 BizNU6 literal 0 HcmV?d00001 diff --git a/smiley_pack/icons/opensource/thunderbird.png b/smiley_pack/icons/opensource/thunderbird.png new file mode 100644 index 0000000000000000000000000000000000000000..2d849e5d30e1f1440869d78dfdbb18a521059ce1 GIT binary patch literal 4661 zcmeHKeNYo;8c&EK=1@`L@B`a5R<9tNY`!E}38Dl6B^V(pSkP>CH*qD&#$m8-Q=t1VFUP)7x+p5h^T?*>GicIL*J>wjcszn=Gb ze(&%3Jd+P|JXcf1bBRvsY_(yu?)y&r;U`E zgqYPf5+a?Hk;8FbvuG_N&q7{3je+SyhU!8;NU>B*yw`O$M`M}WdV|~6$?fS@w#dDw z@IDn(wFO+Mw4ZaSbCPC?J;T2Bc)T?Eq0LX5Q1Wr`_Ioc(Vaq()c2+QBw;lIC_J#H| zw?5+h#BU3|3hoJYDVzSucYI|`-I)BzPfM<5CTi~0WaCXGg=^}PA7!q&9F}`EFkbtP zVPbY2UhGo)P9b{~Ps3eR`G&kB z2S*;vfx39D_gYGB3#K;h@LgKl)$(iDr8T!~&1L3CYh%~O`F{5xdHItEojt-!M^1J0RC#XCxxm>IzFU6+8%_H(nwO%t*0y?0pU>}9 zuDV$4x%urX;mK!pRW}dsG0oj#Hh!#_6TJOIV!L7S3|%YLTDouL_KwD?1Gc8t1B>q- z`1vncSY`3&!H%Mp-hsh};esLOOZVpl1=mtPM2olXeOU6htSg;)H@96_#GUfB$4c#F z<+=y6x>WBSQONI1+n68Tk!Q);!mCLs{{Ha&4*a^ch_l|*GVg9zsz(1f|Iys2ytlX; zu2-K+i^_kJ-7raiGiHbPg{>aC=Z4YFS^MdF-r3{fFLus6{#Y6Jc6RVLL2G#d0Ul$g z)-QYF%qU%BebGcUb_`pWX8%lTEL{e=&PjppO4P)nIBgMP1Z^ONPKyn+9fuP-%W1># zRFZ)Vq=~Ys1RW>O2q21336{t;h{hH{uArhb?PNk`oDR=S#g&9$Rv16ji2?u%$zYJv zVzxR^r%K?)MZr6376~A?3zMo6BxthM&tlVP`r)mPJ{5o-A}3}OiG_&BVi66Da4?bS0Hlx5??yOuV3CUA zNe7)~$H~Za(#lL32tnZe@wPO(*_{r7i%2tR0j>@(tN67kqhd7L{s>kA6J@cvqk!12 zc`}sol~}KFV@KTS3?u@=`*C0Mewn-58F*RtJMwagv1s;6e)E$Rrp+7^N7DOT=yn^8>13Pgvcw4){HSm5TFvoQr0x* zs{tKlArlykRZ|=yk%lOgVu>7)i)A4*UO6o$?GDh1ET$L{N_#1=WkEqQKv<0JQvl$O z0J)$Mb`oP~yN;&KDgjFgVk7&9HDEar7=x)Xh6JF9M1~>?R6Ik+-W8}!J{^&u$N+zu zpp2{kmp8k3pwQluM^g?k|7y3XcSR+Tt9rkBKh2bTDM65XQJ@&!n}P#NCkZ!CfYm#M zufVJ(66_v*?fTMA{Z1<=rMM(Sstkc;I6=ZPg+dA|jTiyTafQq%F~|*aq*tVVbO&u@ zGB7(i+XQq3T7mX-YX!aQE>z&_TryUWY!!fDFrt8eE10M+VG+A$yv#UM^czh=-3|jb z84%ZN1DhAv3q}2#VV`Dz?;rW=tHmEV1q2OF@<#d&$~7q08!7Nc&V$`GDAyY)@J7yq z-SvNyi~s64MOwkXpbT(WD)!gk1_v!q!~7^UXB@}Q*;lu2d>yb1w?!v8!0GG<_TtWY zcb5|whcPjl$YHm=d_2d%w0G7}aGGw3QP0*X8cuINovK^tb1sVx@$#G<-~;DoFCC)Z z;M_1SGO_jA@bsLGP}d??ez$+@)SQ%~M~_A0zWc6L7SFt18697m3k?|}TKIr>qy5^& z`iD;|cKK%h(pmV+r7EeZ&HGv7SVOs{PF7J+Xy#n?wvFg&ds1GF>Z^B`U8MO)?NMIk z&}429ZyUw+kNwyE_p>Lv#4Uk`v-158auZw?UHNvj!C4Of7ab}iYUdv3Yy~0`N5!G|X8gyt*YO#8u|^;p_OpyAzO|HTzxjp6sEYF3)H!9kZ7o RR|U$?iHVF;ADpAl`7c%W%y|F+ literal 0 HcmV?d00001 diff --git a/smiley_pack/icons/opensource/tutanota.png b/smiley_pack/icons/opensource/tutanota.png new file mode 100644 index 0000000000000000000000000000000000000000..9008c6845c386fdb021f665f7a73cdd1bb24964e GIT binary patch literal 5011 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 literal 0 HcmV?d00001 diff --git a/smiley_pack/icons/opensource/ubuntu.png b/smiley_pack/icons/opensource/ubuntu.png new file mode 100644 index 0000000000000000000000000000000000000000..1e68494c797857105972c72386c36f02d60b5d8a GIT binary patch literal 5067 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 literal 0 HcmV?d00001 diff --git a/smiley_pack/icons/respect/cc.png b/smiley_pack/icons/respect/cc.png new file mode 100644 index 0000000000000000000000000000000000000000..b28ef687f359018c136149b631ae3f0bfb38bbc4 GIT binary patch literal 4461 zcmeHKdr(tn7QYA6`?@m09F_a-+_i4>CnK>{g63ftW-H@P=(A+IJEl2~5_ z1uHv?U~NUwirUW5W$3t5w^r(-i`KR{t5mVpy35l6YAvtUx{JmAZa^N>&UBdB{zqn# zd%yGeedqkn`Of5fRhyO+=pX41K~SJNS(yQzA?(-B2mId38A}3>k2dSFnGC|ovDvLg z+C*^}w~gXZF4_n|uG?nq3&G7Czel~H@{)PaEW3>Nr&_Od|90M|7vEmjJ)E7V${qdi zPlIT#vE%a-4}QO|WSw*A!DRcN4?DUJpFMhQ_)dA|v*w&-r*53y{@n=OLF8xg5{Cnb znqB|wMB)?sUNLc7zCgbwlzkh5N;}(APHk-3Mtu2sz>s%h?8vS6&-6dId2C>DSK^sK ziu=IplOXRvjZ&I+c->~(h;IH=PXG9j?v8sm&rX)J-)i*CTJr@}vYT9-% zwRw5E<4~KVNh03b7Q|a!+eHZUpY7barxDNW4KJ71Z%nu#Us;Dgon?KyW>3^}YgfOa zXnpp?S9p)P&3z;zarnR|Ezx(XKD*vSjQ#NP{qBZ;zbEQ-Yki6e6WSsxJAeGm&9ZCm zvi@~F^-|690ogW zV`!^|!(tM8YY`*oa)F-nBtElEqnU)aI3`#Cd>}5uhG0AtF`JR;9u7uT3_vCV`dJT$ z4xAt)gK}7l>;_6zOj(!}(;-O1q`$4mZt|o<8W74vnSrST?266UGD)q`PI|Bu!;+zmQ)JDEjn#P4nH~smpTwPE{UmpfF|g8TWJ;@{hz(DzlylkrWu(MK`Cc*T2Y8sT<;$R4ifnuQmIFAN6QlXF(>kT4U zgb@HoK;W=csMo`Uh&1wzD8(;@5iW#rQlf|T z7$$*5e2UUbq#}VpD)vB;23exjZYDrEX)}>WAvQ~%N5K*+u><-Y0EGCBX1h_}TmPH1V0mKq) zp8^1n9ONQX*eQas+I3c|NzP?M;;^2RY7IC}B*73$f}sE?%Ex7>M1~1)9PeIhuPV*t^t4njg9F3* z^sS*j7TC;t1?kX+pJ7VFpQ;<1pQ7y0rio5Vv(JyD4&5DG>HEdrr=&gKI?uOX?u={v z+i2|7!7Z*1_qjzn_0V4eH$+Fb;PnOfZc}GJ3h*A>aXET-PG{7GxaQhTcf-(2u<(MUnh zk%&s&ze3y#+cV3)P9ONsjcuck?!G2jvn^}IK#MH&<4u~c?tP&0c62>2?5%&NJNRbn zUMP20Ii8U&b{}2RcOqhk&mZ1B9_}@`n;L#Cd!^S>@A6t`v0_0(&p|T>bI> z2}wa|OM$79eEcQT>^Rla7?G}%ht`w@9jiO&yuP5S2@*U!S@xZZtgEJXEN@H=_+zNF z%eeB<3qBA3u{;dff9z0D#W%Lm%F5_ZUrxEzcOc}PXl*c-R2}o)zEwwegl2aKn%i#9 Yzjdr?x2;a80o8%jsx)QehTM|>0f6af00000 literal 0 HcmV?d00001 diff --git a/smiley_pack/icons/respect/cc0.png b/smiley_pack/icons/respect/cc0.png new file mode 100644 index 0000000000000000000000000000000000000000..51ebdf1fc1be3a5bb42c11051c89467254762aeb GIT binary patch literal 4669 zcmeHLdsGuw8jlKwMPaod#rj|x)S{ToOfuv#B_K_ZM2tp67gnuKG7}id%VaP?SA0+v zbp>&?Dxy^spFm}OQN#yEM2jm?#I@41QmW$C7JLgw)V&Fac-nJ%JZJkKIVYLi?|$F! ze&6r=-FtGgNI*(CYT+gDs8|r6z{C+Y$ZRp`Xgvin zX=Vzd?6i)>vfnhQXMEs*yxN=mrOU!G`_S6mf|F6%v;EhvQf-+xD?t}M=XLq)2lt{v zptLJ-vC4qBf;d6`#a%w%~d^m6QIJ07>cZ06}h&9v{+KEvcqC8jn_ef>XAI^>_$3;S=WWH+RH zln$OEi!B_;{*brgRK%0z?e(<-A9yzOPYm!c`0H>MtJfE_Or}=KWN(TACFCv2kt!VH zhE~p=QOOzP`KkZB3+h=%e8)5<98`bdy>ohUUB&IIaPrl4yGzC1#h&cQfP=og%Vl_} z_p%0d=HZNg9W)etA} zOyH;yx}U81o0m1UmaWYG+J4NYudhb zLnB**+MBPBov12P?(}fJ)YJzBkE`K13+tafFENNFFF7MH7aVWb*jl8PBSZ2$VD=xBB=8KK>b{dE)K{XNAnhZRGG-)WF-Czc)W3j>`?Pfxo zLNSnrN}`QYPRohY9Ec{RoWF#r5S3X*CDV!p7HaB(N%7hRDOw51iHz_Lx8nf7KrsYl zH|UL4+%Dy~adGh7WrjJB+l5JyauQT(NM^E75XQrJ2sheJ&*yU@yrFOlsl(&s<2xb1 zNXkiO7&8vTHk*xS6YxxyBp8)QBrw8<`Ft+$;9Ap+3}NRQt-&sc4h%VE)mmsXLz|3{ z3zN{8QW+_S1LmPO`5DYARTsR`+Q|ao1GW=p808_b!2oxUurkr}0Z3;;zZqeT2YVEb zqpYS>iPZ^ou?hvH5E8d)H(YwnbwJ@cp48YY2Rz=@gGDfLVcSX1;NTLm9cN8G| z9Z!bVy(R0N+*~v6a=Ir1!n<(a@qSag+ZlMNRJh!vO?9QGluJ3T^>NaqrAgfVmC}Ww zA_Aqjq>ezj7=j{PjYuTo3i)9oR3t=%8cfm+N@=t*gi%Ympa3|J1~?j&)DS42;tDXK zmWv5=1eXwCe6EH>5Q$DB<|8QC4Pvr|2C5|V-LrB*kpK$SP+C-r3Atj4M8L)P5)qdW z^T80&kP;z+h_sZ*4Ml44@g|Fb0PUm=L=pv?jY;ka7vXr6S}Eo5dB|IfT2C-K5Fq7D zq>ZWew-fQSfttz?E;dmS9|L4aL|ArJWOu{EY+qnpVintgWrUNPvQe3`()Byk}5i$4Igu$H!!>%*qO~v8xuQ&;J zJ9Il_KwO6n9A4logu4#IPR>9Ef8?vP7k}gu5Y)5Cd-2;tR}Wq9#lU+x_o%CfuJ>Z# zy_|d0^?#$w`|Wj#GJ;=0HgH+m_jTiSaM9|kiH(u70$CPT{`vI5=Yi!=HA(WcDFga8z%^W+7n=V; zaOREVaTOuP1h3IW>zAmo5RW0AMMYx^^>VYr)8C_CKhKXL;j!X+WNWT7>+|o=dFYU=`#HyBOkWbpYV&}-B?0im-n$Z(PSQJ& z%ZrMAs2cT|!Idl&7m!%kJ+TiAQU;O!1|ZX;{Yp@aEY zAiL_&;Gna&st?~kGHkKaXVb$y>+ALeMoiWoYxv~V_)|OMT8@`~9;>TC5<`yM9eVc9 zdHrW@m!B$gZabI4)Hzp_NFF>FMc-O|qF3>^f*(R}rnDu_{w9yNec_ns;XFt%?TX2v z@X2;AEvUScd^wA3V}+LR9+@`g8nS|NeQ~z5@*a7j7 zP_uAt&IIS(hR0KfC7H!jUaTqEPryd9ck!q-7Ri$;&d8nTAGE98b8<#W)Zcicb{)T(x#HS}${XA8wN(`( hn)jxpd^Gq~A2PwVG$Qu(3ZMg)GJ2A{__I07{s-^H&x!y5 literal 0 HcmV?d00001 diff --git a/smiley_pack/icons/respect/ccby.png b/smiley_pack/icons/respect/ccby.png new file mode 100644 index 0000000000000000000000000000000000000000..69d237d25027f8c992fc2a30025b1358667814c5 GIT binary patch literal 4407 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 G^M3&g)*ssd literal 0 HcmV?d00001 diff --git a/smiley_pack/smiley_pack.php b/smiley_pack/smiley_pack.php index 4361b2f5a..343ea262d 100644 --- a/smiley_pack/smiley_pack.php +++ b/smiley_pack/smiley_pack.php @@ -2,30 +2,28 @@ /* * Name: Smiley Pack * Description: Pack of smileys that make master too AOLish. - * Version: 1.05 + * Version: 1.06 * Author: Thomas Willingham (based on Mike Macgirvin's Adult Smile template) * Author: Matthias Ebers * All smileys from sites offering them as Public Domain */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\DI; -function smiley_pack_install() { +function smiley_pack_install() +{ Hook::register('smilie', 'addon/smiley_pack/smiley_pack.php', 'smiley_pack_smilies'); } function smiley_pack_smilies(array &$b) { -#Smileys are split into various directories by the intended range of emotions. This is in case we get too big and need to modularise things. We can then cut and paste the right lines, move the right directory, and just change the name of the addon to happy_smilies or whatever. + #Smileys are split into various directories by the intended range of emotions. This is in case we get too big and need to modularise things. We can then cut and paste the right lines, move the right directory, and just change the name of the addon to happy_smilies or whatever. -#Be careful with invocation strings. If you have a smiley called foo, and another called foobar, typing :foobar will call foo. Avoid this with clever naming, using ~ instead of : -#when all else fails. + #Be careful with invocation strings. If you have a smiley called foo, and another called foobar, typing :foobar will call foo. Avoid this with clever naming, using ~ instead of : + #when all else fails. - - -#Animal smileys. + #Animal smileys. $b['texts'][] = ':bunnyflowers:'; $b['icons'][] = '' . ':bunnyflowers:' . ''; @@ -50,7 +48,7 @@ function smiley_pack_smilies(array &$b) $b['texts'][] = ':cow:'; $b['icons'][] = '' . ':cow:' . ''; - + $b['texts'][] = ':crab:'; $b['icons'][] = '' . ':crab:' . ''; @@ -71,7 +69,7 @@ function smiley_pack_smilies(array &$b) $b['texts'][] = ':horse:'; $b['icons'][] = '' . ':horse:' . ''; - + $b['texts'][] = ':parrot:'; $b['icons'][] = '' . ':parrot:' . ''; @@ -99,16 +97,13 @@ function smiley_pack_smilies(array &$b) $b['texts'][] = ':pig:'; $b['icons'][] = '' . ':pig:' . ''; - - -#Baby Smileys + #Baby Smileys $b['texts'][] = ':baby:'; $b['icons'][] = '' . ':baby:' . ''; $b['texts'][] = ':babycot:'; $b['icons'][] = '' . ':babycot:' . ''; - $b['texts'][] = ':pregnant:'; $b['icons'][] = '' . ':pregnant:' . ''; @@ -116,11 +111,10 @@ function smiley_pack_smilies(array &$b) $b['texts'][] = ':stork:'; $b['icons'][] = '' . ':stork:' . ''; - -#Confused Smileys + #Confused Smileys $b['texts'][] = ':confused:'; $b['icons'][] = '' . ':confused:' . ''; - + $b['texts'][] = ':shrug:'; $b['icons'][] = '' . ':shrug:' . ''; @@ -130,13 +124,12 @@ function smiley_pack_smilies(array &$b) $b['texts'][] = ':dazed:'; $b['icons'][] = '' . ':dazed:' . ''; - -#Cool Smileys + #Cool Smileys $b['texts'][] = ':affro:'; $b['icons'][] = '' . ':affro:' . ''; -#Devil/Angel Smileys + #Devil/Angel Smileys $b['texts'][] = ':angel:'; $b['icons'][] = '' . ':angel:' . ''; @@ -152,20 +145,20 @@ function smiley_pack_smilies(array &$b) $b['texts'][] = ':devillish:'; $b['icons'][] = '' . ':devillish:' . ''; - + $b['texts'][] = ':daseesaw:'; $b['icons'][] = '' . ':daseesaw:' . ''; $b['texts'][] = ':turnevil:'; $b['icons'][] = '' . ':turnevil:' . ''; - + $b['texts'][] = ':saint:'; $b['icons'][] = '' . ':saint:' . ''; $b['texts'][] = ':graveside:'; $b['icons'][] = '' . ':graveside:' . ''; -#Unpleasent smileys. + #Unpleasent smileys. $b['texts'][] = ':toilet:'; $b['icons'][] = '' . ':toilet:' . ''; @@ -176,7 +169,7 @@ function smiley_pack_smilies(array &$b) $b['texts'][] = ':fartblush:'; $b['icons'][] = '' . ':fartblush:' . ''; -#Drinks + #Drinks $b['texts'][] = ':tea:'; $b['icons'][] = '' . ':tea:' . ''; @@ -184,7 +177,7 @@ function smiley_pack_smilies(array &$b) $b['texts'][] = ':drool:'; $b['icons'][] = '' . ':drool:' . ''; -#Sad smileys + #Sad smileys $b['texts'][] = ':crying:'; $b['icons'][] = '' . ':crying:' . ''; @@ -195,12 +188,12 @@ function smiley_pack_smilies(array &$b) $b['texts'][] = ':sigh:'; $b['icons'][] = '' . ':sigh:' . ''; -#Smoking - only one smiley in here, maybe it needs moving elsewhere? + #Smoking - only one smiley in here, maybe it needs moving elsewhere? $b['texts'][] = ':smoking:'; $b['icons'][] = '' . ':smoking:' . ''; -#Sport smileys + #Sport smileys $b['texts'][] = ':basketball:'; $b['icons'][] = '' . ':basketball:' . ''; @@ -231,11 +224,11 @@ function smiley_pack_smilies(array &$b) $b['texts'][] = ':snooker:'; $b['icons'][] = '' . ':snooker:' . ''; - + $b['texts'][] = ':horseriding:'; $b['icons'][] = '' . ':horseriding:' . ''; -#Love smileys + #Love smileys $b['texts'][] = ':iloveyou:'; $b['icons'][] = '' . ':iloveyou:' . ''; @@ -255,7 +248,7 @@ function smiley_pack_smilies(array &$b) $b['texts'][] = ':loveheart:'; $b['icons'][] = '' . ':loveheart:' . ''; -#Tired/Sleep smileys + #Tired/Sleep smileys $b['texts'][] = ':countsheep'; $b['icons'][] = '' . ':countsheep:' . ''; @@ -269,7 +262,7 @@ function smiley_pack_smilies(array &$b) $b['texts'][] = ':yawn:'; $b['icons'][] = '' . ':yawn:' . ''; -#Fight/Flame/Violent smileys + #Fight/Flame/Violent smileys $b['texts'][] = ':2guns:'; $b['icons'][] = '' . ':2guns:' . ''; @@ -313,7 +306,7 @@ function smiley_pack_smilies(array &$b) $b['texts'][] = ':acid:'; $b['icons'][] = '' . ':acid:' . ''; -#Fantasy smileys - monsters and dragons fantasy. The other type of fantasy belongs in adult smileys + #Fantasy smileys - monsters and dragons fantasy. The other type of fantasy belongs in adult smileys $b['texts'][] = ':alienmonster:'; $b['icons'][] = '' . ':alienmonster:' . ''; @@ -336,7 +329,7 @@ function smiley_pack_smilies(array &$b) $b['texts'][] = ':mummy:'; $b['icons'][] = '' . ':mummy:' . ''; -#Food smileys + #Food smileys $b['texts'][] = ':apple:'; $b['icons'][] = '' . ':apple:' . ''; @@ -368,7 +361,7 @@ function smiley_pack_smilies(array &$b) $b['texts'][] = ':birthdaycake:'; $b['icons'][] = '' . ':birthdaycake:' . ''; -#Happy smileys + #Happy smileys $b['texts'][] = ':cloud9:'; $b['icons'][] = '' . ':cloud9:' . ''; @@ -376,7 +369,7 @@ function smiley_pack_smilies(array &$b) $b['texts'][] = ':tearsofjoy:'; $b['icons'][] = '' . ':tearsofjoy:' . ''; -#Repsect smileys + #Repsect smileys $b['texts'][] = ':bow:'; $b['icons'][] = '' . ':bow:' . ''; @@ -390,7 +383,19 @@ function smiley_pack_smilies(array &$b) $b['texts'][] = ':number1:'; $b['icons'][] = '' . ':number1:' . ''; -#Laugh smileys + $b['texts'][] = ':cc_cc:'; + $b['icons'][] = '' . ':cc_cc:' . ''; + + $b['texts'][] = ':cc_by:'; + $b['icons'][] = '' . ':cc_by:' . ''; + + $b['texts'][] = ':cc_sa:'; + $b['icons'][] = '' . ':cc_sa:' . ''; + + $b['texts'][] = ':cc_0:'; + $b['icons'][] = '' . ':cc_0:' . ''; + + #Laugh smileys $b['texts'][] = ':hahaha:'; $b['icons'][] = '' . ':hahaha:' . ''; @@ -401,24 +406,23 @@ function smiley_pack_smilies(array &$b) $b['texts'][] = ':rofl:'; $b['icons'][] = '' . ':rofl:' . ''; -#Music smileys + #Music smileys $b['texts'][] = ':drums:'; $b['icons'][] = '' . ':drums:' . ''; - $b['texts'][] = ':guitar:'; $b['icons'][] = '' . ':guitar:' . ''; $b['texts'][] = ':trumpet:'; $b['icons'][] = '' . ':trumpet:' . ''; -#Smileys that used to be in core + #Smileys that used to be in core $b['texts'][] = ':headbang:'; $b['icons'][] = '' . ':headbang:' . ''; - $b['texts'][] = ':beard:'; + $b['texts'][] = ':beard:'; $b['icons'][] = '' . ':beard:' . ''; $b['texts'][] = ':whitebeard:'; @@ -436,7 +440,7 @@ function smiley_pack_smilies(array &$b) $b['texts'][] = ':headdesk:'; $b['icons'][] = '' . ':headdesk:' . ''; -#These two are still in core, so oldcore isn't strictly right, but we don't want too many directories + #These two are still in core, so oldcore isn't strictly right, but we don't want too many directories $b['texts'][] = ':-d'; $b['icons'][] = '' . ':-d' . ''; @@ -444,8 +448,8 @@ function smiley_pack_smilies(array &$b) $b['texts'][] = ':-o'; $b['icons'][] = '' . ':-o' . ''; -# Regex killers - stick these at the bottom so they appear at the end of the English and -# at the start of $OtherLanguage. + # Regex killers - stick these at the bottom so they appear at the end of the English and + # at the start of $OtherLanguage. $b['texts'][] = ':cool:'; $b['icons'][] = '' . ':cool:' . ''; @@ -455,7 +459,7 @@ function smiley_pack_smilies(array &$b) $b['texts'][] = ':golf:'; $b['icons'][] = '' . ':golf:' . ''; - + $b['texts'][] = ':football:'; $b['icons'][] = '' . ':football:' . ''; @@ -480,63 +484,167 @@ function smiley_pack_smilies(array &$b) $b['texts'][] = ':gangs:'; $b['icons'][] = '' . ':gangs:' . ''; - $b['texts'][] = ':dj:'; $b['icons'][] = '' . ':dj:' . ''; - $b['texts'][] = ':elvis:'; $b['icons'][] = '' . ':elivs:' . ''; $b['texts'][] = ':violin:'; $b['icons'][] = '' . ':violin:' . ''; -# New Gif Emoji (@one@loma.ml) -# Fediverse + # New Gif Emoji (@one@loma.ml) + # Fediverse $b['texts'][] = ':friendica:'; - $b['icons'][] = '' . ':friendica:' . ''; - + $b['icons'][] = '' . ':friendica:' . ''; + + $b['texts'][] = ':fediverse:'; + $b['icons'][] = '' . ':fediverse:' . ''; + $b['texts'][] = ':mastodon:'; $b['icons'][] = '' . ':mastodon:' . ''; - + $b['texts'][] = ':pleroma:'; $b['icons'][] = '' . ':pleroma:' . ''; - + $b['texts'][] = ':misskey:'; $b['icons'][] = '' . ':misskey:' . ''; - + $b['texts'][] = ':diaspora:'; - $b['icons'][] = '' . ':diaspora:' . ''; - + $b['icons'][] = '' . ':diaspora:' . ''; + $b['texts'][] = ':hubzilla:'; - $b['icons'][] = '' . ':hubzilla:' . ''; - + $b['icons'][] = '' . ':hubzilla:' . ''; + $b['texts'][] = ':pixelfed:'; $b['icons'][] = '' . ':pixelfeed:' . ''; - + $b['texts'][] = ':nextcloud:'; $b['icons'][] = '' . ':nextcloud:' . ''; - + $b['texts'][] = ':activitypub:'; $b['icons'][] = '' . ':activitypub:' . ''; - -# ccc + + # ccc $b['texts'][] = ':ccc event:'; $b['icons'][] = '' . ':ccc event:' . ''; - -# Commercial + + # Commercial $b['texts'][] = ':youtube:'; $b['icons'][] = '' . ':youtube:' . ''; - + $b['texts'][] = ':spotify:'; $b['icons'][] = '' . ':spotify:' . ''; - + $b['texts'][] = ':twitter:'; $b['icons'][] = '' . ':twitter:' . ''; - + $b['texts'][] = ':twitch:'; $b['icons'][] = '' . ':twitch:' . ''; + + $b['texts'][] = ':facebook:'; + $b['icons'][] = '' . ':facebook:' . ''; + + $b['texts'][] = ':threads:'; + $b['icons'][] = '' . ':threads:' . ''; + + $b['texts'][] = ':google:'; + $b['icons'][] = '' . ':google:' . ''; + + $b['texts'][] = ':signal:'; + $b['icons'][] = '' . ':signal:' . ''; + + $b['texts'][] = ':tiktok:'; + $b['icons'][] = '' . ':tiktok:' . ''; + + $b['texts'][] = ':whatsapp:'; + $b['icons'][] = '' . ':whatsapp:' . ''; + + $b['texts'][] = ':instagram:'; + $b['icons'][] = '' . ':instagram:' . ''; + + $b['texts'][] = ':telegram:'; + $b['icons'][] = '' . ':telegram:' . ''; + + $b['texts'][] = ':windows:'; + $b['icons'][] = '' . ':windows:' . ''; + + $b['texts'][] = ':github:'; + $b['icons'][] = '' . ':github:' . ''; + + $b['texts'][] = ':threema:'; + $b['icons'][] = '' . ':threema:' . ''; + + # nonCommercial + + $b['texts'][] = ':invidious:'; + $b['icons'][] = '' . ':invidious:' . ''; + + $b['texts'][] = ':bluesky:'; + $b['icons'][] = '' . ':bluesky:' . ''; + + $b['texts'][] = ':vivaldi:'; + $b['icons'][] = '' . ':vivaldi:' . ''; + + # opensource + + $b['texts'][] = ':firefox:'; + $b['icons'][] = '' . ':firefox:' . ''; + + $b['texts'][] = ':linuxopensuse:'; + $b['icons'][] = '' . ':linuxopensuse:' . ''; + + $b['texts'][] = ':linuxdebian:'; + $b['icons'][] = '' . ':linuxdebian:' . ''; + + $b['texts'][] = ':linuxfedora:'; + $b['icons'][] = '' . ':linuxfedora:' . ''; + + $b['texts'][] = ':linuxubuntu:'; + $b['icons'][] = '' . ':linuxubuntu:' . ''; + + $b['texts'][] = ':linuxmint:'; + $b['icons'][] = '' . ':linuxmint:' . ''; + + $b['texts'][] = ':fdroid:'; + $b['icons'][] = '' . ':fdroid:' . ''; + + $b['texts'][] = ':tutanota:'; + $b['icons'][] = '' . ':tutanota:' . ''; + + $b['texts'][] = ':raspi:'; + $b['icons'][] = '' . ':raspi:' . ''; + + $b['texts'][] = ':linux:'; + $b['icons'][] = '' . ':linux:' . ''; + + $b['texts'][] = ':kde:'; + $b['icons'][] = '' . ':kde:' . ''; + + $b['texts'][] = ':firefoxnightly:'; + $b['icons'][] = '' . ':firefoxnightly:' . ''; + + $b['texts'][] = ':archlinux:'; + $b['icons'][] = '' . ':archlinux:' . ''; + + $b['texts'][] = ':thunderbird:'; + $b['icons'][] = '' . ':thunderbird:' . ''; + + $b['texts'][] = ':vivaldi:'; + $b['icons'][] = '' . ':vivaldi:' . ''; + + $b['texts'][] = ':jabber:'; + $b['icons'][] = '' . ':jabber:' . ''; + + $b['texts'][] = ':matrix:'; + $b['icons'][] = '' . ':matrix:' . ''; + + $b['texts'][] = ':xmpp:'; + $b['icons'][] = '' . ':xmpp:' . ''; + + $b['texts'][] = ':foss:'; + $b['icons'][] = '' . ':foss:' . ''; } From 6f3ba10466a78d174d17594b8e2f0fe3a1ceb967 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 14 Sep 2024 14:40:48 +0000 Subject: [PATCH 209/388] Bluesky: Preparation for video posts --- bluesky/bluesky.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index 181e8d2db..f4e2f4569 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -1410,6 +1410,19 @@ function bluesky_add_media(stdClass $embed, array $item, int $fetch_uid, int $le } break; + case 'app.bsky.embed.video#view': + $media = [ + 'uri-id' => $item['uri-id'], + 'type' => Post\Media::HLS, + 'url' => $embed->playlist, + 'preview' => $embed->thumbnail, + 'description' => $embed->alt ?? '', + 'height' => $embed->aspectRatio->height, + 'width' => $embed->aspectRatio->width, + ]; + Post\Media::insert($media); + break; + case 'app.bsky.embed.external#view': $media = [ 'uri-id' => $item['uri-id'], From f8f63532f4297db73f6cfc578ef4a5e8959db61c Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 29 Sep 2024 18:19:38 +0000 Subject: [PATCH 210/388] Bluesky: New option to complete threads --- bluesky/bluesky.php | 203 ++++++++++++++++------- bluesky/bluesky_feed.php | 8 +- bluesky/bluesky_notifications.php | 8 +- bluesky/bluesky_timeline.php | 8 +- bluesky/lang/C/messages.po | 168 +++++++++---------- bluesky/templates/connector_settings.tpl | 1 + 6 files changed, 235 insertions(+), 161 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index f4e2f4569..73b196124 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -1,7 +1,7 @@ * @@ -10,6 +10,8 @@ * - Outgoing mentions * * At some point in time: + * - post videos + * - direct messages * - Sending Quote shares https://atproto.com/lexicons/app-bsky-embed#appbskyembedrecord and https://atproto.com/lexicons/app-bsky-embed#appbskyembedrecordwithmedia * * Possibly not possible: @@ -151,7 +153,7 @@ function bluesky_probe_detect(array &$hookData) } $data = bluesky_xrpc_get($pconfig['uid'], 'app.bsky.actor.getProfile', ['actor' => $did]); - if (empty($data)) { + if (empty($data) || empty($data->did)) { return; } @@ -346,15 +348,16 @@ function bluesky_settings(array &$data) return; } - $enabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'post') ?? false; - $def_enabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'post_by_default') ?? false; - $pds = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'pds'); - $handle = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'handle'); - $did = bluesky_get_user_did(DI::userSession()->getLocalUserId()); - $token = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'access_token'); - $import = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'import') ?? false; - $import_feeds = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'import_feeds') ?? false; - $custom_handle = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'friendica_handle') ?? false; + $enabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'post') ?? false; + $def_enabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'post_by_default') ?? false; + $pds = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'pds'); + $handle = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'handle'); + $did = bluesky_get_user_did(DI::userSession()->getLocalUserId()); + $token = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'access_token'); + $import = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'import') ?? false; + $import_feeds = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'import_feeds') ?? false; + $complete_threads = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'complete_threads') ?? false; + $custom_handle = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'friendica_handle') ?? false; if (DI::config()->get('bluesky', 'friendica_handles')) { $self = User::getById(DI::userSession()->getLocalUserId(), ['nickname']); @@ -369,16 +372,17 @@ function bluesky_settings(array &$data) $t = Renderer::getMarkupTemplate('connector_settings.tpl', 'addon/bluesky/'); $html = Renderer::replaceMacros($t, [ - '$enable' => ['bluesky', DI::l10n()->t('Enable Bluesky Post Addon'), $enabled], - '$bydefault' => ['bluesky_bydefault', DI::l10n()->t('Post to Bluesky by default'), $def_enabled], - '$import' => ['bluesky_import', DI::l10n()->t('Import the remote timeline'), $import], - '$import_feeds' => ['bluesky_import_feeds', DI::l10n()->t('Import the pinned feeds'), $import_feeds, DI::l10n()->t('When activated, Posts will be imported from all the feeds that you pinned in Bluesky.')], - '$custom_handle' => $friendica_handle, - '$pds' => ['bluesky_pds', DI::l10n()->t('Personal Data Server'), $pds, DI::l10n()->t('The personal data server (PDS) is the system that hosts your profile.'), '', 'readonly'], - '$handle' => ['bluesky_handle', DI::l10n()->t('Bluesky handle'), $handle, '', '', $custom_handle ? 'readonly' : ''], - '$did' => ['bluesky_did', DI::l10n()->t('Bluesky DID'), $did, DI::l10n()->t('This is the unique identifier. It will be fetched automatically, when the handle is entered.'), '', 'readonly'], - '$password' => ['bluesky_password', DI::l10n()->t('Bluesky app password'), '', DI::l10n()->t("Please don't add your real password here, but instead create a specific app password in the Bluesky settings.")], - '$status' => bluesky_get_status($handle, $did, $pds, $token), + '$enable' => ['bluesky', DI::l10n()->t('Enable Bluesky Post Addon'), $enabled], + '$bydefault' => ['bluesky_bydefault', DI::l10n()->t('Post to Bluesky by default'), $def_enabled], + '$import' => ['bluesky_import', DI::l10n()->t('Import the remote timeline'), $import], + '$import_feeds' => ['bluesky_import_feeds', DI::l10n()->t('Import the pinned feeds'), $import_feeds, DI::l10n()->t('When activated, Posts will be imported from all the feeds that you pinned in Bluesky.')], + '$complete_threads' => ['bluesky_complete_threads', DI::l10n()->t('Complete the threads'), $complete_threads, DI::l10n()->t('When activated, the system fetches additional replies for the posts in the timeline. This leads to more complete threads.')], + '$custom_handle' => $friendica_handle, + '$pds' => ['bluesky_pds', DI::l10n()->t('Personal Data Server'), $pds, DI::l10n()->t('The personal data server (PDS) is the system that hosts your profile.'), '', 'readonly'], + '$handle' => ['bluesky_handle', DI::l10n()->t('Bluesky handle'), $handle, '', '', $custom_handle ? 'readonly' : ''], + '$did' => ['bluesky_did', DI::l10n()->t('Bluesky DID'), $did, DI::l10n()->t('This is the unique identifier. It will be fetched automatically, when the handle is entered.'), '', 'readonly'], + '$password' => ['bluesky_password', DI::l10n()->t('Bluesky app password'), '', DI::l10n()->t("Please don't add your real password here, but instead create a specific app password in the Bluesky settings.")], + '$status' => bluesky_get_status($handle, $did, $pds, $token), ]); $data = [ @@ -446,6 +450,7 @@ function bluesky_settings_post(array &$b) DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'handle', $handle); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'import', intval($_POST['bluesky_import'])); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'import_feeds', intval($_POST['bluesky_import_feeds'])); + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'complete_threads', intval($_POST['bluesky_complete_threads'])); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'friendica_handle', intval($_POST['bluesky_friendica_handle'] ?? false)); if (!empty($handle)) { @@ -534,15 +539,15 @@ function bluesky_cron() Logger::debug('Refresh the token', ['uid' => $pconfig['uid']]); bluesky_get_token($pconfig['uid']); - Worker::add(['priority' => Worker::PRIORITY_MEDIUM, 'force_priority' => true], 'addon/bluesky/bluesky_notifications.php', $pconfig['uid'], $last); + Worker::add(['priority' => Worker::PRIORITY_MEDIUM, 'force_priority' => true], 'addon/bluesky/bluesky_notifications.php', $pconfig['uid']); if (DI::pConfig()->get($pconfig['uid'], 'bluesky', 'import')) { - Worker::add(['priority' => Worker::PRIORITY_MEDIUM, 'force_priority' => true], 'addon/bluesky/bluesky_timeline.php', $pconfig['uid'], $last); + Worker::add(['priority' => Worker::PRIORITY_MEDIUM, 'force_priority' => true], 'addon/bluesky/bluesky_timeline.php', $pconfig['uid']); } if (DI::pConfig()->get($pconfig['uid'], 'bluesky', 'import_feeds')) { Logger::debug('Fetch feeds for user', ['uid' => $pconfig['uid']]); $feeds = bluesky_get_feeds($pconfig['uid']); foreach ($feeds as $feed) { - Worker::add(['priority' => Worker::PRIORITY_MEDIUM, 'force_priority' => true], 'addon/bluesky/bluesky_feed.php', $pconfig['uid'], $feed, $last); + Worker::add(['priority' => Worker::PRIORITY_MEDIUM, 'force_priority' => true], 'addon/bluesky/bluesky_feed.php', $pconfig['uid'], $feed); } } Logger::debug('Polling done for user', ['uid' => $pconfig['uid']]); @@ -710,7 +715,7 @@ function bluesky_create_activity(array $item, stdClass $parent = null) } $activity = bluesky_xrpc_post($uid, 'com.atproto.repo.createRecord', $post); - if (empty($activity)) { + if (empty($activity->uri)) { return; } Logger::debug('Activity done', ['return' => $activity]); @@ -794,7 +799,7 @@ function bluesky_create_post(array $item, stdClass $root = null, stdClass $paren ]; $parent = bluesky_xrpc_post($uid, 'com.atproto.repo.createRecord', $post); - if (empty($parent)) { + if (empty($parent->uri)) { if ($part == 0) { Worker::defer(); } @@ -972,7 +977,7 @@ function bluesky_upload_blob(int $uid, array $photo): ?stdClass Logger::info('Uploading', ['uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size]); $data = bluesky_post($uid, '/xrpc/com.atproto.repo.uploadBlob', $content, ['Content-type' => $photo['type'], 'Authorization' => ['Bearer ' . bluesky_get_token($uid)]]); - if (empty($data)) { + if (empty($data) || empty($data->blob)) { Logger::info('Uploading failed', ['uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size]); return null; } @@ -993,7 +998,7 @@ function bluesky_delete_post(string $uri, int $uid) Logger::debug('Deleted', ['parts' => $parts]); } -function bluesky_fetch_timeline(int $uid, int $last_poll) +function bluesky_fetch_timeline(int $uid) { $data = bluesky_xrpc_get($uid, 'app.bsky.feed.getTimeline'); if (empty($data)) { @@ -1004,15 +1009,44 @@ function bluesky_fetch_timeline(int $uid, int $last_poll) return; } + $last_post = DBA::selectFirst('post-thread-user', ['received'], ['network' => Protocol::BLUESKY, 'uid' => $uid], ['order' => ['received' => true]]); + $last_poll = !empty($last_post['received']) ? strtotime($last_post['received']) : 0; + foreach (array_reverse($data->feed) as $entry) { + $causer = bluesky_get_contact($entry->post->author, 0, $uid); + if (!empty($entry->reply)) { + if (!empty($entry->reply->root)) { + bluesky_complete_post($entry->reply->root, $uid, Item::PR_COMMENT, $causer['id'], $last_poll); + } + if (!empty($entry->reply->parent)) { + bluesky_complete_post($entry->reply->parent, $uid, Item::PR_COMMENT, $causer['id'], $last_poll); + } + } bluesky_process_post($entry->post, $uid, $uid, Item::PR_NONE, 0, 0, $last_poll); if (!empty($entry->reason)) { bluesky_process_reason($entry->reason, bluesky_get_uri($entry->post), $uid); } } +} - // @todo Support paging - // [cursor] => 1684670516000::bafyreidq3ilwslmlx72jf5vrk367xcc63s6lrhzlyup2bi3zwcvso6w2vi +function bluesky_complete_post(stdClass $post, int $uid, int $post_reason, int $causer, int $last_poll): int +{ + $complete = DI::pConfig()->get($uid, 'bluesky', 'complete_threads'); + $existing_uri = bluesky_fetch_post(bluesky_get_uri($post), $uid); + if (!empty($existing_uri)) { + $comments = Post::countPosts(['thr-parent' => $existing_uri, 'gravity' => Item::GRAVITY_COMMENT]); + if (($post->replyCount <= $comments) || !$complete) { + return bluesky_fetch_uri_id($existing_uri, $uid); + } + } + + if ($complete) { + $uri = bluesky_fetch_missing_post($post->uri, $uid, $uid, $post_reason, $causer, 0, $last_poll, '', true); + $uri_id = bluesky_fetch_uri_id($uri, $uid); + } else { + $uri_id = bluesky_process_post($post, $uid, $uid, $post_reason, $causer, 0, $last_poll); + } + return $uri_id; } function bluesky_process_reason(stdClass $reason, string $uri, int $uid) @@ -1056,12 +1090,16 @@ function bluesky_process_reason(stdClass $reason, string $uri, int $uid) } } -function bluesky_fetch_notifications(int $uid, int $last_poll) +function bluesky_fetch_notifications(int $uid) { $data = bluesky_xrpc_get($uid, 'app.bsky.notification.listNotifications'); if (empty($data->notifications)) { return; } + + $last_post = DBA::selectFirst('post-thread-user', ['received'], ['network' => Protocol::BLUESKY, 'uid' => $uid], ['order' => ['received' => true]]); + $last_poll = !empty($last_post['received']) ? strtotime($last_post['received']) : 0; + foreach ($data->notifications as $notification) { $uri = bluesky_get_uri($notification); if (Post::exists(['uri' => $uri, 'uid' => $uid]) || Post::exists(['extid' => $uri, 'uid' => $uid])) { @@ -1071,7 +1109,7 @@ function bluesky_fetch_notifications(int $uid, int $last_poll) Logger::debug('Process notification', ['uid' => $uid, 'reason' => $notification->reason, 'uri' => $uri, 'indexedAt' => $notification->indexedAt]); switch ($notification->reason) { case 'like': - $item = bluesky_get_header($notification, $uri, $uid, $uid); + $item = bluesky_get_header($notification, $uri, $uid, $uid, $last_poll); $item['gravity'] = Item::GRAVITY_ACTIVITY; $item['body'] = $item['verb'] = Activity::LIKE; $item['thr-parent'] = bluesky_get_uri($notification->record->subject); @@ -1085,7 +1123,7 @@ function bluesky_fetch_notifications(int $uid, int $last_poll) break; case 'repost': - $item = bluesky_get_header($notification, $uri, $uid, $uid); + $item = bluesky_get_header($notification, $uri, $uid, $uid, $last_poll); $item['gravity'] = Item::GRAVITY_ACTIVITY; $item['body'] = $item['verb'] = Activity::ANNOUNCE; $item['thr-parent'] = bluesky_get_uri($notification->record->subject); @@ -1128,7 +1166,7 @@ function bluesky_fetch_notifications(int $uid, int $last_poll) } } -function bluesky_fetch_feed(int $uid, string $feed, int $last_poll) +function bluesky_fetch_feed(int $uid, string $feed) { $data = bluesky_xrpc_get($uid, 'app.bsky.feed.getFeed', ['feed' => $feed]); if (empty($data)) { @@ -1139,8 +1177,11 @@ function bluesky_fetch_feed(int $uid, string $feed, int $last_poll) return; } + $last_post = DBA::selectFirst('post-thread-user', ['received'], ['network' => Protocol::BLUESKY, 'uid' => $uid], ['order' => ['received' => true]]); + $last_poll = !empty($last_post['received']) ? strtotime($last_post['received']) : 0; + $feeddata = bluesky_xrpc_get($uid, 'app.bsky.feed.getFeedGenerator', ['feed' => $feed]); - if (!empty($feeddata)) { + if (!empty($feeddata) && !empty($feeddata->view)) { $feedurl = $feeddata->view->uri; $feedname = $feeddata->view->displayName; } else { @@ -1153,10 +1194,11 @@ function bluesky_fetch_feed(int $uid, string $feed, int $last_poll) $languages = $entry->post->record->langs ?? []; if (!Relay::isWantedLanguage($entry->post->record->text, 0, $contact['id'] ?? 0, $languages)) { - Logger::debug('Unwanted language detected', ['text' => $entry->post->record->text]); + Logger::debug('Unwanted language detected', ['languages' => $languages, 'text' => $entry->post->record->text]); continue; } - $uri_id = bluesky_process_post($entry->post, $uid, $uid, Item::PR_TAG, 0, 0, $last_poll); + $causer = bluesky_get_contact($entry->post->author, 0, $uid); + $uri_id = bluesky_complete_post($entry->post, $uid, Item::PR_TAG, $causer['id'], $last_poll); if (!empty($uri_id)) { $stored = Post\Category::storeFileByURIId($uri_id, $uid, Post\Category::SUBCRIPTION, $feedname, $feedurl); Logger::debug('Stored tag subscription for user', ['uri-id' => $uri_id, 'uid' => $uid, 'name' => $feedname, 'url' => $feedurl, 'stored' => $stored]); @@ -1184,7 +1226,7 @@ function bluesky_process_post(stdClass $post, int $uid, int $fetch_uid, int $pos Logger::debug('Importing post', ['uid' => $uid, 'indexedAt' => $post->indexedAt, 'uri' => $post->uri, 'cid' => $post->cid, 'root' => $post->record->reply->root ?? '']); - $item = bluesky_get_header($post, $uri, $uid, $fetch_uid); + $item = bluesky_get_header($post, $uri, $uid, $fetch_uid, $last_poll); $item = bluesky_get_content($item, $post->record, $uri, $uid, $fetch_uid, $level, $last_poll); if (empty($item)) { return 0; @@ -1208,7 +1250,7 @@ function bluesky_process_post(stdClass $post, int $uid, int $fetch_uid, int $pos return bluesky_fetch_uri_id($uri, $uid); } -function bluesky_get_header(stdClass $post, string $uri, int $uid, int $fetch_uid): array +function bluesky_get_header(stdClass $post, string $uri, int $uid, int $fetch_uid, int $last_poll = 0): array { $parts = bluesky_get_uri_parts($uri); if (empty($post->author) || empty($post->cid) || empty($parts->rkey)) { @@ -1221,6 +1263,7 @@ function bluesky_get_header(stdClass $post, string $uri, int $uid, int $fetch_ui 'wall' => false, 'uri' => $uri, 'guid' => $post->cid, + 'received' => DateTimeFormat::utc($post->indexedAt, DateTimeFormat::MYSQL), 'private' => Item::UNLISTED, 'verb' => Activity::POST, 'contact-id' => $contact['id'], @@ -1231,6 +1274,10 @@ function bluesky_get_header(stdClass $post, string $uri, int $uid, int $fetch_ui 'source' => json_encode($post), ]; + if (($last_poll != 0) && strtotime($item['received']) < $last_poll) { + unset($item['received']); + } + $account = Contact::selectFirstAccountUser(['pid'], ['id' => $contact['id']]); $item['author-id'] = $account['pid']; @@ -1329,10 +1376,6 @@ function bluesky_get_content(array $item, stdClass $record, string $uri, int $ui $item['created'] = DateTimeFormat::utc($record->createdAt, DateTimeFormat::MYSQL); $item['transmitted-languages'] = $record->langs ?? []; - if (($last_poll != 0) && strtotime($item['created']) > $last_poll) { - $item['received'] = $item['created']; - } - return $item; } @@ -1422,7 +1465,7 @@ function bluesky_add_media(stdClass $embed, array $item, int $fetch_uid, int $le ]; Post\Media::insert($media); break; - + case 'app.bsky.embed.external#view': $media = [ 'uri-id' => $item['uri-id'], @@ -1522,10 +1565,10 @@ function bluesky_get_uri_parts(string $uri): ?stdClass return $class; } -function bluesky_fetch_missing_post(string $uri, int $uid, int $fetch_uid, int $post_reason, int $causer, int $level, int $last_poll, string $fallback = ''): string +function bluesky_fetch_missing_post(string $uri, int $uid, int $fetch_uid, int $post_reason, int $causer, int $level, int $last_poll, string $fallback = '', bool $always_fetch = false): string { $fetched_uri = bluesky_fetch_post($uri, $uid); - if (!empty($fetched_uri)) { + if (!$always_fetch && !empty($fetched_uri)) { return $fetched_uri; } @@ -1545,7 +1588,7 @@ function bluesky_fetch_missing_post(string $uri, int $uid, int $fetch_uid, int $ Logger::debug('Fetch missing post', ['level' => $level, 'uid' => $uid, 'uri' => $uri]); $data = bluesky_xrpc_get($fetch_uid, 'app.bsky.feed.getPostThread', ['uri' => $fetch_uri]); - if (empty($data)) { + if (empty($data) || empty($data->thread)) { Logger::info('Thread was not fetched', ['level' => $level, 'uid' => $uid, 'uri' => $uri, 'fallback' => $fallback]); return $fallback; } @@ -1556,9 +1599,31 @@ function bluesky_fetch_missing_post(string $uri, int $uid, int $fetch_uid, int $ $causer = Contact::getPublicContactId($causer, $uid); } + if (!empty($data->thread->parent)) { + $parents = bluesky_fetch_parents($data->thread->parent, $uid); + + foreach ($parents as $parent) { + $uri_id = bluesky_process_post($parent, $uid, $fetch_uid, Item::PR_FETCHED, $causer, $level, $last_poll); + Logger::debug('Parent created', ['uri-id' => $uri_id]); + } + } + return bluesky_process_thread($data->thread, $uid, $fetch_uid, $post_reason, $causer, $level, $last_poll); } +function bluesky_fetch_parents(stdClass $parent, int $uid, array $parents = []): array +{ + if (!empty($parent->parent)) { + $parents = bluesky_fetch_parents($parent->parent, $uid, $parents); + } + + if (empty(bluesky_fetch_post(bluesky_get_uri($parent->post), $uid))) { + $parents[] = $parent->post; + } + + return $parents; +} + function bluesky_fetch_post(string $uri, int $uid): string { if (Post::exists(['uri' => $uri, 'uid' => [$uid, 0]])) { @@ -1694,7 +1759,7 @@ function bluesky_get_contact_fields(stdClass $author, int $uid, int $fetch_uid, } $data = bluesky_get(BLUESKY_DIRECTORY . '/' . $author->did); - if (!empty($data)) { + if (!empty($data)) { $fields['baseurl'] = bluesky_get_pds('', $data); if (!empty($fields['baseurl'])) { GServer::check($fields['baseurl'], Protocol::BLUESKY); @@ -1877,6 +1942,13 @@ function bluesky_get_did(string $handle, int $uid): string return $did; } + // The profile page can contain hints to the DID as well + $did = bluesky_get_did_by_profile('https://' . $handle); + if ($did != '') { + Logger::debug('Got DID by profile page', ['handle' => $handle, 'did' => $did]); + return $did; + } + // And finally we use the default PDS from Bluesky. $data = bluesky_get(BLUESKY_PDS . '/xrpc/com.atproto.identity.resolveHandle?handle=' . urlencode($handle)); if (!empty($data) && !empty($data->did)) { @@ -1996,7 +2068,7 @@ function bluesky_refresh_token(int $uid): string $token = DI::pConfig()->get($uid, 'bluesky', 'refresh_token'); $data = bluesky_post($uid, '/xrpc/com.atproto.server.refreshSession', '', ['Authorization' => ['Bearer ' . $token]]); - if (empty($data)) { + if (empty($data) || empty($data->accessJwt)) { return ''; } @@ -2015,7 +2087,7 @@ function bluesky_create_token(int $uid, string $password): string } $data = bluesky_post($uid, '/xrpc/com.atproto.server.createSession', json_encode(['identifier' => $did, 'password' => $password]), ['Content-type' => 'application/json']); - if (empty($data)) { + if (empty($data) || empty($data->accessJwt)) { DI::pConfig()->set($uid, 'bluesky', 'status', BLUEKSY_STATUS_TOKEN_FAIL); return ''; } @@ -2052,14 +2124,18 @@ function bluesky_post(int $uid, string $url, string $params, array $headers): ?s return null; } + $data = json_decode($curlResult->getBodyString()); if (!$curlResult->isSuccess()) { - Logger::notice('API Error', ['error' => json_decode($curlResult->getBodyString()) ?: $curlResult->getBodyString()]); - DI::pConfig()->set($uid, 'bluesky', 'status', BLUEKSY_STATUS_API_FAIL); - return null; + Logger::notice('API Error', ['url' => $url, 'code' => $curlResult->getReturnCode(), 'error' => $data ?: $curlResult->getBodyString()]); + if (!$data) { + DI::pConfig()->set($uid, 'bluesky', 'status', BLUEKSY_STATUS_API_FAIL); + return null; + } + $data->code = $curlResult->getReturnCode(); } DI::pConfig()->set($uid, 'bluesky', 'status', BLUEKSY_STATUS_SUCCESS); - return json_decode($curlResult->getBodyString()); + return $data; } function bluesky_xrpc_get(int $uid, string $url, array $parameters = []): ?stdClass @@ -2073,7 +2149,14 @@ function bluesky_xrpc_get(int $uid, string $url, array $parameters = []): ?stdCl return null; } - $data = bluesky_get($pds . '/xrpc/' . $url, HttpClientAccept::JSON, [HttpClientOptions::HEADERS => ['Authorization' => ['Bearer ' . bluesky_get_token($uid)]]]); + $headers = ['Authorization' => ['Bearer ' . bluesky_get_token($uid)]]; + + $languages = User::getWantedLanguages($uid); + if (!empty($languages)) { + $headers['Accept-Language'] = implode(',', $languages); + } + + $data = bluesky_get($pds . '/xrpc/' . $url, HttpClientAccept::JSON, [HttpClientOptions::HEADERS => $headers]); DI::pConfig()->set($uid, 'bluesky', 'status', is_null($data) ? BLUEKSY_STATUS_API_FAIL : BLUEKSY_STATUS_SUCCESS); return $data; } @@ -2087,11 +2170,15 @@ function bluesky_get(string $url, string $accept_content = HttpClientAccept::DEF return null; } + $data = json_decode($curlResult->getBodyString()); if (!$curlResult->isSuccess()) { - Logger::notice('API Error', ['url' => $url, 'error' => json_decode($curlResult->getBodyString()) ?: $curlResult->getBodyString()]); - return null; + Logger::notice('API Error', ['url' => $url, 'code' => $curlResult->getReturnCode(), 'error' => $data ?: $curlResult->getBodyString()]); + if (!$data) { + return null; + } + $data->code = $curlResult->getReturnCode(); } Item::incrementInbound(Protocol::BLUESKY); - return json_decode($curlResult->getBodyString()); + return $data; } diff --git a/bluesky/bluesky_feed.php b/bluesky/bluesky_feed.php index c9a54223f..a20ef1b93 100644 --- a/bluesky/bluesky_feed.php +++ b/bluesky/bluesky_feed.php @@ -6,11 +6,11 @@ function bluesky_feed_run($argv, $argc) { require_once 'addon/bluesky/bluesky.php'; - if ($argc != 4) { + if ($argc < 3) { return; } - Logger::debug('Importing feed - start', ['user' => $argv[1], 'feed' => $argv[2], 'last_poll' => $argv[3]]); - bluesky_fetch_feed($argv[1], $argv[2], $argv[3]); - Logger::debug('Importing feed - done', ['user' => $argv[1], 'feed' => $argv[2], 'last_poll' => $argv[3]]); + Logger::debug('Importing feed - start', ['user' => $argv[1], 'feed' => $argv[2]]); + bluesky_fetch_feed($argv[1], $argv[2]); + Logger::debug('Importing feed - done', ['user' => $argv[1], 'feed' => $argv[2]]); } diff --git a/bluesky/bluesky_notifications.php b/bluesky/bluesky_notifications.php index ad35dfe0f..1fbc8f677 100644 --- a/bluesky/bluesky_notifications.php +++ b/bluesky/bluesky_notifications.php @@ -6,11 +6,11 @@ function bluesky_notifications_run($argv, $argc) { require_once 'addon/bluesky/bluesky.php'; - if ($argc != 3) { + if ($argc < 2) { return; } - Logger::notice('importing notifications - start', ['user' => $argv[1], 'last_poll' => $argv[2]]); - bluesky_fetch_notifications($argv[1], $argv[2]); - Logger::notice('importing notifications - done', ['user' => $argv[1], 'last_poll' => $argv[2]]); + Logger::notice('importing notifications - start', ['user' => $argv[1]]); + bluesky_fetch_notifications($argv[1]); + Logger::notice('importing notifications - done', ['user' => $argv[1]]); } diff --git a/bluesky/bluesky_timeline.php b/bluesky/bluesky_timeline.php index 22ef2224e..fda846bab 100644 --- a/bluesky/bluesky_timeline.php +++ b/bluesky/bluesky_timeline.php @@ -6,11 +6,11 @@ function bluesky_timeline_run($argv, $argc) { require_once 'addon/bluesky/bluesky.php'; - if ($argc != 3) { + if ($argc < 2) { return; } - Logger::notice('importing timeline - start', ['user' => $argv[1], 'last_poll' => $argv[2]]); - bluesky_fetch_timeline($argv[1], $argv[2]); - Logger::notice('importing timeline - done', ['user' => $argv[1], 'last_poll' => $argv[2]]); + Logger::notice('importing timeline - start', ['user' => $argv[1]]); + bluesky_fetch_timeline($argv[1]); + Logger::notice('importing timeline - done', ['user' => $argv[1]]); } diff --git a/bluesky/lang/C/messages.po b/bluesky/lang/C/messages.po index 9521ab89c..d573972c7 100644 --- a/bluesky/lang/C/messages.po +++ b/bluesky/lang/C/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-03-22 05:31+0000\n" +"POT-Creation-Date: 2024-09-29 18:16+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,131 +17,117 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: bluesky.php:325 +#: bluesky.php:335 msgid "Save Settings" msgstr "" -#: bluesky.php:326 +#: bluesky.php:336 msgid "Allow your users to use your hostname for their Bluesky handles" msgstr "" -#: bluesky.php:326 +#: bluesky.php:336 #, php-format -msgid "" -"Before enabling this option, you have to setup a wildcard domain " -"configuration and you have to enable wildcard requests in your webserver " -"configuration. On Apache this is done by adding \"ServerAlias *.%s\" to your " -"HTTP configuration. You don't need to change the HTTPS configuration." +msgid "Before enabling this option, you have to setup a wildcard domain configuration and you have to enable wildcard requests in your webserver configuration. On Apache this is done by adding \"ServerAlias *.%s\" to your HTTP configuration. You don't need to change the HTTPS configuration." msgstr "" -#: bluesky.php:354 +#: bluesky.php:365 #, php-format msgid "Allow to use %s as your Bluesky handle." msgstr "" -#: bluesky.php:354 +#: bluesky.php:365 #, php-format -msgid "" -"When enabled, you can use %s as your Bluesky handle. After you enabled this " -"option, please go to https://bsky.app/settings and select to change your " -"handle. Select that you have got your own domain. Then enter %s and select " -"\"No DNS Panel\". Then select \"Verify Text File\"." -msgstr "" - -#: bluesky.php:361 -msgid "Enable Bluesky Post Addon" -msgstr "" - -#: bluesky.php:362 -msgid "Post to Bluesky by default" -msgstr "" - -#: bluesky.php:363 -msgid "Import the remote timeline" -msgstr "" - -#: bluesky.php:364 -msgid "Import the pinned feeds" -msgstr "" - -#: bluesky.php:364 -msgid "" -"When activated, Posts will be imported from all the feeds that you pinned in " -"Bluesky." -msgstr "" - -#: bluesky.php:366 -msgid "Personal Data Server" -msgstr "" - -#: bluesky.php:366 -msgid "The personal data server (PDS) is the system that hosts your profile." -msgstr "" - -#: bluesky.php:367 -msgid "Bluesky handle" -msgstr "" - -#: bluesky.php:368 -msgid "Bluesky DID" -msgstr "" - -#: bluesky.php:368 -msgid "" -"This is the unique identifier. It will be fetched automatically, when the " -"handle is entered." -msgstr "" - -#: bluesky.php:369 -msgid "Bluesky app password" -msgstr "" - -#: bluesky.php:369 -msgid "" -"Please don't add your real password here, but instead create a specific app " -"password in the Bluesky settings." +msgid "When enabled, you can use %s as your Bluesky handle. After you enabled this option, please go to https://bsky.app/settings and select to change your handle. Select that you have got your own domain. Then enter %s and select \"No DNS Panel\". Then select \"Verify Text File\"." msgstr "" #: bluesky.php:375 +msgid "Enable Bluesky Post Addon" +msgstr "" + +#: bluesky.php:376 +msgid "Post to Bluesky by default" +msgstr "" + +#: bluesky.php:377 +msgid "Import the remote timeline" +msgstr "" + +#: bluesky.php:378 +msgid "Import the pinned feeds" +msgstr "" + +#: bluesky.php:378 +msgid "When activated, Posts will be imported from all the feeds that you pinned in Bluesky." +msgstr "" + +#: bluesky.php:379 +msgid "Complete the threads" +msgstr "" + +#: bluesky.php:379 +msgid "When activated, the system fetches additional replies for the posts in the timeline. This leads to more complete threads." +msgstr "" + +#: bluesky.php:381 +msgid "Personal Data Server" +msgstr "" + +#: bluesky.php:381 +msgid "The personal data server (PDS) is the system that hosts your profile." +msgstr "" + +#: bluesky.php:382 +msgid "Bluesky handle" +msgstr "" + +#: bluesky.php:383 +msgid "Bluesky DID" +msgstr "" + +#: bluesky.php:383 +msgid "This is the unique identifier. It will be fetched automatically, when the handle is entered." +msgstr "" + +#: bluesky.php:384 +msgid "Bluesky app password" +msgstr "" + +#: bluesky.php:384 +msgid "Please don't add your real password here, but instead create a specific app password in the Bluesky settings." +msgstr "" + +#: bluesky.php:390 msgid "Bluesky Import/Export" msgstr "" -#: bluesky.php:385 -msgid "" -"You are not authenticated. Please enter your handle and the app password." +#: bluesky.php:400 +msgid "You are not authenticated. Please enter your handle and the app password." msgstr "" -#: bluesky.php:405 -msgid "" -"You are authenticated to Bluesky. For security reasons the password isn't " -"stored." +#: bluesky.php:420 +msgid "You are authenticated to Bluesky. For security reasons the password isn't stored." msgstr "" -#: bluesky.php:407 -msgid "" -"The communication with the personal data server service (PDS) is established." +#: bluesky.php:422 +msgid "The communication with the personal data server service (PDS) is established." msgstr "" -#: bluesky.php:409 +#: bluesky.php:424 msgid "Communication issues with the personal data server service (PDS)." msgstr "" -#: bluesky.php:411 -msgid "" -"The DID for the provided handle could not be detected. Please check if you " -"entered the correct handle." +#: bluesky.php:426 +msgid "The DID for the provided handle could not be detected. Please check if you entered the correct handle." msgstr "" -#: bluesky.php:413 +#: bluesky.php:428 msgid "The personal data server service (PDS) could not be detected." msgstr "" -#: bluesky.php:415 -msgid "" -"The authentication with the provided handle and password failed. Please " -"check if you entered the correct password." +#: bluesky.php:430 +msgid "The authentication with the provided handle and password failed. Please check if you entered the correct password." msgstr "" -#: bluesky.php:484 +#: bluesky.php:492 msgid "Post to Bluesky" msgstr "" diff --git a/bluesky/templates/connector_settings.tpl b/bluesky/templates/connector_settings.tpl index 3ebea827b..a85bcd89a 100644 --- a/bluesky/templates/connector_settings.tpl +++ b/bluesky/templates/connector_settings.tpl @@ -3,6 +3,7 @@ {{include file="field_checkbox.tpl" field=$bydefault}} {{include file="field_checkbox.tpl" field=$import}} {{include file="field_checkbox.tpl" field=$import_feeds}} +{{include file="field_checkbox.tpl" field=$complete_threads}} {{if $custom_handle}} {{include file="field_checkbox.tpl" field=$custom_handle}} {{/if}} From 08c17c9dd47388da281875c2def8d07d4a0085d6 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 19 Oct 2024 07:41:24 +0000 Subject: [PATCH 211/388] Bluesky: Fixes "E_WARNING: Undefined property: stdClass::$post" --- bluesky/bluesky.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index 73b196124..95857b015 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -1617,7 +1617,7 @@ function bluesky_fetch_parents(stdClass $parent, int $uid, array $parents = []): $parents = bluesky_fetch_parents($parent->parent, $uid, $parents); } - if (empty(bluesky_fetch_post(bluesky_get_uri($parent->post), $uid))) { + if (!empty($parent->post) && empty(bluesky_fetch_post(bluesky_get_uri($parent->post), $uid))) { $parents[] = $parent->post; } From 586ebe96993bcf8ee3be35c13b2475cb1d527287 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 23 Oct 2024 12:14:40 +0000 Subject: [PATCH 212/388] Bluesky: "block" now works / label names are now displayed --- bluesky/bluesky.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index 95857b015..894b64d99 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -278,14 +278,12 @@ function bluesky_block(array &$hook_data) return; } - Logger::debug('Check if contact is bluesky', ['data' => $hook_data]); - $contact = DBA::selectFirst('contact', [], ['network' => Protocol::BLUESKY, 'url' => $hook_data['url'], 'uid' => [0, $hook_data['uid']]]); - if (empty($contact)) { + if ($hook_data['contact']['network'] != Protocol::BLUESKY) { return; } $record = [ - 'subject' => $contact['url'], + 'subject' => $hook_data['contact']['url'], 'createdAt' => DateTimeFormat::utcNow(DateTimeFormat::ATOM), '$type' => 'app.bsky.graph.block' ]; @@ -1297,6 +1295,7 @@ function bluesky_get_header(stdClass $post, string $uri, int $uid, int $fetch_ui // When "ver" is set to "1" it was flagged by some automated process. if (empty($label->ver)) { $item['sensitive'] = true; + $item['content-warning'] = $label->val ?? ''; Logger::debug('Sensitive content', ['uri-id' => $item['uri-id'], 'label' => $label]); } } From 8b694fbb4c6ee0a19fd7c3b30edca30d916523a9 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 27 Oct 2024 04:50:45 +0000 Subject: [PATCH 213/388] Bluesky: Fix following of a contact and adding a post --- bluesky/bluesky.php | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index 894b64d99..45a56792f 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -139,7 +139,7 @@ function bluesky_probe_detect(array &$hookData) return; } } elseif (Network::isValidHttpUrl($hookData['uri'])) { - $did = bluesky_get_did_by_profile($hookData['uri']); + $did = bluesky_get_did_by_profile($hookData['uri'], $pconfig['uid']); if (empty($did)) { return; } @@ -181,21 +181,21 @@ function bluesky_item_by_link(array &$hookData) return; } - $did = bluesky_get_did_by_profile($hookData['uri']); + if (!preg_match('#/profile/(.+)/post/(.+)#', $hookData['uri'], $matches)) { + return; + } + + $did = bluesky_get_did($matches[1], $hookData['uid']); if (empty($did)) { return; } - if (!preg_match('#/profile/.+/post/(.+)#', $hookData['uri'], $matches)) { - return; - } + Logger::debug('Found bluesky post', ['url' => $hookData['uri'], 'did' => $did, 'cid' => $matches[2]]); - Logger::debug('Found bluesky post', ['url' => $hookData['uri'], 'did' => $did, 'cid' => $matches[1]]); - - $uri = 'at://' . $did . '/app.bsky.feed.post/' . $matches[1]; + $uri = 'at://' . $did . '/app.bsky.feed.post/' . $matches[2]; $uri = bluesky_fetch_missing_post($uri, $hookData['uid'], $hookData['uid'], Item::PR_FETCHED, 0, 0, 0); - Logger::debug('Got post', ['did' => $did, 'cid' => $matches[1], 'result' => $uri]); + Logger::debug('Got post', ['did' => $did, 'cid' => $matches[2], 'result' => $uri]); if (!empty($uri)) { $item = Post::selectFirst(['id'], ['uri' => $uri, 'uid' => $hookData['uid']]); if (!empty($item['id'])) { @@ -1831,8 +1831,14 @@ function bluesky_get_preferences(int $uid): ?stdClass return $data; } -function bluesky_get_did_by_profile(string $url): string +function bluesky_get_did_by_profile(string $url, int $uid): string { + if (preg_match('#/profile/(.+)#', $url, $matches)) { + $did = bluesky_get_did($matches[1], $uid); + if (!empty($did)) { + return $did; + } + } try { $curlResult = DI::httpClient()->get($url, HttpClientAccept::HTML, [HttpClientOptions::REQUEST => HttpClientRequest::CONTACTINFO]); } catch (\Throwable $th) { @@ -1941,13 +1947,6 @@ function bluesky_get_did(string $handle, int $uid): string return $did; } - // The profile page can contain hints to the DID as well - $did = bluesky_get_did_by_profile('https://' . $handle); - if ($did != '') { - Logger::debug('Got DID by profile page', ['handle' => $handle, 'did' => $did]); - return $did; - } - // And finally we use the default PDS from Bluesky. $data = bluesky_get(BLUESKY_PDS . '/xrpc/com.atproto.identity.resolveHandle?handle=' . urlencode($handle)); if (!empty($data) && !empty($data->did)) { From 4165479079faf4a8bb63d08574e0ff10cd4950ab Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 30 Oct 2024 05:11:50 +0000 Subject: [PATCH 214/388] Bluesky: Fix probe mistake --- bluesky/bluesky.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index 45a56792f..af7d9ac70 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -181,7 +181,7 @@ function bluesky_item_by_link(array &$hookData) return; } - if (!preg_match('#/profile/(.+)/post/(.+)#', $hookData['uri'], $matches)) { + if (!preg_match('#^' . BLUESKY_WEB . '/profile/(.+)/post/(.+)#', $hookData['uri'], $matches)) { return; } @@ -1833,7 +1833,7 @@ function bluesky_get_preferences(int $uid): ?stdClass function bluesky_get_did_by_profile(string $url, int $uid): string { - if (preg_match('#/profile/(.+)#', $url, $matches)) { + if (preg_match('#^' . BLUESKY_WEB . '/profile/(.+)#', $url, $matches)) { $did = bluesky_get_did($matches[1], $uid); if (!empty($did)) { return $did; From e89b5b1466811a28c28cd95bd81417735809018f Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Wed, 13 Nov 2024 10:10:25 +0100 Subject: [PATCH 215/388] deprecate fancybox addon replaces #1562 --- fancybox/fancybox.php | 1 + 1 file changed, 1 insertion(+) diff --git a/fancybox/fancybox.php b/fancybox/fancybox.php index 1a9ff6344..73bbdab92 100644 --- a/fancybox/fancybox.php +++ b/fancybox/fancybox.php @@ -4,6 +4,7 @@ * Description: Open media attachments of posts into a fancybox overlay. * Version: 1.05 * Author: Grischa Brockhaus + * Status: Unsupported */ use Friendica\App; From 6a1cbe9040d13de472f4924f4fe44ee1e2524ffc Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 6 Nov 2024 17:45:30 +0000 Subject: [PATCH 216/388] Bluesky/Tumblr: Add "connector" parcel to each incoming post --- bluesky/bluesky.php | 7 +++++-- tumblr/tumblr.php | 3 ++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index af7d9ac70..4882a263f 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -38,6 +38,7 @@ use Friendica\Core\Worker; use Friendica\Database\DBA; use Friendica\DI; use Friendica\Model\Contact; +use Friendica\Model\Conversation; use Friendica\Model\GServer; use Friendica\Model\Item; use Friendica\Model\ItemURI; @@ -1058,6 +1059,7 @@ function bluesky_process_reason(stdClass $reason, string $uri, int $uid) $item = [ 'network' => Protocol::BLUESKY, + 'protocol' => Conversation::PARCEL_CONNECTOR, 'uid' => $uid, 'wall' => false, 'uri' => $reason->by->did . '/app.bsky.feed.repost/' . $reason->indexedAt, @@ -1257,6 +1259,7 @@ function bluesky_get_header(stdClass $post, string $uri, int $uid, int $fetch_ui $contact = bluesky_get_contact($post->author, $uid, $fetch_uid); $item = [ 'network' => Protocol::BLUESKY, + 'protocol' => Conversation::PARCEL_CONNECTOR, 'uid' => $uid, 'wall' => false, 'uri' => $uri, @@ -1459,8 +1462,8 @@ function bluesky_add_media(stdClass $embed, array $item, int $fetch_uid, int $le 'url' => $embed->playlist, 'preview' => $embed->thumbnail, 'description' => $embed->alt ?? '', - 'height' => $embed->aspectRatio->height, - 'width' => $embed->aspectRatio->width, + 'height' => $embed->aspectRatio->height ?? null, + 'width' => $embed->aspectRatio->width ?? null, ]; Post\Media::insert($media); break; diff --git a/tumblr/tumblr.php b/tumblr/tumblr.php index dd34bd415..390c3c6c2 100644 --- a/tumblr/tumblr.php +++ b/tumblr/tumblr.php @@ -22,6 +22,7 @@ use Friendica\Core\Worker; use Friendica\Database\DBA; use Friendica\DI; use Friendica\Model\Contact; +use Friendica\Model\Conversation; use Friendica\Model\Item; use Friendica\Model\Photo; use Friendica\Model\Post; @@ -31,7 +32,6 @@ use Friendica\Network\HTTPClient\Client\HttpClientAccept; use Friendica\Network\HTTPClient\Client\HttpClientOptions; use Friendica\Protocol\Activity; use Friendica\Util\DateTimeFormat; -use Friendica\Util\Network; use Friendica\Util\Strings; use GuzzleHttp\Client; use GuzzleHttp\Exception\RequestException; @@ -850,6 +850,7 @@ function tumblr_get_header(stdClass $post, string $uri, int $uid): array $contact = tumblr_get_contact($post->blog, $uid); $item = [ 'network' => Protocol::TUMBLR, + 'protocol' => Conversation::PARCEL_CONNECTOR, 'uid' => $uid, 'wall' => false, 'uri' => $uri, From c22e0ae8310e80c83373f608ab4e5b21660c594d Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 16 Nov 2024 05:42:00 +0000 Subject: [PATCH 217/388] Fix handling of the 'private' field / reformatted code --- bluesky/bluesky.php | 32 +++++++++++++++++----------- diaspora/diaspora.php | 47 ++++++++++++++++++++--------------------- dwpost/dwpost.php | 29 ++++++++++++------------- ijpost/ijpost.php | 22 ++++++++----------- libertree/libertree.php | 47 ++++++++++++++++++----------------------- ljpost/ljpost.php | 41 +++++++++++++++++------------------ pnut/pnut.php | 17 ++++++--------- pumpio/pumpio.php | 8 +++---- statusnet/statusnet.php | 10 +++++---- tumblr/tumblr.php | 14 +++++------- twitter/twitter.php | 6 +++--- wppost/wppost.php | 19 +++++------------ 12 files changed, 135 insertions(+), 157 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index 4882a263f..d719eecb7 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -587,13 +587,13 @@ function bluesky_hook_fork(array &$b) if (DI::pConfig()->get($post['uid'], 'bluesky', 'import')) { // Don't post if it isn't a reply to a bluesky post - if (($post['parent'] != $post['id']) && !Post::exists(['id' => $post['parent'], 'network' => Protocol::BLUESKY])) { + if (($post['gravity'] != Item::GRAVITY_PARENT) && !Post::exists(['id' => $post['parent'], 'network' => Protocol::BLUESKY])) { Logger::notice('No bluesky parent found', ['item' => $post['id']]); $b['execute'] = false; return; } - } elseif (!strstr($post['postopts'] ?? '', 'bluesky') || ($post['parent'] != $post['id']) || $post['private']) { - DI::logger()->info('Activities are never exported when we don\'t import the bluesky timeline', ['uid' => $post['uid']]); + } elseif (!strstr($post['postopts'] ?? '', 'bluesky') || ($post['gravity'] != Item::GRAVITY_PARENT) || ($post['private'] == Item::PRIVATE)) { + DI::logger()->info('Post will not be exported', ['uid' => $post['uid'], 'postopts' => $post['postopts'], 'gravity' => $post['gravity'], 'private' => $post['private']]); $b['execute'] = false; return; } @@ -601,15 +601,11 @@ function bluesky_hook_fork(array &$b) function bluesky_post_local(array &$b) { - if ($b['edit']) { - return; - } - if (!DI::userSession()->getLocalUserId() || (DI::userSession()->getLocalUserId() != $b['uid'])) { return; } - if ($b['private'] || $b['parent']) { + if ($b['edit'] || ($b['private'] == Item::PRIVATE) || ($b['gravity'] != Item::GRAVITY_PARENT)) { return; } @@ -667,7 +663,7 @@ function bluesky_send(array &$b) bluesky_create_activity($b, $parent); } return; - } elseif ($b['private'] || !strstr($b['postopts'], 'bluesky')) { + } elseif (($b['private'] == Item::PRIVATE) || !strstr($b['postopts'], 'bluesky')) { return; } @@ -1481,6 +1477,18 @@ function bluesky_add_media(stdClass $embed, array $item, int $fetch_uid, int $le case 'app.bsky.embed.record#view': $original_uri = $uri = bluesky_get_uri($embed->record); + $type = '$type'; + if (!empty($embed->record->record->$type)) { + $embed_type = $embed->record->record->$type; + if ($embed_type == 'app.bsky.graph.starterpack') { + Logger::debug('Starterpacks are not fetched like posts', ['original-uri' => $original_uri]); + if (empty($item['body'])) { + // @todo process starterpack + $item['body'] = '[url=' . $embed->record->record->list . ']' . $embed->record->record->name . '[/url]'; + } + break; + } + } $uri = bluesky_fetch_missing_post($uri, $item['uid'], $fetch_uid, Item::PR_FETCHED, $item['contact-id'], $level, $last_poll); if ($uri) { $shared = Post::selectFirst(['uri-id'], ['uri' => $uri, 'uid' => [$item['uid'], 0]]); @@ -1603,13 +1611,13 @@ function bluesky_fetch_missing_post(string $uri, int $uid, int $fetch_uid, int $ if (!empty($data->thread->parent)) { $parents = bluesky_fetch_parents($data->thread->parent, $uid); - + foreach ($parents as $parent) { $uri_id = bluesky_process_post($parent, $uid, $fetch_uid, Item::PR_FETCHED, $causer, $level, $last_poll); Logger::debug('Parent created', ['uri-id' => $uri_id]); } } - + return bluesky_process_thread($data->thread, $uid, $fetch_uid, $post_reason, $causer, $level, $last_poll); } @@ -1618,7 +1626,7 @@ function bluesky_fetch_parents(stdClass $parent, int $uid, array $parents = []): if (!empty($parent->parent)) { $parents = bluesky_fetch_parents($parent->parent, $uid, $parents); } - + if (!empty($parent->post) && empty(bluesky_fetch_post(bluesky_get_uri($parent->post), $uid))) { $parents[] = $parent->post; } diff --git a/diaspora/diaspora.php b/diaspora/diaspora.php index cb2eb9968..979204baf 100644 --- a/diaspora/diaspora.php +++ b/diaspora/diaspora.php @@ -17,6 +17,7 @@ use Friendica\Core\Renderer; use Friendica\Database\DBA; use Friendica\Core\Worker; use Friendica\DI; +use Friendica\Model\Item; use Friendica\Model\Post; function diaspora_install() @@ -120,15 +121,15 @@ function diaspora_settings(array &$data) function diaspora_settings_post(array &$b) { if (!empty($_POST['diaspora-submit'])) { - DI::pConfig()->set(DI::userSession()->getLocalUserId(),'diaspora', 'post' , intval($_POST['enabled'])); + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'diaspora', 'post', intval($_POST['enabled'])); if (intval($_POST['enabled'])) { if (isset($_POST['handle'])) { - DI::pConfig()->set(DI::userSession()->getLocalUserId(),'diaspora', 'handle' , trim($_POST['handle'])); - DI::pConfig()->set(DI::userSession()->getLocalUserId(),'diaspora', 'password' , trim($_POST['password'])); + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'diaspora', 'handle', trim($_POST['handle'])); + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'diaspora', 'password', trim($_POST['password'])); } if (!empty($_POST['aspect'])) { - DI::pConfig()->set(DI::userSession()->getLocalUserId(),'diaspora', 'aspect' , trim($_POST['aspect'])); - DI::pConfig()->set(DI::userSession()->getLocalUserId(),'diaspora', 'post_by_default', intval($_POST['post_by_default'])); + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'diaspora', 'aspect', trim($_POST['aspect'])); + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'diaspora', 'post_by_default', intval($_POST['post_by_default'])); } } else { DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'diaspora', 'password'); @@ -144,8 +145,10 @@ function diaspora_hook_fork(array &$b) $post = $b['data']; - if ($post['deleted'] || $post['private'] || ($post['created'] !== $post['edited']) || - !strstr($post['postopts'] ?? '', 'diaspora') || ($post['parent'] != $post['id'])) { + if ( + $post['deleted'] || ($post['private'] == Item::PRIVATE) || ($post['created'] !== $post['edited']) || + !strstr($post['postopts'] ?? '', 'diaspora') || ($post['gravity'] != Item::GRAVITY_PARENT) + ) { $b['execute'] = false; return; } @@ -153,23 +156,19 @@ function diaspora_hook_fork(array &$b) function diaspora_post_local(array &$b) { - if ($b['edit']) { - return; - } - if (!DI::userSession()->getLocalUserId() || (DI::userSession()->getLocalUserId() != $b['uid'])) { return; } - if ($b['private'] || $b['parent']) { + if ($b['edit'] || ($b['private'] == Item::PRIVATE) || ($b['gravity'] != Item::GRAVITY_PARENT)) { return; } - $diaspora_post = intval(DI::pConfig()->get(DI::userSession()->getLocalUserId(),'diaspora','post')); + $diaspora_post = intval(DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'diaspora', 'post')); $diaspora_enable = (($diaspora_post && !empty($_REQUEST['diaspora_enable'])) ? intval($_REQUEST['diaspora_enable']) : 0); - if ($b['api_source'] && intval(DI::pConfig()->get(DI::userSession()->getLocalUserId(),'diaspora','post_by_default'))) { + if ($b['api_source'] && intval(DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'diaspora', 'post_by_default'))) { $diaspora_enable = 1; } @@ -190,11 +189,11 @@ function diaspora_send(array &$b) Logger::notice('diaspora_send: invoked'); - if ($b['deleted'] || $b['private'] || ($b['created'] !== $b['edited'])) { + if ($b['deleted'] || ($b['private'] == Item::PRIVATE) || ($b['created'] !== $b['edited'])) { return; } - if (!strstr($b['postopts'],'diaspora')) { + if (!strstr($b['postopts'], 'diaspora')) { return; } @@ -214,9 +213,9 @@ function diaspora_send(array &$b) Logger::info('diaspora_send: prepare posting'); - $handle = DI::pConfig()->get($b['uid'],'diaspora','handle'); - $password = DI::pConfig()->get($b['uid'],'diaspora','password'); - $aspect = DI::pConfig()->get($b['uid'],'diaspora','aspect'); + $handle = DI::pConfig()->get($b['uid'], 'diaspora', 'handle'); + $password = DI::pConfig()->get($b['uid'], 'diaspora', 'password'); + $aspect = DI::pConfig()->get($b['uid'], 'diaspora', 'aspect'); if ($handle && $password) { Logger::info('diaspora_send: all values seem to be okay'); @@ -230,7 +229,7 @@ function diaspora_send(array &$b) // Removal of tags and mentions // #-tags $body = preg_replace('/#\[url\=(\w+.*?)\](\w+.*?)\[\/url\]/i', '#$2', $body); - // @-mentions + // @-mentions $body = preg_replace('/@\[url\=(\w+.*?)\](\w+.*?)\[\/url\]/i', '@$2', $body); // remove multiple newlines @@ -244,7 +243,7 @@ function diaspora_send(array &$b) // Adding the title if (strlen($title)) { - $body = "## ".html_entity_decode($title)."\n\n".$body; + $body = "## " . html_entity_decode($title) . "\n\n" . $body; } require_once "addon/diaspora/diasphp.php"; @@ -252,9 +251,9 @@ function diaspora_send(array &$b) try { Logger::info('diaspora_send: prepare'); $conn = new Diaspora_Connection($handle, $password); - Logger::info('diaspora_send: try to log in '.$handle); + Logger::info('diaspora_send: try to log in ' . $handle); $conn->logIn(); - Logger::info('diaspora_send: try to send '.$body); + Logger::info('diaspora_send: try to send ' . $body); $conn->provider = $hostname; $conn->postStatusMessage($body, $aspect); @@ -263,7 +262,7 @@ function diaspora_send(array &$b) } catch (Exception $e) { Logger::notice("diaspora_send: Error submitting the post: " . $e->getMessage()); - Logger::info('diaspora_send: requeueing '.$b['uid']); + Logger::info('diaspora_send: requeueing ' . $b['uid']); Worker::defer(); } diff --git a/dwpost/dwpost.php b/dwpost/dwpost.php index 4ad5021f7..1ecd9764b 100644 --- a/dwpost/dwpost.php +++ b/dwpost/dwpost.php @@ -14,6 +14,7 @@ use Friendica\Core\Hook; use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\DI; +use Friendica\Model\Item; use Friendica\Model\Post; use Friendica\Model\Tag; use Friendica\Model\User; @@ -88,24 +89,20 @@ function dwpost_settings_post(array &$b) function dwpost_post_local(array &$b) { - // This can probably be changed to allow editing by pointing to a different API endpoint - if ($b['edit']) { - return; - } - if ((!DI::userSession()->getLocalUserId()) || (DI::userSession()->getLocalUserId() != $b['uid'])) { return; } - if ($b['private'] || $b['parent']) { + // This can probably be changed to allow editing by pointing to a different API endpoint + if ($b['edit'] || ($b['private'] == Item::PRIVATE) || ($b['gravity'] != Item::GRAVITY_PARENT)) { return; } - $dw_post = intval(DI::pConfig()->get(DI::userSession()->getLocalUserId(),'dwpost','post')); + $dw_post = intval(DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'dwpost', 'post')); $dw_enable = (($dw_post && !empty($_REQUEST['dwpost_enable'])) ? intval($_REQUEST['dwpost_enable']) : 0); - if ($b['api_source'] && intval(DI::pConfig()->get(DI::userSession()->getLocalUserId(),'dwpost','post_by_default'))) { + if ($b['api_source'] && intval(DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'dwpost', 'post_by_default'))) { $dw_enable = 1; } @@ -122,7 +119,7 @@ function dwpost_post_local(array &$b) function dwpost_send(array &$b) { - if ($b['deleted'] || $b['private'] || ($b['created'] !== $b['edited'])) { + if ($b['deleted'] || ($b['private'] == Item::PRIVATE) || ($b['created'] !== $b['edited'])) { return; } @@ -145,8 +142,8 @@ function dwpost_send(array &$b) $user = User::getById($b['uid']); $tz = $user['timezone'] ?: 'UTC'; - $dw_username = DI::pConfig()->get($b['uid'],'dwpost','dw_username'); - $dw_password = DI::pConfig()->get($b['uid'],'dwpost','dw_password'); + $dw_username = DI::pConfig()->get($b['uid'], 'dwpost', 'dw_username'); + $dw_password = DI::pConfig()->get($b['uid'], 'dwpost', 'dw_password'); $dw_blog = 'http://www.dreamwidth.org/interface/xmlrpc'; if ($dw_username && $dw_password && $dw_blog) { @@ -156,11 +153,11 @@ function dwpost_send(array &$b) $tags = Tag::getCSVByURIId($b['uri-id'], [Tag::HASHTAG]); $date = DateTimeFormat::convert($b['created'], $tz); - $year = intval(substr($date,0,4)); - $mon = intval(substr($date,5,2)); - $day = intval(substr($date,8,2)); - $hour = intval(substr($date,11,2)); - $min = intval(substr($date,14,2)); + $year = intval(substr($date, 0, 4)); + $mon = intval(substr($date, 5, 2)); + $day = intval(substr($date, 8, 2)); + $hour = intval(substr($date, 11, 2)); + $min = intval(substr($date, 14, 2)); $xml = <<< EOT diff --git a/ijpost/ijpost.php b/ijpost/ijpost.php index 885bc289c..f22dfff29 100644 --- a/ijpost/ijpost.php +++ b/ijpost/ijpost.php @@ -14,6 +14,7 @@ use Friendica\Core\Hook; use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\DI; +use Friendica\Model\Item; use Friendica\Model\Tag; use Friendica\Model\User; use Friendica\Util\DateTimeFormat; @@ -85,17 +86,12 @@ function ijpost_settings_post(array &$b) function ijpost_post_local(array &$b) { - // This can probably be changed to allow editing by pointing to a different API endpoint - - if ($b['edit']) { - return; - } - if (!DI::userSession()->getLocalUserId() || (DI::userSession()->getLocalUserId() != $b['uid'])) { return; } - if ($b['private'] || $b['parent']) { + // This can probably be changed to allow editing by pointing to a different API endpoint + if ($b['edit'] || ($b['private'] == Item::PRIVATE) || ($b['gravity'] != Item::GRAVITY_PARENT)) { return; } @@ -120,7 +116,7 @@ function ijpost_post_local(array &$b) function ijpost_send(array &$b) { - if ($b['deleted'] || $b['private'] || ($b['created'] !== $b['edited'])) { + if ($b['deleted'] || ($b['private'] == Item::PRIVATE) || ($b['created'] !== $b['edited'])) { return; } @@ -150,11 +146,11 @@ function ijpost_send(array &$b) $tags = Tag::getCSVByURIId($b['uri-id'], [Tag::HASHTAG]); $date = DateTimeFormat::convert($b['created'], $tz); - $year = intval(substr($date,0,4)); - $mon = intval(substr($date,5,2)); - $day = intval(substr($date,8,2)); - $hour = intval(substr($date,11,2)); - $min = intval(substr($date,14,2)); + $year = intval(substr($date, 0, 4)); + $mon = intval(substr($date, 5, 2)); + $day = intval(substr($date, 8, 2)); + $hour = intval(substr($date, 11, 2)); + $min = intval(substr($date, 14, 2)); $xml = <<< EOT diff --git a/libertree/libertree.php b/libertree/libertree.php index f69c0aabb..1d997123a 100644 --- a/libertree/libertree.php +++ b/libertree/libertree.php @@ -13,6 +13,7 @@ use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\Database\DBA; use Friendica\DI; +use Friendica\Model\Item; use Friendica\Model\Post; function libertree_install() @@ -74,13 +75,11 @@ function libertree_settings(array &$data) function libertree_settings_post(array &$b) { if (!empty($_POST['libertree-submit'])) { - DI::pConfig()->set(DI::userSession()->getLocalUserId(),'libertree','post',intval($_POST['libertree'])); - DI::pConfig()->set(DI::userSession()->getLocalUserId(),'libertree','post_by_default',intval($_POST['libertree_bydefault'])); - DI::pConfig()->set(DI::userSession()->getLocalUserId(),'libertree','libertree_api_token',trim($_POST['libertree_api_token'])); - DI::pConfig()->set(DI::userSession()->getLocalUserId(),'libertree','libertree_url',trim($_POST['libertree_url'])); - + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'libertree', 'post', intval($_POST['libertree'])); + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'libertree', 'post_by_default', intval($_POST['libertree_bydefault'])); + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'libertree', 'libertree_api_token', trim($_POST['libertree_api_token'])); + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'libertree', 'libertree_url', trim($_POST['libertree_url'])); } - } function libertree_hook_fork(array &$b) @@ -91,8 +90,10 @@ function libertree_hook_fork(array &$b) $post = $b['data']; - if ($post['deleted'] || $post['private'] || ($post['created'] !== $post['edited']) || - !strstr($post['postopts'], 'libertree') || ($post['parent'] != $post['id'])) { + if ( + $post['deleted'] || ($post['private'] == Item::PRIVATE) || ($post['created'] !== $post['edited']) || + !strstr($post['postopts'], 'libertree') || ($post['gravity'] != Item::GRAVITY_PARENT) + ) { $b['execute'] = false; return; } @@ -100,26 +101,20 @@ function libertree_hook_fork(array &$b) function libertree_post_local(array &$b) { - - // This can probably be changed to allow editing by pointing to a different API endpoint - - if ($b['edit']) { - return; - } - if (!DI::userSession()->getLocalUserId() || (DI::userSession()->getLocalUserId() != $b['uid'])) { return; } - if ($b['private'] || $b['parent']) { + // This can probably be changed to allow editing by pointing to a different API endpoint + if ($b['edit'] || ($b['private'] == Item::PRIVATE) || ($b['gravity'] != Item::GRAVITY_PARENT)) { return; } - $ltree_post = intval(DI::pConfig()->get(DI::userSession()->getLocalUserId(),'libertree','post')); + $ltree_post = intval(DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'libertree', 'post')); $ltree_enable = (($ltree_post && !empty($_REQUEST['libertree_enable'])) ? intval($_REQUEST['libertree_enable']) : 0); - if ($b['api_source'] && intval(DI::pConfig()->get(DI::userSession()->getLocalUserId(),'libertree','post_by_default'))) { + if ($b['api_source'] && intval(DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'libertree', 'post_by_default'))) { $ltree_enable = 1; } @@ -138,11 +133,11 @@ function libertree_send(array &$b) { Logger::notice('libertree_send: invoked'); - if ($b['deleted'] || $b['private'] || ($b['created'] !== $b['edited'])) { + if ($b['deleted'] || ($b['private'] == Item::PRIVATE) || ($b['created'] !== $b['edited'])) { return; } - if (! strstr($b['postopts'],'libertree')) { + if (! strstr($b['postopts'], 'libertree')) { return; } @@ -159,15 +154,15 @@ function libertree_send(array &$b) $b['body'] = Post\Media::addAttachmentsToBody($b['uri-id'], DI::contentItem()->addSharedPost($b)); - $ltree_api_token = DI::pConfig()->get($b['uid'],'libertree','libertree_api_token'); - $ltree_url = DI::pConfig()->get($b['uid'],'libertree','libertree_url'); + $ltree_api_token = DI::pConfig()->get($b['uid'], 'libertree', 'libertree_api_token'); + $ltree_url = DI::pConfig()->get($b['uid'], 'libertree', 'libertree_url'); $ltree_blog = "$ltree_url/api/v1/posts/create/?token=$ltree_api_token"; $ltree_source = DI::baseUrl()->getHost(); if ($b['app'] != "") - $ltree_source .= " (".$b['app'].")"; + $ltree_source .= " (" . $b['app'] . ")"; - if($ltree_url && $ltree_api_token && $ltree_blog && $ltree_source) { + if ($ltree_url && $ltree_api_token && $ltree_blog && $ltree_source) { $title = $b['title']; $body = $b['body']; // Insert a newline before and after a quote @@ -177,7 +172,7 @@ function libertree_send(array &$b) // Removal of tags and mentions // #-tags $body = preg_replace('/#\[url\=(\w+.*?)\](\w+.*?)\[\/url\]/i', '#$2', $body); - // @-mentions + // @-mentions $body = preg_replace('/@\[url\=(\w+.*?)\](\w+.*?)\[\/url\]/i', '@$2', $body); // remove multiple newlines @@ -198,7 +193,7 @@ function libertree_send(array &$b) $params = [ 'text' => $body, 'source' => $ltree_source - // 'token' => $ltree_api_token + // 'token' => $ltree_api_token ]; $result = DI::httpClient()->post($ltree_blog, $params)->getBodyString(); diff --git a/ljpost/ljpost.php b/ljpost/ljpost.php index fac447677..7acc65898 100644 --- a/ljpost/ljpost.php +++ b/ljpost/ljpost.php @@ -14,6 +14,7 @@ use Friendica\Core\Hook; use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\DI; +use Friendica\Model\Item; use Friendica\Model\Post; use Friendica\Model\Tag; use Friendica\Model\User; @@ -35,7 +36,7 @@ function ljpost_jot_nets(array &$jotnets_fields) return; } - if (DI::pConfig()->get(DI::userSession()->getLocalUserId(),'ljpost','post')) { + if (DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'ljpost', 'post')) { $jotnets_fields[] = [ 'type' => 'checkbox', 'field' => [ @@ -57,7 +58,7 @@ function ljpost_settings(array &$data) $ij_username = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'ljpost', 'ij_username'); $def_enabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'ljpost', 'post_by_default'); - $t= Renderer::getMarkupTemplate('connector_settings.tpl', 'addon/ljpost/'); + $t = Renderer::getMarkupTemplate('connector_settings.tpl', 'addon/ljpost/'); $html = Renderer::replaceMacros($t, [ '$enabled' => ['ljpost', DI::l10n()->t('Enable LiveJournal Post Addon'), $enabled], '$username' => ['ij_username', DI::l10n()->t('LiveJournal username'), $ij_username], @@ -86,20 +87,16 @@ function ljpost_settings_post(array &$b) function ljpost_post_local(array &$b) { - // This can probably be changed to allow editing by pointing to a different API endpoint - if ($b['edit']) { - return; - } - if (!DI::userSession()->getLocalUserId() || (DI::userSession()->getLocalUserId() != $b['uid'])) { return; } - if ($b['private'] || $b['parent']) { + // This can probably be changed to allow editing by pointing to a different API endpoint + if ($b['edit'] || ($b['private'] == Item::PRIVATE) || ($b['gravity'] != Item::GRAVITY_PARENT)) { return; } - $lj_post = intval(DI::pConfig()->get(DI::userSession()->getLocalUserId(),'ljpost','post')); + $lj_post = intval(DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'ljpost', 'post')); $lj_enable = (($lj_post && !empty($_REQUEST['ljpost_enable'])) ? intval($_REQUEST['ljpost_enable']) : 0); if ($b['api_source'] && intval(DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'ljpost', 'post_by_default'))) { @@ -118,11 +115,11 @@ function ljpost_post_local(array &$b) function ljpost_send(array &$b) { - if ($b['deleted'] || $b['private'] || ($b['created'] !== $b['edited'])) { + if ($b['deleted'] || ($b['private'] == Item::PRIVATE) || ($b['created'] !== $b['edited'])) { return; } - if (!strstr($b['postopts'],'ljpost')) { + if (!strstr($b['postopts'], 'ljpost')) { return; } @@ -139,13 +136,13 @@ function ljpost_send(array &$b) $user = User::getById($b['uid']); $tz = $user['timezone'] ?: 'UTC'; - $lj_username = XML::escape(DI::pConfig()->get($b['uid'],'ljpost','lj_username')); - $lj_password = XML::escape(DI::pConfig()->get($b['uid'],'ljpost','lj_password')); - $lj_journal = XML::escape(DI::pConfig()->get($b['uid'],'ljpost','lj_journal')); -// if(! $lj_journal) -// $lj_journal = $lj_username; + $lj_username = XML::escape(DI::pConfig()->get($b['uid'], 'ljpost', 'lj_username')); + $lj_password = XML::escape(DI::pConfig()->get($b['uid'], 'ljpost', 'lj_password')); + $lj_journal = XML::escape(DI::pConfig()->get($b['uid'], 'ljpost', 'lj_journal')); + // if(! $lj_journal) + // $lj_journal = $lj_username; - $lj_blog = XML::escape(DI::pConfig()->get($b['uid'],'ljpost','lj_blog')); + $lj_blog = XML::escape(DI::pConfig()->get($b['uid'], 'ljpost', 'lj_blog')); if (!strlen($lj_blog)) { $lj_blog = XML::escape('http://www.livejournal.com/interface/xmlrpc'); } @@ -157,11 +154,11 @@ function ljpost_send(array &$b) $tags = Tag::getCSVByURIId($b['uri-id'], [Tag::HASHTAG]); $date = DateTimeFormat::convert($b['created'], $tz); - $year = intval(substr($date,0,4)); - $mon = intval(substr($date,5,2)); - $day = intval(substr($date,8,2)); - $hour = intval(substr($date,11,2)); - $min = intval(substr($date,14,2)); + $year = intval(substr($date, 0, 4)); + $mon = intval(substr($date, 5, 2)); + $day = intval(substr($date, 8, 2)); + $hour = intval(substr($date, 11, 2)); + $min = intval(substr($date, 14, 2)); $xml = <<< EOT diff --git a/pnut/pnut.php b/pnut/pnut.php index e84f208bc..32f60f6d5 100644 --- a/pnut/pnut.php +++ b/pnut/pnut.php @@ -18,6 +18,7 @@ use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\Core\System; use Friendica\DI; +use Friendica\Model\Item; use Friendica\Model\Photo; use phpnut\phpnutException; @@ -82,7 +83,7 @@ function pnut_connect() $o = DI::l10n()->t('Error fetching token. Please try again.', ['code' => $e->getCode(), 'message' => $e->getMessage()]); } - $o .= '
' . DI::l10n()->t("return to the connector page").''; + $o .= '
' . DI::l10n()->t("return to the connector page") . ''; return $o; } @@ -119,14 +120,14 @@ function pnut_settings(array &$data) } $redirectUri = DI::baseUrl() . '/pnut/connect'; - $scope = ['write_post','files']; + $scope = ['write_post', 'files']; $enabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'pnut', 'post') ?? false; $def_enabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'pnut', 'post_by_default') ?? false; $client_id = DI::config()->get('pnut', 'client_id'); $client_secret = DI::config()->get('pnut', 'client_secret'); $token = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'pnut', 'access_token'); - + $user_client = empty($client_id) || empty($client_secret); if ($user_client) { $client_id = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'pnut', 'client_id'); @@ -221,7 +222,7 @@ function pnut_hook_fork(array &$b) return; } - if (!strstr($post['postopts'] ?? '', 'pnut') || ($post['parent'] != $post['id']) || $post['private']) { + if (!strstr($post['postopts'] ?? '', 'pnut') || ($post['gravity'] != Item::GRAVITY_PARENT) || ($post['private'] == Item::PRIVATE)) { $b['execute'] = false; return; } @@ -229,15 +230,11 @@ function pnut_hook_fork(array &$b) function pnut_post_local(array &$b) { - if ($b['edit']) { - return; - } - if (!DI::userSession()->getLocalUserId() || (DI::userSession()->getLocalUserId() != $b['uid'])) { return; } - if ($b['private'] || $b['parent']) { + if ($b['edit'] || ($b['private'] == Item::PRIVATE) || ($b['gravity'] != Item::GRAVITY_PARENT)) { return; } @@ -265,7 +262,7 @@ function pnut_post_hook(array &$b) /** * Post to pnut.io */ - if ($b['deleted'] || $b['private'] || ($b['created'] !== $b['edited'])) { + if ($b['deleted'] || ($b['private'] == Item::PRIVATE) || ($b['created'] !== $b['edited'])) { return; } diff --git a/pumpio/pumpio.php b/pumpio/pumpio.php index 6600696ec..2a8a530e0 100644 --- a/pumpio/pumpio.php +++ b/pumpio/pumpio.php @@ -345,14 +345,14 @@ function pumpio_hook_fork(array &$b) if (DI::pConfig()->get($post['uid'], 'pumpio', 'import')) { // Don't fork if it isn't a reply to a pump.io post - if (($post['parent'] != $post['id']) && !Post::exists(['id' => $post['parent'], 'network' => Protocol::PUMPIO])) { + if (($post['gravity'] != Item::GRAVITY_PARENT) && !Post::exists(['id' => $post['parent'], 'network' => Protocol::PUMPIO])) { Logger::notice('No pump.io parent found for item ' . $post['id']); $b['execute'] = false; return; } } else { // Comments are never exported when we don't import the pumpio timeline - if (!strstr($post['postopts'], 'pumpio') || ($post['parent'] != $post['id']) || $post['private']) { + if (!strstr($post['postopts'], 'pumpio') || ($post['gravity'] != Item::GRAVITY_PARENT)|| ($post['private'] == Item::PRIVATE)) { $b['execute'] = false; return; } @@ -412,7 +412,7 @@ function pumpio_send(array &$b) Logger::notice('pumpio_send: receiver ', $receiver); - if (!count($receiver) && ($b['private'] || !strstr($b['postopts'], 'pumpio'))) { + if (!count($receiver) && ($b['private'] == Item::PRIVATE) || !strstr($b['postopts'], 'pumpio'))) { return; } @@ -1319,7 +1319,7 @@ function pumpio_getreceiver(array $b) { $receiver = []; - if (!$b['private']) { + if ($b['private'] != Item::PRIVATE)) { if (!strstr($b['postopts'], 'pumpio')) { return $receiver; } diff --git a/statusnet/statusnet.php b/statusnet/statusnet.php index f0372852a..4bc32050f 100644 --- a/statusnet/statusnet.php +++ b/statusnet/statusnet.php @@ -296,7 +296,7 @@ function statusnet_hook_fork(array &$b) $post = $b['data']; - if ($post['deleted'] || ($post['created'] !== $post['edited']) || strpos($post['postopts'] ?? '', 'statusnet') === false || ($post['parent'] != $post['id']) || $post['private']) { + if ($post['deleted'] || ($post['created'] !== $post['edited']) || strpos($post['postopts'] ?? '', 'statusnet') === false || ($post['gravity'] != Item::GRAVITY_PARENT) || ($post['private'] == Item::PRIVATE)) { $b['execute'] = false; return; } @@ -336,7 +336,7 @@ function statusnet_post_hook(array &$b) /** * Post to GNU Social */ - if ($b['deleted'] || $b['private'] || ($b['created'] !== $b['edited'])) { + if ($b['deleted'] || ($b['private'] == Item::PRIVATE) || ($b['created'] !== $b['edited'])) { return; } @@ -439,11 +439,13 @@ function statusnet_addon_admin_post() $secret = trim($_POST['secret'][$id]); $key = trim($_POST['key'][$id]); //$applicationname = (!empty($_POST['applicationname']) ? Strings::escapeTags(trim($_POST['applicationname'][$id])):''); - if ($sitename != '' && + if ( + $sitename != '' && $apiurl != '' && $secret != '' && $key != '' && - empty($_POST['delete'][$id])) { + empty($_POST['delete'][$id]) + ) { $sites[] = [ 'sitename' => $sitename, diff --git a/tumblr/tumblr.php b/tumblr/tumblr.php index 390c3c6c2..1e9f5c7fa 100644 --- a/tumblr/tumblr.php +++ b/tumblr/tumblr.php @@ -477,13 +477,13 @@ function tumblr_hook_fork(array &$b) if (DI::pConfig()->get($post['uid'], 'tumblr', 'import')) { // Don't post if it isn't a reply to a tumblr post - if (($post['parent'] != $post['id']) && !Post::exists(['id' => $post['parent'], 'network' => Protocol::TUMBLR])) { + if (($post['gravity'] != Item::GRAVITY_PARENT) && !Post::exists(['id' => $post['parent'], 'network' => Protocol::TUMBLR])) { Logger::notice('No tumblr parent found', ['item' => $post['id']]); $b['execute'] = false; return; } - } elseif (!strstr($post['postopts'] ?? '', 'tumblr') || ($post['parent'] != $post['id']) || $post['private']) { - DI::logger()->info('Activities are never exported when we don\'t import the tumblr timeline', ['uid' => $post['uid']]); + } elseif (!strstr($post['postopts'] ?? '', 'tumblr') || ($post['gravity'] != Item::GRAVITY_PARENT) || ($post['private'] == Item::PRIVATE)) { + DI::logger()->info('Post will not be exported', ['uid' => $post['uid'], 'postopts' => $post['postopts'], 'gravity' => $post['gravity'], 'private' => $post['private']]); $b['execute'] = false; return; } @@ -491,15 +491,11 @@ function tumblr_hook_fork(array &$b) function tumblr_post_local(array &$b) { - if ($b['edit']) { - return; - } - if (!DI::userSession()->getLocalUserId() || (DI::userSession()->getLocalUserId() != $b['uid'])) { return; } - if ($b['private'] || $b['parent']) { + if ($b['edit'] || ($b['private'] == Item::PRIVATE) || ($b['gravity'] != Item::GRAVITY_PARENT)) { return; } @@ -575,7 +571,7 @@ function tumblr_send(array &$b) } } return; - } elseif ($b['private'] || !strstr($b['postopts'], 'tumblr')) { + } elseif (($b['private'] == Item::PRIVATE) || !strstr($b['postopts'], 'tumblr')) { return; } diff --git a/twitter/twitter.php b/twitter/twitter.php index 11c163efc..10f8a2fb3 100644 --- a/twitter/twitter.php +++ b/twitter/twitter.php @@ -170,7 +170,7 @@ function twitter_hook_fork(array &$b) $post = $b['data']; if ( - $post['deleted'] || $post['private'] || ($post['created'] !== $post['edited']) || + $post['deleted'] || ($post['private'] == Item::PRIVATE) || ($post['created'] !== $post['edited']) || !strstr($post['postopts'], 'twitter') || ($post['gravity'] != Item::GRAVITY_PARENT) ) { $b['execute'] = false; @@ -184,7 +184,7 @@ function twitter_post_local(array &$b) return; } - if ($b['edit'] || $b['private'] || $b['parent']) { + if ($b['edit'] || ($b['private'] == Item::PRIVATE) || ($b['gravity'] != Item::GRAVITY_PARENT)) { return; } @@ -211,7 +211,7 @@ function twitter_post_hook(array &$b) { DI::logger()->debug('Invoke post hook', $b); - if (($b['gravity'] != Item::GRAVITY_PARENT) || !strstr($b['postopts'], 'twitter') || $b['private'] || $b['deleted'] || ($b['created'] !== $b['edited'])) { + if (($b['gravity'] != Item::GRAVITY_PARENT) || !strstr($b['postopts'], 'twitter') || ($b['private'] == Item::PRIVATE) || $b['deleted'] || ($b['created'] !== $b['edited'])) { return; } diff --git a/wppost/wppost.php b/wppost/wppost.php index e27079aa3..dba738de4 100644 --- a/wppost/wppost.php +++ b/wppost/wppost.php @@ -108,8 +108,8 @@ function wppost_hook_fork(array &$b) $post = $b['data']; if ( - $post['deleted'] || $post['private'] || ($post['created'] !== $post['edited']) || - !strstr($post['postopts'] ?? '', 'wppost') || ($post['parent'] != $post['id']) + $post['deleted'] || ($post['private'] == Item::PRIVATE) || ($post['created'] !== $post['edited']) || + !strstr($post['postopts'] ?? '', 'wppost') || ($post['gravity'] != Item::GRAVITY_PARENT) ) { $b['execute'] = false; return; @@ -118,18 +118,12 @@ function wppost_hook_fork(array &$b) function wppost_post_local(array &$b) { - - // This can probably be changed to allow editing by pointing to a different API endpoint - - if ($b['edit']) { - return; - } - if (!DI::userSession()->getLocalUserId() || (DI::userSession()->getLocalUserId() != $b['uid'])) { return; } - if ($b['private'] || $b['parent']) { + // This can probably be changed to allow editing by pointing to a different API endpoint + if ($b['edit'] || ($b['private'] == Item::PRIVATE) || ($b['gravity'] != Item::GRAVITY_PARENT)) { return; } @@ -152,12 +146,9 @@ function wppost_post_local(array &$b) $b['postopts'] .= 'wppost'; } - - - function wppost_send(array &$b) { - if ($b['deleted'] || $b['private'] || ($b['created'] !== $b['edited'])) { + if ($b['deleted'] || ($b['private'] == Item::PRIVATE) || ($b['created'] !== $b['edited'])) { return; } From aa5130247b27093fbca5fa1126b857c83446eb14 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Sat, 16 Nov 2024 21:19:06 -0500 Subject: [PATCH 218/388] [pumpio] Remove two superfluous parentheses - Thanks to @SteffenK9 for the report! --- pumpio/pumpio.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pumpio/pumpio.php b/pumpio/pumpio.php index 2a8a530e0..5e053d7c3 100644 --- a/pumpio/pumpio.php +++ b/pumpio/pumpio.php @@ -412,7 +412,7 @@ function pumpio_send(array &$b) Logger::notice('pumpio_send: receiver ', $receiver); - if (!count($receiver) && ($b['private'] == Item::PRIVATE) || !strstr($b['postopts'], 'pumpio'))) { + if (!count($receiver) && ($b['private'] == Item::PRIVATE) || !strstr($b['postopts'], 'pumpio')) { return; } @@ -1319,7 +1319,7 @@ function pumpio_getreceiver(array $b) { $receiver = []; - if ($b['private'] != Item::PRIVATE)) { + if ($b['private'] != Item::PRIVATE) { if (!strstr($b['postopts'], 'pumpio')) { return $receiver; } From a0c727ac35d3dadb3be077527af97612656c674f Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Sun, 17 Nov 2024 13:23:16 +0000 Subject: [PATCH 219/388] [advancedcontentfilter] Remove unused vendor files Thanks to @Art4 for the initial submission in https://github.com/friendica/friendica-addons/pull/1363 --- advancedcontentfilter/vendor/autoload.php | 18 + .../vendor/composer/ClassLoader.php | 202 +- .../vendor/composer/InstalledVersions.php | 359 +++ .../vendor/composer/autoload_classmap.php | 6 +- .../vendor/composer/autoload_files.php | 2 +- .../vendor/composer/autoload_namespaces.php | 2 +- .../vendor/composer/autoload_psr4.php | 4 +- .../vendor/composer/autoload_real.php | 53 +- .../vendor/composer/autoload_static.php | 8 +- .../vendor/composer/installed.json | 2354 +++++++++-------- .../vendor/composer/installed.php | 203 ++ .../vendor/composer/platform_check.php | 26 + .../vendor/psr/simple-cache/.editorconfig | 12 - .../vendor/psr/simple-cache/LICENSE.md | 21 - .../vendor/psr/simple-cache/README.md | 8 - .../vendor/psr/simple-cache/composer.json | 25 - .../psr/simple-cache/src/CacheException.php | 10 - .../psr/simple-cache/src/CacheInterface.php | 114 - .../src/InvalidArgumentException.php | 13 - .../vendor/symfony/cache/.gitignore | 3 - .../Adapter/AbstractRedisAdapterTest.php | 47 - .../cache/Tests/Adapter/AdapterTestCase.php | 175 -- .../cache/Tests/Adapter/ApcuAdapterTest.php | 124 - .../cache/Tests/Adapter/ArrayAdapterTest.php | 56 - .../cache/Tests/Adapter/ChainAdapterTest.php | 233 -- .../Tests/Adapter/DoctrineAdapterTest.php | 32 - .../Tests/Adapter/FilesystemAdapterTest.php | 61 - .../Tests/Adapter/MaxIdLengthAdapterTest.php | 87 - .../Tests/Adapter/MemcachedAdapterTest.php | 204 -- .../Adapter/NamespacedProxyAdapterTest.php | 26 - .../cache/Tests/Adapter/NullAdapterTest.php | 128 - .../cache/Tests/Adapter/PdoAdapterTest.php | 73 - .../Tests/Adapter/PdoDbalAdapterTest.php | 48 - .../Tests/Adapter/PhpArrayAdapterTest.php | 135 - .../PhpArrayAdapterWithFallbackTest.php | 51 - .../Tests/Adapter/PhpFilesAdapterTest.php | 47 - .../cache/Tests/Adapter/PredisAdapterTest.php | 53 - .../Adapter/PredisClusterAdapterTest.php | 26 - .../Adapter/PredisRedisClusterAdapterTest.php | 28 - .../cache/Tests/Adapter/ProxyAdapterTest.php | 69 - .../cache/Tests/Adapter/RedisAdapterTest.php | 92 - .../Tests/Adapter/RedisArrayAdapterTest.php | 24 - .../Tests/Adapter/RedisClusterAdapterTest.php | 27 - .../Tests/Adapter/SimpleCacheAdapterTest.php | 41 - .../Tests/Adapter/TagAwareAdapterTest.php | 338 --- ...TagAwareAndProxyAdapterIntegrationTest.php | 38 - .../Tests/Adapter/TraceableAdapterTest.php | 191 -- .../Adapter/TraceableTagAwareAdapterTest.php | 37 - .../symfony/cache/Tests/CacheItemTest.php | 77 - .../cache/Tests/DoctrineProviderTest.php | 45 - .../cache/Tests/Fixtures/ArrayCache.php | 52 - .../cache/Tests/Fixtures/ExternalAdapter.php | 76 - .../Tests/Simple/AbstractRedisCacheTest.php | 47 - .../cache/Tests/Simple/ApcuCacheTest.php | 35 - .../cache/Tests/Simple/ArrayCacheTest.php | 25 - .../cache/Tests/Simple/CacheTestCase.php | 150 -- .../cache/Tests/Simple/ChainCacheTest.php | 113 - .../cache/Tests/Simple/DoctrineCacheTest.php | 31 - .../Tests/Simple/FilesystemCacheTest.php | 34 - .../cache/Tests/Simple/MemcachedCacheTest.php | 178 -- .../Simple/MemcachedCacheTextModeTest.php | 25 - .../cache/Tests/Simple/NullCacheTest.php | 96 - .../cache/Tests/Simple/PdoCacheTest.php | 47 - .../cache/Tests/Simple/PdoDbalCacheTest.php | 48 - .../cache/Tests/Simple/PhpArrayCacheTest.php | 145 - .../Simple/PhpArrayCacheWithFallbackTest.php | 57 - .../cache/Tests/Simple/PhpFilesCacheTest.php | 42 - .../cache/Tests/Simple/Psr6CacheTest.php | 30 - .../Tests/Simple/RedisArrayCacheTest.php | 24 - .../cache/Tests/Simple/RedisCacheTest.php | 82 - .../Tests/Simple/RedisClusterCacheTest.php | 27 - .../cache/Tests/Simple/TraceableCacheTest.php | 171 -- .../cache/Tests/Traits/PdoPruneableTrait.php | 34 - .../vendor/symfony/cache/phpunit.xml.dist | 50 - .../vendor/symfony/polyfill-apcu/Apcu.php | 106 - .../vendor/symfony/polyfill-apcu/LICENSE | 19 - .../vendor/symfony/polyfill-apcu/README.md | 12 - .../symfony/polyfill-apcu/bootstrap.php | 83 - .../symfony/polyfill-apcu/bootstrap80.php | 75 - .../symfony/polyfill-apcu/composer.json | 35 - 80 files changed, 1986 insertions(+), 6019 deletions(-) create mode 100644 advancedcontentfilter/vendor/composer/InstalledVersions.php create mode 100644 advancedcontentfilter/vendor/composer/installed.php create mode 100644 advancedcontentfilter/vendor/composer/platform_check.php delete mode 100644 advancedcontentfilter/vendor/psr/simple-cache/.editorconfig delete mode 100644 advancedcontentfilter/vendor/psr/simple-cache/LICENSE.md delete mode 100644 advancedcontentfilter/vendor/psr/simple-cache/README.md delete mode 100644 advancedcontentfilter/vendor/psr/simple-cache/composer.json delete mode 100644 advancedcontentfilter/vendor/psr/simple-cache/src/CacheException.php delete mode 100644 advancedcontentfilter/vendor/psr/simple-cache/src/CacheInterface.php delete mode 100644 advancedcontentfilter/vendor/psr/simple-cache/src/InvalidArgumentException.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/.gitignore delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/AbstractRedisAdapterTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/AdapterTestCase.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ApcuAdapterTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ArrayAdapterTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ChainAdapterTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/DoctrineAdapterTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/FilesystemAdapterTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/MaxIdLengthAdapterTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/MemcachedAdapterTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/NamespacedProxyAdapterTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/NullAdapterTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PdoAdapterTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PdoDbalAdapterTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PhpArrayAdapterTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PhpArrayAdapterWithFallbackTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PhpFilesAdapterTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PredisAdapterTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PredisClusterAdapterTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PredisRedisClusterAdapterTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ProxyAdapterTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/RedisAdapterTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/RedisArrayAdapterTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/RedisClusterAdapterTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/SimpleCacheAdapterTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TagAwareAdapterTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TagAwareAndProxyAdapterIntegrationTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TraceableAdapterTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TraceableTagAwareAdapterTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/CacheItemTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/DoctrineProviderTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Fixtures/ArrayCache.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Fixtures/ExternalAdapter.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Simple/AbstractRedisCacheTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Simple/ApcuCacheTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Simple/ArrayCacheTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Simple/CacheTestCase.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Simple/ChainCacheTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Simple/DoctrineCacheTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Simple/FilesystemCacheTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Simple/MemcachedCacheTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Simple/MemcachedCacheTextModeTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Simple/NullCacheTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PdoCacheTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PdoDbalCacheTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PhpArrayCacheTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PhpArrayCacheWithFallbackTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PhpFilesCacheTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Simple/Psr6CacheTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Simple/RedisArrayCacheTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Simple/RedisCacheTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Simple/RedisClusterCacheTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Simple/TraceableCacheTest.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/Tests/Traits/PdoPruneableTrait.php delete mode 100644 advancedcontentfilter/vendor/symfony/cache/phpunit.xml.dist delete mode 100644 advancedcontentfilter/vendor/symfony/polyfill-apcu/Apcu.php delete mode 100644 advancedcontentfilter/vendor/symfony/polyfill-apcu/LICENSE delete mode 100644 advancedcontentfilter/vendor/symfony/polyfill-apcu/README.md delete mode 100644 advancedcontentfilter/vendor/symfony/polyfill-apcu/bootstrap.php delete mode 100644 advancedcontentfilter/vendor/symfony/polyfill-apcu/bootstrap80.php delete mode 100644 advancedcontentfilter/vendor/symfony/polyfill-apcu/composer.json diff --git a/advancedcontentfilter/vendor/autoload.php b/advancedcontentfilter/vendor/autoload.php index 3e6193fa4..2d273a020 100644 --- a/advancedcontentfilter/vendor/autoload.php +++ b/advancedcontentfilter/vendor/autoload.php @@ -2,6 +2,24 @@ // autoload.php @generated by Composer +if (PHP_VERSION_ID < 50600) { + if (!headers_sent()) { + header('HTTP/1.1 500 Internal Server Error'); + } + $err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL; + if (!ini_get('display_errors')) { + if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') { + fwrite(STDERR, $err); + } elseif (!headers_sent()) { + echo $err; + } + } + trigger_error( + $err, + E_USER_ERROR + ); +} + require_once __DIR__ . '/composer/autoload_real.php'; return ComposerAutoloaderInitAdvancedContentFilterAddon::getLoader(); diff --git a/advancedcontentfilter/vendor/composer/ClassLoader.php b/advancedcontentfilter/vendor/composer/ClassLoader.php index 03b9bb9c4..7824d8f7e 100644 --- a/advancedcontentfilter/vendor/composer/ClassLoader.php +++ b/advancedcontentfilter/vendor/composer/ClassLoader.php @@ -37,26 +37,81 @@ namespace Composer\Autoload; * * @author Fabien Potencier * @author Jordi Boggiano - * @see http://www.php-fig.org/psr/psr-0/ - * @see http://www.php-fig.org/psr/psr-4/ + * @see https://www.php-fig.org/psr/psr-0/ + * @see https://www.php-fig.org/psr/psr-4/ */ class ClassLoader { + /** @var \Closure(string):void */ + private static $includeFile; + + /** @var string|null */ + private $vendorDir; + // PSR-4 + /** + * @var array> + */ private $prefixLengthsPsr4 = array(); + /** + * @var array> + */ private $prefixDirsPsr4 = array(); + /** + * @var list + */ private $fallbackDirsPsr4 = array(); // PSR-0 + /** + * List of PSR-0 prefixes + * + * Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2'))) + * + * @var array>> + */ private $prefixesPsr0 = array(); + /** + * @var list + */ private $fallbackDirsPsr0 = array(); + /** @var bool */ private $useIncludePath = false; + + /** + * @var array + */ private $classMap = array(); + + /** @var bool */ private $classMapAuthoritative = false; + + /** + * @var array + */ private $missingClasses = array(); + + /** @var string|null */ private $apcuPrefix; + /** + * @var array + */ + private static $registeredLoaders = array(); + + /** + * @param string|null $vendorDir + */ + public function __construct($vendorDir = null) + { + $this->vendorDir = $vendorDir; + self::initializeIncludeClosure(); + } + + /** + * @return array> + */ public function getPrefixes() { if (!empty($this->prefixesPsr0)) { @@ -66,28 +121,42 @@ class ClassLoader return array(); } + /** + * @return array> + */ public function getPrefixesPsr4() { return $this->prefixDirsPsr4; } + /** + * @return list + */ public function getFallbackDirs() { return $this->fallbackDirsPsr0; } + /** + * @return list + */ public function getFallbackDirsPsr4() { return $this->fallbackDirsPsr4; } + /** + * @return array Array of classname => path + */ public function getClassMap() { return $this->classMap; } /** - * @param array $classMap Class to filename map + * @param array $classMap Class to filename map + * + * @return void */ public function addClassMap(array $classMap) { @@ -102,22 +171,25 @@ class ClassLoader * Registers a set of PSR-0 directories for a given prefix, either * appending or prepending to the ones previously set for this prefix. * - * @param string $prefix The prefix - * @param array|string $paths The PSR-0 root directories - * @param bool $prepend Whether to prepend the directories + * @param string $prefix The prefix + * @param list|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories + * + * @return void */ public function add($prefix, $paths, $prepend = false) { + $paths = (array) $paths; if (!$prefix) { if ($prepend) { $this->fallbackDirsPsr0 = array_merge( - (array) $paths, + $paths, $this->fallbackDirsPsr0 ); } else { $this->fallbackDirsPsr0 = array_merge( $this->fallbackDirsPsr0, - (array) $paths + $paths ); } @@ -126,19 +198,19 @@ class ClassLoader $first = $prefix[0]; if (!isset($this->prefixesPsr0[$first][$prefix])) { - $this->prefixesPsr0[$first][$prefix] = (array) $paths; + $this->prefixesPsr0[$first][$prefix] = $paths; return; } if ($prepend) { $this->prefixesPsr0[$first][$prefix] = array_merge( - (array) $paths, + $paths, $this->prefixesPsr0[$first][$prefix] ); } else { $this->prefixesPsr0[$first][$prefix] = array_merge( $this->prefixesPsr0[$first][$prefix], - (array) $paths + $paths ); } } @@ -147,25 +219,28 @@ class ClassLoader * Registers a set of PSR-4 directories for a given namespace, either * appending or prepending to the ones previously set for this namespace. * - * @param string $prefix The prefix/namespace, with trailing '\\' - * @param array|string $paths The PSR-4 base directories - * @param bool $prepend Whether to prepend the directories + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param list|string $paths The PSR-4 base directories + * @param bool $prepend Whether to prepend the directories * * @throws \InvalidArgumentException + * + * @return void */ public function addPsr4($prefix, $paths, $prepend = false) { + $paths = (array) $paths; if (!$prefix) { // Register directories for the root namespace. if ($prepend) { $this->fallbackDirsPsr4 = array_merge( - (array) $paths, + $paths, $this->fallbackDirsPsr4 ); } else { $this->fallbackDirsPsr4 = array_merge( $this->fallbackDirsPsr4, - (array) $paths + $paths ); } } elseif (!isset($this->prefixDirsPsr4[$prefix])) { @@ -175,18 +250,18 @@ class ClassLoader throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); } $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; - $this->prefixDirsPsr4[$prefix] = (array) $paths; + $this->prefixDirsPsr4[$prefix] = $paths; } elseif ($prepend) { // Prepend directories for an already registered namespace. $this->prefixDirsPsr4[$prefix] = array_merge( - (array) $paths, + $paths, $this->prefixDirsPsr4[$prefix] ); } else { // Append directories for an already registered namespace. $this->prefixDirsPsr4[$prefix] = array_merge( $this->prefixDirsPsr4[$prefix], - (array) $paths + $paths ); } } @@ -195,8 +270,10 @@ class ClassLoader * Registers a set of PSR-0 directories for a given prefix, * replacing any others previously set for this prefix. * - * @param string $prefix The prefix - * @param array|string $paths The PSR-0 base directories + * @param string $prefix The prefix + * @param list|string $paths The PSR-0 base directories + * + * @return void */ public function set($prefix, $paths) { @@ -211,10 +288,12 @@ class ClassLoader * Registers a set of PSR-4 directories for a given namespace, * replacing any others previously set for this namespace. * - * @param string $prefix The prefix/namespace, with trailing '\\' - * @param array|string $paths The PSR-4 base directories + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param list|string $paths The PSR-4 base directories * * @throws \InvalidArgumentException + * + * @return void */ public function setPsr4($prefix, $paths) { @@ -234,6 +313,8 @@ class ClassLoader * Turns on searching the include path for class files. * * @param bool $useIncludePath + * + * @return void */ public function setUseIncludePath($useIncludePath) { @@ -256,6 +337,8 @@ class ClassLoader * that have not been registered with the class map. * * @param bool $classMapAuthoritative + * + * @return void */ public function setClassMapAuthoritative($classMapAuthoritative) { @@ -276,6 +359,8 @@ class ClassLoader * APCu prefix to use to cache found/not-found classes, if the extension is enabled. * * @param string|null $apcuPrefix + * + * @return void */ public function setApcuPrefix($apcuPrefix) { @@ -296,33 +381,55 @@ class ClassLoader * Registers this instance as an autoloader. * * @param bool $prepend Whether to prepend the autoloader or not + * + * @return void */ public function register($prepend = false) { spl_autoload_register(array($this, 'loadClass'), true, $prepend); + + if (null === $this->vendorDir) { + return; + } + + if ($prepend) { + self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders; + } else { + unset(self::$registeredLoaders[$this->vendorDir]); + self::$registeredLoaders[$this->vendorDir] = $this; + } } /** * Unregisters this instance as an autoloader. + * + * @return void */ public function unregister() { spl_autoload_unregister(array($this, 'loadClass')); + + if (null !== $this->vendorDir) { + unset(self::$registeredLoaders[$this->vendorDir]); + } } /** * Loads the given class or interface. * * @param string $class The name of the class - * @return bool|null True if loaded, null otherwise + * @return true|null True if loaded, null otherwise */ public function loadClass($class) { if ($file = $this->findFile($class)) { - includeFile($file); + $includeFile = self::$includeFile; + $includeFile($file); return true; } + + return null; } /** @@ -367,6 +474,21 @@ class ClassLoader return $file; } + /** + * Returns the currently registered loaders keyed by their corresponding vendor directories. + * + * @return array + */ + public static function getRegisteredLoaders() + { + return self::$registeredLoaders; + } + + /** + * @param string $class + * @param string $ext + * @return string|false + */ private function findFileWithExtension($class, $ext) { // PSR-4 lookup @@ -432,14 +554,26 @@ class ClassLoader return false; } -} -/** - * Scope isolated include. - * - * Prevents access to $this/self from included files. - */ -function includeFile($file) -{ - include $file; + /** + * @return void + */ + private static function initializeIncludeClosure() + { + if (self::$includeFile !== null) { + return; + } + + /** + * Scope isolated include. + * + * Prevents access to $this/self from included files. + * + * @param string $file + * @return void + */ + self::$includeFile = \Closure::bind(static function($file) { + include $file; + }, null, null); + } } diff --git a/advancedcontentfilter/vendor/composer/InstalledVersions.php b/advancedcontentfilter/vendor/composer/InstalledVersions.php new file mode 100644 index 000000000..51e734a77 --- /dev/null +++ b/advancedcontentfilter/vendor/composer/InstalledVersions.php @@ -0,0 +1,359 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer; + +use Composer\Autoload\ClassLoader; +use Composer\Semver\VersionParser; + +/** + * This class is copied in every Composer installed project and available to all + * + * See also https://getcomposer.org/doc/07-runtime.md#installed-versions + * + * To require its presence, you can require `composer-runtime-api ^2.0` + * + * @final + */ +class InstalledVersions +{ + /** + * @var mixed[]|null + * @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array}|array{}|null + */ + private static $installed; + + /** + * @var bool|null + */ + private static $canGetVendors; + + /** + * @var array[] + * @psalm-var array}> + */ + private static $installedByVendor = array(); + + /** + * Returns a list of all package names which are present, either by being installed, replaced or provided + * + * @return string[] + * @psalm-return list + */ + public static function getInstalledPackages() + { + $packages = array(); + foreach (self::getInstalled() as $installed) { + $packages[] = array_keys($installed['versions']); + } + + if (1 === \count($packages)) { + return $packages[0]; + } + + return array_keys(array_flip(\call_user_func_array('array_merge', $packages))); + } + + /** + * Returns a list of all package names with a specific type e.g. 'library' + * + * @param string $type + * @return string[] + * @psalm-return list + */ + public static function getInstalledPackagesByType($type) + { + $packagesByType = array(); + + foreach (self::getInstalled() as $installed) { + foreach ($installed['versions'] as $name => $package) { + if (isset($package['type']) && $package['type'] === $type) { + $packagesByType[] = $name; + } + } + } + + return $packagesByType; + } + + /** + * Checks whether the given package is installed + * + * This also returns true if the package name is provided or replaced by another package + * + * @param string $packageName + * @param bool $includeDevRequirements + * @return bool + */ + public static function isInstalled($packageName, $includeDevRequirements = true) + { + foreach (self::getInstalled() as $installed) { + if (isset($installed['versions'][$packageName])) { + return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false; + } + } + + return false; + } + + /** + * Checks whether the given package satisfies a version constraint + * + * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call: + * + * Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3') + * + * @param VersionParser $parser Install composer/semver to have access to this class and functionality + * @param string $packageName + * @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package + * @return bool + */ + public static function satisfies(VersionParser $parser, $packageName, $constraint) + { + $constraint = $parser->parseConstraints((string) $constraint); + $provided = $parser->parseConstraints(self::getVersionRanges($packageName)); + + return $provided->matches($constraint); + } + + /** + * Returns a version constraint representing all the range(s) which are installed for a given package + * + * It is easier to use this via isInstalled() with the $constraint argument if you need to check + * whether a given version of a package is installed, and not just whether it exists + * + * @param string $packageName + * @return string Version constraint usable with composer/semver + */ + public static function getVersionRanges($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + $ranges = array(); + if (isset($installed['versions'][$packageName]['pretty_version'])) { + $ranges[] = $installed['versions'][$packageName]['pretty_version']; + } + if (array_key_exists('aliases', $installed['versions'][$packageName])) { + $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']); + } + if (array_key_exists('replaced', $installed['versions'][$packageName])) { + $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']); + } + if (array_key_exists('provided', $installed['versions'][$packageName])) { + $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']); + } + + return implode(' || ', $ranges); + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present + */ + public static function getVersion($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + if (!isset($installed['versions'][$packageName]['version'])) { + return null; + } + + return $installed['versions'][$packageName]['version']; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present + */ + public static function getPrettyVersion($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + if (!isset($installed['versions'][$packageName]['pretty_version'])) { + return null; + } + + return $installed['versions'][$packageName]['pretty_version']; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference + */ + public static function getReference($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + if (!isset($installed['versions'][$packageName]['reference'])) { + return null; + } + + return $installed['versions'][$packageName]['reference']; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path. + */ + public static function getInstallPath($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @return array + * @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool} + */ + public static function getRootPackage() + { + $installed = self::getInstalled(); + + return $installed[0]['root']; + } + + /** + * Returns the raw installed.php data for custom implementations + * + * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect. + * @return array[] + * @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} + */ + public static function getRawData() + { + @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED); + + if (null === self::$installed) { + // only require the installed.php file if this file is loaded from its dumped location, + // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 + if (substr(__DIR__, -8, 1) !== 'C') { + self::$installed = include __DIR__ . '/installed.php'; + } else { + self::$installed = array(); + } + } + + return self::$installed; + } + + /** + * Returns the raw data of all installed.php which are currently loaded for custom implementations + * + * @return array[] + * @psalm-return list}> + */ + public static function getAllRawData() + { + return self::getInstalled(); + } + + /** + * Lets you reload the static array from another file + * + * This is only useful for complex integrations in which a project needs to use + * this class but then also needs to execute another project's autoloader in process, + * and wants to ensure both projects have access to their version of installed.php. + * + * A typical case would be PHPUnit, where it would need to make sure it reads all + * the data it needs from this class, then call reload() with + * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure + * the project in which it runs can then also use this class safely, without + * interference between PHPUnit's dependencies and the project's dependencies. + * + * @param array[] $data A vendor/composer/installed.php data set + * @return void + * + * @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $data + */ + public static function reload($data) + { + self::$installed = $data; + self::$installedByVendor = array(); + } + + /** + * @return array[] + * @psalm-return list}> + */ + private static function getInstalled() + { + if (null === self::$canGetVendors) { + self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders'); + } + + $installed = array(); + + if (self::$canGetVendors) { + foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) { + if (isset(self::$installedByVendor[$vendorDir])) { + $installed[] = self::$installedByVendor[$vendorDir]; + } elseif (is_file($vendorDir.'/composer/installed.php')) { + /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $required */ + $required = require $vendorDir.'/composer/installed.php'; + $installed[] = self::$installedByVendor[$vendorDir] = $required; + if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) { + self::$installed = $installed[count($installed) - 1]; + } + } + } + } + + if (null === self::$installed) { + // only require the installed.php file if this file is loaded from its dumped location, + // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 + if (substr(__DIR__, -8, 1) !== 'C') { + /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $required */ + $required = require __DIR__ . '/installed.php'; + self::$installed = $required; + } else { + self::$installed = array(); + } + } + + if (self::$installed !== array()) { + $installed[] = self::$installed; + } + + return $installed; + } +} diff --git a/advancedcontentfilter/vendor/composer/autoload_classmap.php b/advancedcontentfilter/vendor/composer/autoload_classmap.php index 9f79be5c0..fe2a622a6 100644 --- a/advancedcontentfilter/vendor/composer/autoload_classmap.php +++ b/advancedcontentfilter/vendor/composer/autoload_classmap.php @@ -2,11 +2,12 @@ // autoload_classmap.php @generated by Composer -$vendorDir = dirname(dirname(__FILE__)); +$vendorDir = dirname(__DIR__); $baseDir = dirname($vendorDir); return array( 'Attribute' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php', + 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php', 'FastRoute\\BadRouteException' => $vendorDir . '/nikic/fast-route/src/BadRouteException.php', 'FastRoute\\DataGenerator' => $vendorDir . '/nikic/fast-route/src/DataGenerator.php', 'FastRoute\\DataGenerator\\CharCountBased' => $vendorDir . '/nikic/fast-route/src/DataGenerator/CharCountBased.php', @@ -154,7 +155,6 @@ return array( 'Symfony\\Component\\Cache\\Adapter\\TagAwareAdapter' => $vendorDir . '/symfony/cache/Adapter/TagAwareAdapter.php', 'Symfony\\Component\\Cache\\Adapter\\TagAwareAdapterInterface' => $vendorDir . '/symfony/cache/Adapter/TagAwareAdapterInterface.php', 'Symfony\\Component\\Cache\\Adapter\\TraceableAdapter' => $vendorDir . '/symfony/cache/Adapter/TraceableAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\TraceableAdapterEvent' => $vendorDir . '/symfony/cache/Adapter/TraceableAdapter.php', 'Symfony\\Component\\Cache\\Adapter\\TraceableTagAwareAdapter' => $vendorDir . '/symfony/cache/Adapter/TraceableTagAwareAdapter.php', 'Symfony\\Component\\Cache\\CacheItem' => $vendorDir . '/symfony/cache/CacheItem.php', 'Symfony\\Component\\Cache\\DataCollector\\CacheDataCollector' => $vendorDir . '/symfony/cache/DataCollector/CacheDataCollector.php', @@ -188,7 +188,6 @@ return array( 'Symfony\\Component\\Cache\\Simple\\Psr6Cache' => $vendorDir . '/symfony/cache/Simple/Psr6Cache.php', 'Symfony\\Component\\Cache\\Simple\\RedisCache' => $vendorDir . '/symfony/cache/Simple/RedisCache.php', 'Symfony\\Component\\Cache\\Simple\\TraceableCache' => $vendorDir . '/symfony/cache/Simple/TraceableCache.php', - 'Symfony\\Component\\Cache\\Simple\\TraceableCacheEvent' => $vendorDir . '/symfony/cache/Simple/TraceableCache.php', 'Symfony\\Component\\Cache\\Traits\\AbstractAdapterTrait' => $vendorDir . '/symfony/cache/Traits/AbstractAdapterTrait.php', 'Symfony\\Component\\Cache\\Traits\\AbstractTrait' => $vendorDir . '/symfony/cache/Traits/AbstractTrait.php', 'Symfony\\Component\\Cache\\Traits\\ApcuTrait' => $vendorDir . '/symfony/cache/Traits/ApcuTrait.php', @@ -197,7 +196,6 @@ return array( 'Symfony\\Component\\Cache\\Traits\\DoctrineTrait' => $vendorDir . '/symfony/cache/Traits/DoctrineTrait.php', 'Symfony\\Component\\Cache\\Traits\\FilesystemCommonTrait' => $vendorDir . '/symfony/cache/Traits/FilesystemCommonTrait.php', 'Symfony\\Component\\Cache\\Traits\\FilesystemTrait' => $vendorDir . '/symfony/cache/Traits/FilesystemTrait.php', - 'Symfony\\Component\\Cache\\Traits\\LazyValue' => $vendorDir . '/symfony/cache/Traits/PhpFilesTrait.php', 'Symfony\\Component\\Cache\\Traits\\MemcachedTrait' => $vendorDir . '/symfony/cache/Traits/MemcachedTrait.php', 'Symfony\\Component\\Cache\\Traits\\PdoTrait' => $vendorDir . '/symfony/cache/Traits/PdoTrait.php', 'Symfony\\Component\\Cache\\Traits\\PhpArrayTrait' => $vendorDir . '/symfony/cache/Traits/PhpArrayTrait.php', diff --git a/advancedcontentfilter/vendor/composer/autoload_files.php b/advancedcontentfilter/vendor/composer/autoload_files.php index a5d3b9642..aafd69e10 100644 --- a/advancedcontentfilter/vendor/composer/autoload_files.php +++ b/advancedcontentfilter/vendor/composer/autoload_files.php @@ -2,7 +2,7 @@ // autoload_files.php @generated by Composer -$vendorDir = dirname(dirname(__FILE__)); +$vendorDir = dirname(__DIR__); $baseDir = dirname($vendorDir); return array( diff --git a/advancedcontentfilter/vendor/composer/autoload_namespaces.php b/advancedcontentfilter/vendor/composer/autoload_namespaces.php index b7fc0125d..15a2ff3ad 100644 --- a/advancedcontentfilter/vendor/composer/autoload_namespaces.php +++ b/advancedcontentfilter/vendor/composer/autoload_namespaces.php @@ -2,7 +2,7 @@ // autoload_namespaces.php @generated by Composer -$vendorDir = dirname(dirname(__FILE__)); +$vendorDir = dirname(__DIR__); $baseDir = dirname($vendorDir); return array( diff --git a/advancedcontentfilter/vendor/composer/autoload_psr4.php b/advancedcontentfilter/vendor/composer/autoload_psr4.php index 3d716d562..4bf247ce0 100644 --- a/advancedcontentfilter/vendor/composer/autoload_psr4.php +++ b/advancedcontentfilter/vendor/composer/autoload_psr4.php @@ -2,7 +2,7 @@ // autoload_psr4.php @generated by Composer -$vendorDir = dirname(dirname(__FILE__)); +$vendorDir = dirname(__DIR__); $baseDir = dirname($vendorDir); return array( @@ -16,7 +16,7 @@ return array( 'Slim\\' => array($vendorDir . '/slim/slim/Slim'), 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'), 'Psr\\Http\\Server\\' => array($vendorDir . '/psr/http-server-handler/src', $vendorDir . '/psr/http-server-middleware/src'), - 'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-factory/src', $vendorDir . '/psr/http-message/src'), + 'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src', $vendorDir . '/psr/http-factory/src'), 'Psr\\Container\\' => array($vendorDir . '/psr/container/src'), 'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'), 'FastRoute\\' => array($vendorDir . '/nikic/fast-route/src'), diff --git a/advancedcontentfilter/vendor/composer/autoload_real.php b/advancedcontentfilter/vendor/composer/autoload_real.php index d6532d7d4..b305aa002 100644 --- a/advancedcontentfilter/vendor/composer/autoload_real.php +++ b/advancedcontentfilter/vendor/composer/autoload_real.php @@ -22,52 +22,29 @@ class ComposerAutoloaderInitAdvancedContentFilterAddon return self::$loader; } + require __DIR__ . '/platform_check.php'; + spl_autoload_register(array('ComposerAutoloaderInitAdvancedContentFilterAddon', 'loadClassLoader'), true, true); - self::$loader = $loader = new \Composer\Autoload\ClassLoader(); + self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__)); spl_autoload_unregister(array('ComposerAutoloaderInitAdvancedContentFilterAddon', 'loadClassLoader')); - $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); - if ($useStaticLoader) { - require_once __DIR__ . '/autoload_static.php'; - - call_user_func(\Composer\Autoload\ComposerStaticInitAdvancedContentFilterAddon::getInitializer($loader)); - } else { - $map = require __DIR__ . '/autoload_namespaces.php'; - foreach ($map as $namespace => $path) { - $loader->set($namespace, $path); - } - - $map = require __DIR__ . '/autoload_psr4.php'; - foreach ($map as $namespace => $path) { - $loader->setPsr4($namespace, $path); - } - - $classMap = require __DIR__ . '/autoload_classmap.php'; - if ($classMap) { - $loader->addClassMap($classMap); - } - } + require __DIR__ . '/autoload_static.php'; + call_user_func(\Composer\Autoload\ComposerStaticInitAdvancedContentFilterAddon::getInitializer($loader)); $loader->register(true); - if ($useStaticLoader) { - $includeFiles = Composer\Autoload\ComposerStaticInitAdvancedContentFilterAddon::$files; - } else { - $includeFiles = require __DIR__ . '/autoload_files.php'; - } - foreach ($includeFiles as $fileIdentifier => $file) { - composerRequireAdvancedContentFilterAddon($fileIdentifier, $file); + $filesToLoad = \Composer\Autoload\ComposerStaticInitAdvancedContentFilterAddon::$files; + $requireFile = \Closure::bind(static function ($fileIdentifier, $file) { + if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { + $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; + + require $file; + } + }, null, null); + foreach ($filesToLoad as $fileIdentifier => $file) { + $requireFile($fileIdentifier, $file); } return $loader; } } - -function composerRequireAdvancedContentFilterAddon($fileIdentifier, $file) -{ - if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { - require $file; - - $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; - } -} diff --git a/advancedcontentfilter/vendor/composer/autoload_static.php b/advancedcontentfilter/vendor/composer/autoload_static.php index 57172a1a3..8cc48b1af 100644 --- a/advancedcontentfilter/vendor/composer/autoload_static.php +++ b/advancedcontentfilter/vendor/composer/autoload_static.php @@ -83,8 +83,8 @@ class ComposerStaticInitAdvancedContentFilterAddon ), 'Psr\\Http\\Message\\' => array ( - 0 => __DIR__ . '/..' . '/psr/http-factory/src', - 1 => __DIR__ . '/..' . '/psr/http-message/src', + 0 => __DIR__ . '/..' . '/psr/http-message/src', + 1 => __DIR__ . '/..' . '/psr/http-factory/src', ), 'Psr\\Container\\' => array ( @@ -102,6 +102,7 @@ class ComposerStaticInitAdvancedContentFilterAddon public static $classMap = array ( 'Attribute' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Attribute.php', + 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', 'FastRoute\\BadRouteException' => __DIR__ . '/..' . '/nikic/fast-route/src/BadRouteException.php', 'FastRoute\\DataGenerator' => __DIR__ . '/..' . '/nikic/fast-route/src/DataGenerator.php', 'FastRoute\\DataGenerator\\CharCountBased' => __DIR__ . '/..' . '/nikic/fast-route/src/DataGenerator/CharCountBased.php', @@ -249,7 +250,6 @@ class ComposerStaticInitAdvancedContentFilterAddon 'Symfony\\Component\\Cache\\Adapter\\TagAwareAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/TagAwareAdapter.php', 'Symfony\\Component\\Cache\\Adapter\\TagAwareAdapterInterface' => __DIR__ . '/..' . '/symfony/cache/Adapter/TagAwareAdapterInterface.php', 'Symfony\\Component\\Cache\\Adapter\\TraceableAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/TraceableAdapter.php', - 'Symfony\\Component\\Cache\\Adapter\\TraceableAdapterEvent' => __DIR__ . '/..' . '/symfony/cache/Adapter/TraceableAdapter.php', 'Symfony\\Component\\Cache\\Adapter\\TraceableTagAwareAdapter' => __DIR__ . '/..' . '/symfony/cache/Adapter/TraceableTagAwareAdapter.php', 'Symfony\\Component\\Cache\\CacheItem' => __DIR__ . '/..' . '/symfony/cache/CacheItem.php', 'Symfony\\Component\\Cache\\DataCollector\\CacheDataCollector' => __DIR__ . '/..' . '/symfony/cache/DataCollector/CacheDataCollector.php', @@ -283,7 +283,6 @@ class ComposerStaticInitAdvancedContentFilterAddon 'Symfony\\Component\\Cache\\Simple\\Psr6Cache' => __DIR__ . '/..' . '/symfony/cache/Simple/Psr6Cache.php', 'Symfony\\Component\\Cache\\Simple\\RedisCache' => __DIR__ . '/..' . '/symfony/cache/Simple/RedisCache.php', 'Symfony\\Component\\Cache\\Simple\\TraceableCache' => __DIR__ . '/..' . '/symfony/cache/Simple/TraceableCache.php', - 'Symfony\\Component\\Cache\\Simple\\TraceableCacheEvent' => __DIR__ . '/..' . '/symfony/cache/Simple/TraceableCache.php', 'Symfony\\Component\\Cache\\Traits\\AbstractAdapterTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/AbstractAdapterTrait.php', 'Symfony\\Component\\Cache\\Traits\\AbstractTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/AbstractTrait.php', 'Symfony\\Component\\Cache\\Traits\\ApcuTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/ApcuTrait.php', @@ -292,7 +291,6 @@ class ComposerStaticInitAdvancedContentFilterAddon 'Symfony\\Component\\Cache\\Traits\\DoctrineTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/DoctrineTrait.php', 'Symfony\\Component\\Cache\\Traits\\FilesystemCommonTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/FilesystemCommonTrait.php', 'Symfony\\Component\\Cache\\Traits\\FilesystemTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/FilesystemTrait.php', - 'Symfony\\Component\\Cache\\Traits\\LazyValue' => __DIR__ . '/..' . '/symfony/cache/Traits/PhpFilesTrait.php', 'Symfony\\Component\\Cache\\Traits\\MemcachedTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/MemcachedTrait.php', 'Symfony\\Component\\Cache\\Traits\\PdoTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/PdoTrait.php', 'Symfony\\Component\\Cache\\Traits\\PhpArrayTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/PhpArrayTrait.php', diff --git a/advancedcontentfilter/vendor/composer/installed.json b/advancedcontentfilter/vendor/composer/installed.json index 07e02c7f1..70c2dc41a 100644 --- a/advancedcontentfilter/vendor/composer/installed.json +++ b/advancedcontentfilter/vendor/composer/installed.json @@ -1,1190 +1,1212 @@ -[ - { - "name": "nikic/fast-route", - "version": "v1.3.0", - "version_normalized": "1.3.0.0", - "source": { - "type": "git", - "url": "https://github.com/nikic/FastRoute.git", - "reference": "181d480e08d9476e61381e04a71b34dc0432e812" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nikic/FastRoute/zipball/181d480e08d9476e61381e04a71b34dc0432e812", - "reference": "181d480e08d9476e61381e04a71b34dc0432e812", - "shasum": "" - }, - "require": { - "php": ">=5.4.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.35|~5.7" - }, - "time": "2018-02-13T20:26:39+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "FastRoute\\": "src/" +{ + "packages": [ + { + "name": "nikic/fast-route", + "version": "v1.3.0", + "version_normalized": "1.3.0.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/FastRoute.git", + "reference": "181d480e08d9476e61381e04a71b34dc0432e812" }, - "files": [ - "src/functions.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Nikita Popov", - "email": "nikic@php.net" - } - ], - "description": "Fast request router for PHP", - "keywords": [ - "router", - "routing" - ] - }, - { - "name": "psr/cache", - "version": "1.0.1", - "version_normalized": "1.0.1.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/cache.git", - "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8", - "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "time": "2016-08-06T20:24:11+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Psr\\Cache\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for caching libraries", - "keywords": [ - "cache", - "psr", - "psr-6" - ] - }, - { - "name": "psr/container", - "version": "1.1.2", - "version_normalized": "1.1.2.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", - "shasum": "" - }, - "require": { - "php": ">=7.4.0" - }, - "time": "2021-11-05T16:50:12+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Psr\\Container\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", - "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" - ] - }, - { - "name": "psr/http-factory", - "version": "1.0.2", - "version_normalized": "1.0.2.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-factory.git", - "reference": "e616d01114759c4c489f93b099585439f795fe35" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35", - "reference": "e616d01114759c4c489f93b099585439f795fe35", - "shasum": "" - }, - "require": { - "php": ">=7.0.0", - "psr/http-message": "^1.0 || ^2.0" - }, - "time": "2023-04-10T20:10:41+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Psr\\Http\\Message\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interfaces for PSR-7 HTTP message factories", - "keywords": [ - "factory", - "http", - "message", - "psr", - "psr-17", - "psr-7", - "request", - "response" - ] - }, - { - "name": "psr/http-message", - "version": "2.0", - "version_normalized": "2.0.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", - "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "time": "2023-04-04T09:54:51+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Psr\\Http\\Message\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for HTTP messages", - "homepage": "https://github.com/php-fig/http-message", - "keywords": [ - "http", - "http-message", - "psr", - "psr-7", - "request", - "response" - ] - }, - { - "name": "psr/http-server-handler", - "version": "1.0.2", - "version_normalized": "1.0.2.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-server-handler.git", - "reference": "84c4fb66179be4caaf8e97bd239203245302e7d4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-server-handler/zipball/84c4fb66179be4caaf8e97bd239203245302e7d4", - "reference": "84c4fb66179be4caaf8e97bd239203245302e7d4", - "shasum": "" - }, - "require": { - "php": ">=7.0", - "psr/http-message": "^1.0 || ^2.0" - }, - "time": "2023-04-10T20:06:20+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Psr\\Http\\Server\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for HTTP server-side request handler", - "keywords": [ - "handler", - "http", - "http-interop", - "psr", - "psr-15", - "psr-7", - "request", - "response", - "server" - ] - }, - { - "name": "psr/http-server-middleware", - "version": "1.0.2", - "version_normalized": "1.0.2.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-server-middleware.git", - "reference": "c1481f747daaa6a0782775cd6a8c26a1bf4a3829" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-server-middleware/zipball/c1481f747daaa6a0782775cd6a8c26a1bf4a3829", - "reference": "c1481f747daaa6a0782775cd6a8c26a1bf4a3829", - "shasum": "" - }, - "require": { - "php": ">=7.0", - "psr/http-message": "^1.0 || ^2.0", - "psr/http-server-handler": "^1.0" - }, - "time": "2023-04-11T06:14:47+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Psr\\Http\\Server\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for HTTP server-side middleware", - "keywords": [ - "http", - "http-interop", - "middleware", - "psr", - "psr-15", - "psr-7", - "request", - "response" - ] - }, - { - "name": "psr/log", - "version": "1.1.4", - "version_normalized": "1.1.4.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "d49695b909c3b7628b6289db5479a1c204601f11" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", - "reference": "d49695b909c3b7628b6289db5479a1c204601f11", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "time": "2021-05-03T11:20:27+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Psr\\Log\\": "Psr/Log/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ] - }, - { - "name": "slim/slim", - "version": "4.13.0", - "version_normalized": "4.13.0.0", - "source": { - "type": "git", - "url": "https://github.com/slimphp/Slim.git", - "reference": "038fd5713d5a41636fdff0e8dcceedecdd17fc17" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/slimphp/Slim/zipball/038fd5713d5a41636fdff0e8dcceedecdd17fc17", - "reference": "038fd5713d5a41636fdff0e8dcceedecdd17fc17", - "shasum": "" - }, - "require": { - "ext-json": "*", - "nikic/fast-route": "^1.3", - "php": "^7.4 || ^8.0", - "psr/container": "^1.0 || ^2.0", - "psr/http-factory": "^1.0", - "psr/http-message": "^1.1 || ^2.0", - "psr/http-server-handler": "^1.0", - "psr/http-server-middleware": "^1.0", - "psr/log": "^1.1 || ^2.0 || ^3.0" - }, - "require-dev": { - "adriansuter/php-autoload-override": "^1.4", - "ext-simplexml": "*", - "guzzlehttp/psr7": "^2.6", - "httpsoft/http-message": "^1.1", - "httpsoft/http-server-request": "^1.1", - "laminas/laminas-diactoros": "^2.17 || ^3", - "nyholm/psr7": "^1.8", - "nyholm/psr7-server": "^1.1", - "phpspec/prophecy": "^1.19", - "phpspec/prophecy-phpunit": "^2.1", - "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^9.6", - "slim/http": "^1.3", - "slim/psr7": "^1.6", - "squizlabs/php_codesniffer": "^3.9" - }, - "suggest": { - "ext-simplexml": "Needed to support XML format in BodyParsingMiddleware", - "ext-xml": "Needed to support XML format in BodyParsingMiddleware", - "php-di/php-di": "PHP-DI is the recommended container library to be used with Slim", - "slim/psr7": "Slim PSR-7 implementation. See https://www.slimframework.com/docs/v4/start/installation.html for more information." - }, - "time": "2024-03-03T21:25:30+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Slim\\": "Slim" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Josh Lockhart", - "email": "hello@joshlockhart.com", - "homepage": "https://joshlockhart.com" + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/FastRoute/zipball/181d480e08d9476e61381e04a71b34dc0432e812", + "reference": "181d480e08d9476e61381e04a71b34dc0432e812", + "shasum": "" }, - { - "name": "Andrew Smith", - "email": "a.smith@silentworks.co.uk", - "homepage": "http://silentworks.co.uk" + "require": { + "php": ">=5.4.0" }, - { - "name": "Rob Allen", - "email": "rob@akrabat.com", - "homepage": "http://akrabat.com" + "require-dev": { + "phpunit/phpunit": "^4.8.35|~5.7" }, - { - "name": "Pierre Berube", - "email": "pierre@lgse.com", - "homepage": "http://www.lgse.com" + "time": "2018-02-13T20:26:39+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "FastRoute\\": "src/" + }, + "files": [ + "src/functions.php" + ] }, - { - "name": "Gabriel Manricks", - "email": "gmanricks@me.com", - "homepage": "http://gabrielmanricks.com" - } - ], - "description": "Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs", - "homepage": "https://www.slimframework.com", - "keywords": [ - "api", - "framework", - "micro", - "router" - ], - "funding": [ - { - "url": "https://opencollective.com/slimphp", - "type": "open_collective" - }, - { - "url": "https://tidelift.com/funding/github/packagist/slim/slim", - "type": "tidelift" - } - ] - }, - { - "name": "symfony/cache", - "version": "v4.4.48", - "version_normalized": "4.4.48.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/cache.git", - "reference": "3b98ed664887ad197b8ede3da2432787212eb915" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/3b98ed664887ad197b8ede3da2432787212eb915", - "reference": "3b98ed664887ad197b8ede3da2432787212eb915", - "shasum": "" - }, - "require": { - "php": ">=7.1.3", - "psr/cache": "^1.0|^2.0", - "psr/log": "^1|^2|^3", - "symfony/cache-contracts": "^1.1.7|^2", - "symfony/polyfill-php73": "^1.9", - "symfony/polyfill-php80": "^1.16", - "symfony/service-contracts": "^1.1|^2", - "symfony/var-exporter": "^4.2|^5.0" - }, - "conflict": { - "doctrine/dbal": "<2.7", - "symfony/dependency-injection": "<3.4", - "symfony/http-kernel": "<4.4|>=5.0", - "symfony/var-dumper": "<4.4" - }, - "provide": { - "psr/cache-implementation": "1.0|2.0", - "psr/simple-cache-implementation": "1.0|2.0", - "symfony/cache-implementation": "1.0|2.0" - }, - "require-dev": { - "cache/integration-tests": "dev-master", - "doctrine/cache": "^1.6|^2.0", - "doctrine/dbal": "^2.7|^3.0", - "predis/predis": "^1.1", - "psr/simple-cache": "^1.0|^2.0", - "symfony/config": "^4.2|^5.0", - "symfony/dependency-injection": "^3.4|^4.1|^5.0", - "symfony/filesystem": "^4.4|^5.0", - "symfony/http-kernel": "^4.4", - "symfony/var-dumper": "^4.4|^5.0" - }, - "time": "2022-10-17T20:21:54+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\Cache\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides extended PSR-6, PSR-16 (and tags) implementations", - "homepage": "https://symfony.com", - "keywords": [ - "caching", - "psr6" - ], - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ] - }, - { - "name": "symfony/cache-contracts", - "version": "v2.5.2", - "version_normalized": "2.5.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/cache-contracts.git", - "reference": "64be4a7acb83b6f2bf6de9a02cee6dad41277ebc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/64be4a7acb83b6f2bf6de9a02cee6dad41277ebc", - "reference": "64be4a7acb83b6f2bf6de9a02cee6dad41277ebc", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "psr/cache": "^1.0|^2.0|^3.0" - }, - "suggest": { - "symfony/cache-implementation": "" - }, - "time": "2022-01-02T09:53:40+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "2.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Contracts\\Cache\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to caching", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ] - }, - { - "name": "symfony/deprecation-contracts", - "version": "v2.5.2", - "version_normalized": "2.5.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e8b495ea28c1d97b5e0c121748d6f9b53d075c66", - "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "time": "2022-01-02T09:53:40+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "2.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "installation-source": "dist", - "autoload": { - "files": [ - "function.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "A generic function and convention to trigger deprecation notices", - "homepage": "https://symfony.com", - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ] - }, - { - "name": "symfony/expression-language", - "version": "v3.4.47", - "version_normalized": "3.4.47.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/expression-language.git", - "reference": "de38e66398fca1fcb9c48e80279910e6889cb28f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/expression-language/zipball/de38e66398fca1fcb9c48e80279910e6889cb28f", - "reference": "de38e66398fca1fcb9c48e80279910e6889cb28f", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8", - "symfony/cache": "~3.1|~4.0", - "symfony/polyfill-php70": "~1.6" - }, - "time": "2020-10-24T10:57:07+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\ExpressionLanguage\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony ExpressionLanguage Component", - "homepage": "https://symfony.com", - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ] - }, - { - "name": "symfony/polyfill-php70", - "version": "v1.20.0", - "version_normalized": "1.20.0.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php70.git", - "reference": "5f03a781d984aae42cebd18e7912fa80f02ee644" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/5f03a781d984aae42cebd18e7912fa80f02ee644", - "reference": "5f03a781d984aae42cebd18e7912fa80f02ee644", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "time": "2020-10-23T14:02:19+00:00", - "type": "metapackage", - "extra": { - "branch-alias": { - "dev-main": "1.20-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 7.0+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ] - }, - { - "name": "symfony/polyfill-php73", - "version": "v1.29.0", - "version_normalized": "1.29.0.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "21bd091060673a1177ae842c0ef8fe30893114d2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/21bd091060673a1177ae842c0ef8fe30893114d2", - "reference": "21bd091060673a1177ae842c0ef8fe30893114d2", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "time": "2024-01-29T20:11:03+00:00", - "type": "library", - "extra": { - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "installation-source": "dist", - "autoload": { - "files": [ - "bootstrap.php" + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" ], - "psr-4": { - "Symfony\\Polyfill\\Php73\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ] - }, - { - "name": "symfony/polyfill-php80", - "version": "v1.29.0", - "version_normalized": "1.29.0.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", - "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "time": "2024-01-29T20:11:03+00:00", - "type": "library", - "extra": { - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "installation-source": "dist", - "autoload": { - "files": [ - "bootstrap.php" + "authors": [ + { + "name": "Nikita Popov", + "email": "nikic@php.net" + } ], - "psr-4": { - "Symfony\\Polyfill\\Php80\\": "" - }, - "classmap": [ - "Resources/stubs" - ] + "description": "Fast request router for PHP", + "keywords": [ + "router", + "routing" + ], + "install-path": "../nikic/fast-route" }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ion Bazan", - "email": "ion.bazan@gmail.com" + { + "name": "psr/cache", + "version": "1.0.1", + "version_normalized": "1.0.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/cache.git", + "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8" }, - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8", + "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8", + "shasum": "" }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" + "require": { + "php": ">=5.3.0" }, - { - "url": "https://github.com/fabpot", - "type": "github" + "time": "2016-08-06T20:24:11+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ] - }, - { - "name": "symfony/service-contracts", - "version": "v2.5.2", - "version_normalized": "2.5.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/service-contracts.git", - "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c", - "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "psr/container": "^1.1", - "symfony/deprecation-contracts": "^2.1|^3" - }, - "conflict": { - "ext-psr": "<1.1|>=2" - }, - "suggest": { - "symfony/service-implementation": "" - }, - "time": "2022-05-30T19:17:29+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "2.5-dev" + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Cache\\": "src/" + } }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for caching libraries", + "keywords": [ + "cache", + "psr", + "psr-6" + ], + "install-path": "../psr/cache" }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Contracts\\Service\\": "" - } + { + "name": "psr/container", + "version": "1.1.2", + "version_normalized": "1.1.2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "time": "2021-11-05T16:50:12+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "install-path": "../psr/container" }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + { + "name": "psr/http-factory", + "version": "1.0.2", + "version_normalized": "1.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "e616d01114759c4c489f93b099585439f795fe35" }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to writing services", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35", + "reference": "e616d01114759c4c489f93b099585439f795fe35", + "shasum": "" }, - { - "url": "https://github.com/fabpot", - "type": "github" + "require": { + "php": ">=7.0.0", + "psr/http-message": "^1.0 || ^2.0" }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ] - }, - { - "name": "symfony/var-exporter", - "version": "v5.4.35", - "version_normalized": "5.4.35.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/var-exporter.git", - "reference": "abb0a151b62d6b07e816487e20040464af96cae7" + "time": "2023-04-10T20:10:41+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "install-path": "../psr/http-factory" }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/abb0a151b62d6b07e816487e20040464af96cae7", - "reference": "abb0a151b62d6b07e816487e20040464af96cae7", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/polyfill-php80": "^1.16" - }, - "require-dev": { - "symfony/var-dumper": "^4.4.9|^5.0.9|^6.0" - }, - "time": "2024-01-23T13:51:25+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\VarExporter\\": "" + { + "name": "psr/http-message", + "version": "2.0", + "version_normalized": "2.0.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" }, - "exclude-from-classmap": [ - "/Tests/" - ] + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "time": "2023-04-04T09:54:51+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "install-path": "../psr/http-message" }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + { + "name": "psr/http-server-handler", + "version": "1.0.2", + "version_normalized": "1.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-server-handler.git", + "reference": "84c4fb66179be4caaf8e97bd239203245302e7d4" }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Allows exporting any serializable PHP data structure to plain PHP code", - "homepage": "https://symfony.com", - "keywords": [ - "clone", - "construct", - "export", - "hydrate", - "instantiate", - "serialize" - ], - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-server-handler/zipball/84c4fb66179be4caaf8e97bd239203245302e7d4", + "reference": "84c4fb66179be4caaf8e97bd239203245302e7d4", + "shasum": "" }, - { - "url": "https://github.com/fabpot", - "type": "github" + "require": { + "php": ">=7.0", + "psr/http-message": "^1.0 || ^2.0" }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ] - } -] + "time": "2023-04-10T20:06:20+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Http\\Server\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP server-side request handler", + "keywords": [ + "handler", + "http", + "http-interop", + "psr", + "psr-15", + "psr-7", + "request", + "response", + "server" + ], + "install-path": "../psr/http-server-handler" + }, + { + "name": "psr/http-server-middleware", + "version": "1.0.2", + "version_normalized": "1.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-server-middleware.git", + "reference": "c1481f747daaa6a0782775cd6a8c26a1bf4a3829" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-server-middleware/zipball/c1481f747daaa6a0782775cd6a8c26a1bf4a3829", + "reference": "c1481f747daaa6a0782775cd6a8c26a1bf4a3829", + "shasum": "" + }, + "require": { + "php": ">=7.0", + "psr/http-message": "^1.0 || ^2.0", + "psr/http-server-handler": "^1.0" + }, + "time": "2023-04-11T06:14:47+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Http\\Server\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP server-side middleware", + "keywords": [ + "http", + "http-interop", + "middleware", + "psr", + "psr-15", + "psr-7", + "request", + "response" + ], + "install-path": "../psr/http-server-middleware" + }, + { + "name": "psr/log", + "version": "1.1.4", + "version_normalized": "1.1.4.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "time": "2021-05-03T11:20:27+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "install-path": "../psr/log" + }, + { + "name": "slim/slim", + "version": "4.13.0", + "version_normalized": "4.13.0.0", + "source": { + "type": "git", + "url": "https://github.com/slimphp/Slim.git", + "reference": "038fd5713d5a41636fdff0e8dcceedecdd17fc17" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/slimphp/Slim/zipball/038fd5713d5a41636fdff0e8dcceedecdd17fc17", + "reference": "038fd5713d5a41636fdff0e8dcceedecdd17fc17", + "shasum": "" + }, + "require": { + "ext-json": "*", + "nikic/fast-route": "^1.3", + "php": "^7.4 || ^8.0", + "psr/container": "^1.0 || ^2.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1 || ^2.0", + "psr/http-server-handler": "^1.0", + "psr/http-server-middleware": "^1.0", + "psr/log": "^1.1 || ^2.0 || ^3.0" + }, + "require-dev": { + "adriansuter/php-autoload-override": "^1.4", + "ext-simplexml": "*", + "guzzlehttp/psr7": "^2.6", + "httpsoft/http-message": "^1.1", + "httpsoft/http-server-request": "^1.1", + "laminas/laminas-diactoros": "^2.17 || ^3", + "nyholm/psr7": "^1.8", + "nyholm/psr7-server": "^1.1", + "phpspec/prophecy": "^1.19", + "phpspec/prophecy-phpunit": "^2.1", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^9.6", + "slim/http": "^1.3", + "slim/psr7": "^1.6", + "squizlabs/php_codesniffer": "^3.9" + }, + "suggest": { + "ext-simplexml": "Needed to support XML format in BodyParsingMiddleware", + "ext-xml": "Needed to support XML format in BodyParsingMiddleware", + "php-di/php-di": "PHP-DI is the recommended container library to be used with Slim", + "slim/psr7": "Slim PSR-7 implementation. See https://www.slimframework.com/docs/v4/start/installation.html for more information." + }, + "time": "2024-03-03T21:25:30+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Slim\\": "Slim" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Josh Lockhart", + "email": "hello@joshlockhart.com", + "homepage": "https://joshlockhart.com" + }, + { + "name": "Andrew Smith", + "email": "a.smith@silentworks.co.uk", + "homepage": "http://silentworks.co.uk" + }, + { + "name": "Rob Allen", + "email": "rob@akrabat.com", + "homepage": "http://akrabat.com" + }, + { + "name": "Pierre Berube", + "email": "pierre@lgse.com", + "homepage": "http://www.lgse.com" + }, + { + "name": "Gabriel Manricks", + "email": "gmanricks@me.com", + "homepage": "http://gabrielmanricks.com" + } + ], + "description": "Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs", + "homepage": "https://www.slimframework.com", + "keywords": [ + "api", + "framework", + "micro", + "router" + ], + "funding": [ + { + "url": "https://opencollective.com/slimphp", + "type": "open_collective" + }, + { + "url": "https://tidelift.com/funding/github/packagist/slim/slim", + "type": "tidelift" + } + ], + "install-path": "../slim/slim" + }, + { + "name": "symfony/cache", + "version": "v4.4.48", + "version_normalized": "4.4.48.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/cache.git", + "reference": "3b98ed664887ad197b8ede3da2432787212eb915" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/cache/zipball/3b98ed664887ad197b8ede3da2432787212eb915", + "reference": "3b98ed664887ad197b8ede3da2432787212eb915", + "shasum": "" + }, + "require": { + "php": ">=7.1.3", + "psr/cache": "^1.0|^2.0", + "psr/log": "^1|^2|^3", + "symfony/cache-contracts": "^1.1.7|^2", + "symfony/polyfill-php73": "^1.9", + "symfony/polyfill-php80": "^1.16", + "symfony/service-contracts": "^1.1|^2", + "symfony/var-exporter": "^4.2|^5.0" + }, + "conflict": { + "doctrine/dbal": "<2.7", + "symfony/dependency-injection": "<3.4", + "symfony/http-kernel": "<4.4|>=5.0", + "symfony/var-dumper": "<4.4" + }, + "provide": { + "psr/cache-implementation": "1.0|2.0", + "psr/simple-cache-implementation": "1.0|2.0", + "symfony/cache-implementation": "1.0|2.0" + }, + "require-dev": { + "cache/integration-tests": "dev-master", + "doctrine/cache": "^1.6|^2.0", + "doctrine/dbal": "^2.7|^3.0", + "predis/predis": "^1.1", + "psr/simple-cache": "^1.0|^2.0", + "symfony/config": "^4.2|^5.0", + "symfony/dependency-injection": "^3.4|^4.1|^5.0", + "symfony/filesystem": "^4.4|^5.0", + "symfony/http-kernel": "^4.4", + "symfony/var-dumper": "^4.4|^5.0" + }, + "time": "2022-10-17T20:21:54+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\Cache\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides extended PSR-6, PSR-16 (and tags) implementations", + "homepage": "https://symfony.com", + "keywords": [ + "caching", + "psr6" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/cache" + }, + { + "name": "symfony/cache-contracts", + "version": "v2.5.2", + "version_normalized": "2.5.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/cache-contracts.git", + "reference": "64be4a7acb83b6f2bf6de9a02cee6dad41277ebc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/64be4a7acb83b6f2bf6de9a02cee6dad41277ebc", + "reference": "64be4a7acb83b6f2bf6de9a02cee6dad41277ebc", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/cache": "^1.0|^2.0|^3.0" + }, + "suggest": { + "symfony/cache-implementation": "" + }, + "time": "2022-01-02T09:53:40+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Cache\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to caching", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/cache-contracts" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v2.5.2", + "version_normalized": "2.5.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e8b495ea28c1d97b5e0c121748d6f9b53d075c66", + "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "time": "2022-01-02T09:53:40+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/deprecation-contracts" + }, + { + "name": "symfony/expression-language", + "version": "v3.4.47", + "version_normalized": "3.4.47.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/expression-language.git", + "reference": "de38e66398fca1fcb9c48e80279910e6889cb28f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/expression-language/zipball/de38e66398fca1fcb9c48e80279910e6889cb28f", + "reference": "de38e66398fca1fcb9c48e80279910e6889cb28f", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8", + "symfony/cache": "~3.1|~4.0", + "symfony/polyfill-php70": "~1.6" + }, + "time": "2020-10-24T10:57:07+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\ExpressionLanguage\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony ExpressionLanguage Component", + "homepage": "https://symfony.com", + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/expression-language" + }, + { + "name": "symfony/polyfill-php70", + "version": "v1.20.0", + "version_normalized": "1.20.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php70.git", + "reference": "5f03a781d984aae42cebd18e7912fa80f02ee644" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/5f03a781d984aae42cebd18e7912fa80f02ee644", + "reference": "5f03a781d984aae42cebd18e7912fa80f02ee644", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "time": "2020-10-23T14:02:19+00:00", + "type": "metapackage", + "extra": { + "branch-alias": { + "dev-main": "1.20-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": null + }, + { + "name": "symfony/polyfill-php73", + "version": "v1.29.0", + "version_normalized": "1.29.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php73.git", + "reference": "21bd091060673a1177ae842c0ef8fe30893114d2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/21bd091060673a1177ae842c0ef8fe30893114d2", + "reference": "21bd091060673a1177ae842c0ef8fe30893114d2", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "time": "2024-01-29T20:11:03+00:00", + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php73\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/polyfill-php73" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.29.0", + "version_normalized": "1.29.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", + "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "time": "2024-01-29T20:11:03+00:00", + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/polyfill-php80" + }, + { + "name": "symfony/service-contracts", + "version": "v2.5.2", + "version_normalized": "2.5.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c", + "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/container": "^1.1", + "symfony/deprecation-contracts": "^2.1|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "suggest": { + "symfony/service-implementation": "" + }, + "time": "2022-05-30T19:17:29+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/service-contracts" + }, + { + "name": "symfony/var-exporter", + "version": "v5.4.35", + "version_normalized": "5.4.35.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-exporter.git", + "reference": "abb0a151b62d6b07e816487e20040464af96cae7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/abb0a151b62d6b07e816487e20040464af96cae7", + "reference": "abb0a151b62d6b07e816487e20040464af96cae7", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-php80": "^1.16" + }, + "require-dev": { + "symfony/var-dumper": "^4.4.9|^5.0.9|^6.0" + }, + "time": "2024-01-23T13:51:25+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\VarExporter\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Allows exporting any serializable PHP data structure to plain PHP code", + "homepage": "https://symfony.com", + "keywords": [ + "clone", + "construct", + "export", + "hydrate", + "instantiate", + "serialize" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/var-exporter" + } + ], + "dev": false, + "dev-package-names": [] +} diff --git a/advancedcontentfilter/vendor/composer/installed.php b/advancedcontentfilter/vendor/composer/installed.php new file mode 100644 index 000000000..010b1da9c --- /dev/null +++ b/advancedcontentfilter/vendor/composer/installed.php @@ -0,0 +1,203 @@ + array( + 'name' => 'friendica-addons/advancedcontentfilter', + 'pretty_version' => 'dev-develop', + 'version' => 'dev-develop', + 'reference' => 'feb7722f723b21e76fdf20a7ce4b42fa5ffcdcb9', + 'type' => 'friendica-addon', + 'install_path' => __DIR__ . '/../../', + 'aliases' => array(), + 'dev' => false, + ), + 'versions' => array( + 'friendica-addons/advancedcontentfilter' => array( + 'pretty_version' => 'dev-develop', + 'version' => 'dev-develop', + 'reference' => 'feb7722f723b21e76fdf20a7ce4b42fa5ffcdcb9', + 'type' => 'friendica-addon', + 'install_path' => __DIR__ . '/../../', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'nikic/fast-route' => array( + 'pretty_version' => 'v1.3.0', + 'version' => '1.3.0.0', + 'reference' => '181d480e08d9476e61381e04a71b34dc0432e812', + 'type' => 'library', + 'install_path' => __DIR__ . '/../nikic/fast-route', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'psr/cache' => array( + 'pretty_version' => '1.0.1', + 'version' => '1.0.1.0', + 'reference' => 'd11b50ad223250cf17b86e38383413f5a6764bf8', + 'type' => 'library', + 'install_path' => __DIR__ . '/../psr/cache', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'psr/cache-implementation' => array( + 'dev_requirement' => false, + 'provided' => array( + 0 => '1.0|2.0', + ), + ), + 'psr/container' => array( + 'pretty_version' => '1.1.2', + 'version' => '1.1.2.0', + 'reference' => '513e0666f7216c7459170d56df27dfcefe1689ea', + 'type' => 'library', + 'install_path' => __DIR__ . '/../psr/container', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'psr/http-factory' => array( + 'pretty_version' => '1.0.2', + 'version' => '1.0.2.0', + 'reference' => 'e616d01114759c4c489f93b099585439f795fe35', + 'type' => 'library', + 'install_path' => __DIR__ . '/../psr/http-factory', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'psr/http-message' => array( + 'pretty_version' => '2.0', + 'version' => '2.0.0.0', + 'reference' => '402d35bcb92c70c026d1a6a9883f06b2ead23d71', + 'type' => 'library', + 'install_path' => __DIR__ . '/../psr/http-message', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'psr/http-server-handler' => array( + 'pretty_version' => '1.0.2', + 'version' => '1.0.2.0', + 'reference' => '84c4fb66179be4caaf8e97bd239203245302e7d4', + 'type' => 'library', + 'install_path' => __DIR__ . '/../psr/http-server-handler', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'psr/http-server-middleware' => array( + 'pretty_version' => '1.0.2', + 'version' => '1.0.2.0', + 'reference' => 'c1481f747daaa6a0782775cd6a8c26a1bf4a3829', + 'type' => 'library', + 'install_path' => __DIR__ . '/../psr/http-server-middleware', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'psr/log' => array( + 'pretty_version' => '1.1.4', + 'version' => '1.1.4.0', + 'reference' => 'd49695b909c3b7628b6289db5479a1c204601f11', + 'type' => 'library', + 'install_path' => __DIR__ . '/../psr/log', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'psr/simple-cache-implementation' => array( + 'dev_requirement' => false, + 'provided' => array( + 0 => '1.0|2.0', + ), + ), + 'slim/slim' => array( + 'pretty_version' => '4.13.0', + 'version' => '4.13.0.0', + 'reference' => '038fd5713d5a41636fdff0e8dcceedecdd17fc17', + 'type' => 'library', + 'install_path' => __DIR__ . '/../slim/slim', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'symfony/cache' => array( + 'pretty_version' => 'v4.4.48', + 'version' => '4.4.48.0', + 'reference' => '3b98ed664887ad197b8ede3da2432787212eb915', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/cache', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'symfony/cache-contracts' => array( + 'pretty_version' => 'v2.5.2', + 'version' => '2.5.2.0', + 'reference' => '64be4a7acb83b6f2bf6de9a02cee6dad41277ebc', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/cache-contracts', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'symfony/cache-implementation' => array( + 'dev_requirement' => false, + 'provided' => array( + 0 => '1.0|2.0', + ), + ), + 'symfony/deprecation-contracts' => array( + 'pretty_version' => 'v2.5.2', + 'version' => '2.5.2.0', + 'reference' => 'e8b495ea28c1d97b5e0c121748d6f9b53d075c66', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/deprecation-contracts', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'symfony/expression-language' => array( + 'pretty_version' => 'v3.4.47', + 'version' => '3.4.47.0', + 'reference' => 'de38e66398fca1fcb9c48e80279910e6889cb28f', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/expression-language', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'symfony/polyfill-php70' => array( + 'pretty_version' => 'v1.20.0', + 'version' => '1.20.0.0', + 'reference' => '5f03a781d984aae42cebd18e7912fa80f02ee644', + 'type' => 'metapackage', + 'install_path' => null, + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'symfony/polyfill-php73' => array( + 'pretty_version' => 'v1.29.0', + 'version' => '1.29.0.0', + 'reference' => '21bd091060673a1177ae842c0ef8fe30893114d2', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/polyfill-php73', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'symfony/polyfill-php80' => array( + 'pretty_version' => 'v1.29.0', + 'version' => '1.29.0.0', + 'reference' => '87b68208d5c1188808dd7839ee1e6c8ec3b02f1b', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/polyfill-php80', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'symfony/service-contracts' => array( + 'pretty_version' => 'v2.5.2', + 'version' => '2.5.2.0', + 'reference' => '4b426aac47d6427cc1a1d0f7e2ac724627f5966c', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/service-contracts', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'symfony/var-exporter' => array( + 'pretty_version' => 'v5.4.35', + 'version' => '5.4.35.0', + 'reference' => 'abb0a151b62d6b07e816487e20040464af96cae7', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/var-exporter', + 'aliases' => array(), + 'dev_requirement' => false, + ), + ), +); diff --git a/advancedcontentfilter/vendor/composer/platform_check.php b/advancedcontentfilter/vendor/composer/platform_check.php new file mode 100644 index 000000000..580fa9609 --- /dev/null +++ b/advancedcontentfilter/vendor/composer/platform_check.php @@ -0,0 +1,26 @@ += 70400)) { + $issues[] = 'Your Composer dependencies require a PHP version ">= 7.4.0". You are running ' . PHP_VERSION . '.'; +} + +if ($issues) { + if (!headers_sent()) { + header('HTTP/1.1 500 Internal Server Error'); + } + if (!ini_get('display_errors')) { + if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') { + fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL); + } elseif (!headers_sent()) { + echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL; + } + } + trigger_error( + 'Composer detected issues in your platform: ' . implode(' ', $issues), + E_USER_ERROR + ); +} diff --git a/advancedcontentfilter/vendor/psr/simple-cache/.editorconfig b/advancedcontentfilter/vendor/psr/simple-cache/.editorconfig deleted file mode 100644 index 48542cbb4..000000000 --- a/advancedcontentfilter/vendor/psr/simple-cache/.editorconfig +++ /dev/null @@ -1,12 +0,0 @@ -; This file is for unifying the coding style for different editors and IDEs. -; More information at http://editorconfig.org - -root = true - -[*] -charset = utf-8 -indent_size = 4 -indent_style = space -end_of_line = lf -insert_final_newline = true -trim_trailing_whitespace = true diff --git a/advancedcontentfilter/vendor/psr/simple-cache/LICENSE.md b/advancedcontentfilter/vendor/psr/simple-cache/LICENSE.md deleted file mode 100644 index e49a7c85a..000000000 --- a/advancedcontentfilter/vendor/psr/simple-cache/LICENSE.md +++ /dev/null @@ -1,21 +0,0 @@ -# The MIT License (MIT) - -Copyright (c) 2016 PHP Framework Interoperability Group - -> Permission is hereby granted, free of charge, to any person obtaining a copy -> of this software and associated documentation files (the "Software"), to deal -> in the Software without restriction, including without limitation the rights -> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -> copies of the Software, and to permit persons to whom the Software is -> furnished to do so, subject to the following conditions: -> -> The above copyright notice and this permission notice shall be included in -> all copies or substantial portions of the Software. -> -> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -> THE SOFTWARE. diff --git a/advancedcontentfilter/vendor/psr/simple-cache/README.md b/advancedcontentfilter/vendor/psr/simple-cache/README.md deleted file mode 100644 index 43641d175..000000000 --- a/advancedcontentfilter/vendor/psr/simple-cache/README.md +++ /dev/null @@ -1,8 +0,0 @@ -PHP FIG Simple Cache PSR -======================== - -This repository holds all interfaces related to PSR-16. - -Note that this is not a cache implementation of its own. It is merely an interface that describes a cache implementation. See [the specification](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-16-simple-cache.md) for more details. - -You can find implementations of the specification by looking for packages providing the [psr/simple-cache-implementation](https://packagist.org/providers/psr/simple-cache-implementation) virtual package. diff --git a/advancedcontentfilter/vendor/psr/simple-cache/composer.json b/advancedcontentfilter/vendor/psr/simple-cache/composer.json deleted file mode 100644 index 2978fa559..000000000 --- a/advancedcontentfilter/vendor/psr/simple-cache/composer.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "psr/simple-cache", - "description": "Common interfaces for simple caching", - "keywords": ["psr", "psr-16", "cache", "simple-cache", "caching"], - "license": "MIT", - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "require": { - "php": ">=5.3.0" - }, - "autoload": { - "psr-4": { - "Psr\\SimpleCache\\": "src/" - } - }, - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - } -} diff --git a/advancedcontentfilter/vendor/psr/simple-cache/src/CacheException.php b/advancedcontentfilter/vendor/psr/simple-cache/src/CacheException.php deleted file mode 100644 index eba53815c..000000000 --- a/advancedcontentfilter/vendor/psr/simple-cache/src/CacheException.php +++ /dev/null @@ -1,10 +0,0 @@ - value pairs. Cache keys that do not exist or are stale will have $default as value. - * - * @throws \Psr\SimpleCache\InvalidArgumentException - * MUST be thrown if $keys is neither an array nor a Traversable, - * or if any of the $keys are not a legal value. - */ - public function getMultiple($keys, $default = null); - - /** - * Persists a set of key => value pairs in the cache, with an optional TTL. - * - * @param iterable $values A list of key => value pairs for a multiple-set operation. - * @param null|int|\DateInterval $ttl Optional. The TTL value of this item. If no value is sent and - * the driver supports TTL then the library may set a default value - * for it or let the driver take care of that. - * - * @return bool True on success and false on failure. - * - * @throws \Psr\SimpleCache\InvalidArgumentException - * MUST be thrown if $values is neither an array nor a Traversable, - * or if any of the $values are not a legal value. - */ - public function setMultiple($values, $ttl = null); - - /** - * Deletes multiple cache items in a single operation. - * - * @param iterable $keys A list of string-based keys to be deleted. - * - * @return bool True if the items were successfully removed. False if there was an error. - * - * @throws \Psr\SimpleCache\InvalidArgumentException - * MUST be thrown if $keys is neither an array nor a Traversable, - * or if any of the $keys are not a legal value. - */ - public function deleteMultiple($keys); - - /** - * Determines whether an item is present in the cache. - * - * NOTE: It is recommended that has() is only to be used for cache warming type purposes - * and not to be used within your live applications operations for get/set, as this method - * is subject to a race condition where your has() will return true and immediately after, - * another script can remove it making the state of your app out of date. - * - * @param string $key The cache item key. - * - * @return bool - * - * @throws \Psr\SimpleCache\InvalidArgumentException - * MUST be thrown if the $key string is not a legal value. - */ - public function has($key); -} diff --git a/advancedcontentfilter/vendor/psr/simple-cache/src/InvalidArgumentException.php b/advancedcontentfilter/vendor/psr/simple-cache/src/InvalidArgumentException.php deleted file mode 100644 index 6a9524a20..000000000 --- a/advancedcontentfilter/vendor/psr/simple-cache/src/InvalidArgumentException.php +++ /dev/null @@ -1,13 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use Symfony\Component\Cache\Adapter\RedisAdapter; - -abstract class AbstractRedisAdapterTest extends AdapterTestCase -{ - protected $skippedTests = [ - 'testExpiration' => 'Testing expiration slows down the test suite', - 'testHasItemReturnsFalseWhenDeferredItemIsExpired' => 'Testing expiration slows down the test suite', - 'testDefaultLifeTime' => 'Testing expiration slows down the test suite', - ]; - - protected static $redis; - - public function createCachePool($defaultLifetime = 0) - { - return new RedisAdapter(self::$redis, str_replace('\\', '.', __CLASS__), $defaultLifetime); - } - - public static function setUpBeforeClass() - { - if (!\extension_loaded('redis')) { - self::markTestSkipped('Extension redis required.'); - } - try { - (new \Redis())->connect(getenv('REDIS_HOST')); - } catch (\Exception $e) { - self::markTestSkipped($e->getMessage()); - } - } - - public static function tearDownAfterClass() - { - self::$redis = null; - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/AdapterTestCase.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/AdapterTestCase.php deleted file mode 100644 index 5758a2861..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/AdapterTestCase.php +++ /dev/null @@ -1,175 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use Cache\IntegrationTests\CachePoolTest; -use Psr\Cache\CacheItemPoolInterface; -use Symfony\Component\Cache\PruneableInterface; - -abstract class AdapterTestCase extends CachePoolTest -{ - protected function setUp() - { - parent::setUp(); - - if (!\array_key_exists('testDeferredSaveWithoutCommit', $this->skippedTests) && \defined('HHVM_VERSION')) { - $this->skippedTests['testDeferredSaveWithoutCommit'] = 'Destructors are called late on HHVM.'; - } - - if (!\array_key_exists('testPrune', $this->skippedTests) && !$this->createCachePool() instanceof PruneableInterface) { - $this->skippedTests['testPrune'] = 'Not a pruneable cache pool.'; - } - } - - public function testDefaultLifeTime() - { - if (isset($this->skippedTests[__FUNCTION__])) { - $this->markTestSkipped($this->skippedTests[__FUNCTION__]); - } - - $cache = $this->createCachePool(2); - - $item = $cache->getItem('key.dlt'); - $item->set('value'); - $cache->save($item); - sleep(1); - - $item = $cache->getItem('key.dlt'); - $this->assertTrue($item->isHit()); - - sleep(2); - $item = $cache->getItem('key.dlt'); - $this->assertFalse($item->isHit()); - } - - public function testExpiration() - { - if (isset($this->skippedTests[__FUNCTION__])) { - $this->markTestSkipped($this->skippedTests[__FUNCTION__]); - } - - $cache = $this->createCachePool(); - $cache->save($cache->getItem('k1')->set('v1')->expiresAfter(2)); - $cache->save($cache->getItem('k2')->set('v2')->expiresAfter(366 * 86400)); - - sleep(3); - $item = $cache->getItem('k1'); - $this->assertFalse($item->isHit()); - $this->assertNull($item->get(), "Item's value must be null when isHit() is false."); - - $item = $cache->getItem('k2'); - $this->assertTrue($item->isHit()); - $this->assertSame('v2', $item->get()); - } - - public function testNotUnserializable() - { - if (isset($this->skippedTests[__FUNCTION__])) { - $this->markTestSkipped($this->skippedTests[__FUNCTION__]); - } - - $cache = $this->createCachePool(); - - $item = $cache->getItem('foo'); - $cache->save($item->set(new NotUnserializable())); - - $item = $cache->getItem('foo'); - $this->assertFalse($item->isHit()); - - foreach ($cache->getItems(['foo']) as $item) { - } - $cache->save($item->set(new NotUnserializable())); - - foreach ($cache->getItems(['foo']) as $item) { - } - $this->assertFalse($item->isHit()); - } - - public function testPrune() - { - if (isset($this->skippedTests[__FUNCTION__])) { - $this->markTestSkipped($this->skippedTests[__FUNCTION__]); - } - - if (!method_exists($this, 'isPruned')) { - $this->fail('Test classes for pruneable caches must implement `isPruned($cache, $name)` method.'); - } - - /** @var PruneableInterface|CacheItemPoolInterface $cache */ - $cache = $this->createCachePool(); - - $doSet = function ($name, $value, \DateInterval $expiresAfter = null) use ($cache) { - $item = $cache->getItem($name); - $item->set($value); - - if ($expiresAfter) { - $item->expiresAfter($expiresAfter); - } - - $cache->save($item); - }; - - $doSet('foo', 'foo-val', new \DateInterval('PT05S')); - $doSet('bar', 'bar-val', new \DateInterval('PT10S')); - $doSet('baz', 'baz-val', new \DateInterval('PT15S')); - $doSet('qux', 'qux-val', new \DateInterval('PT20S')); - - sleep(30); - $cache->prune(); - $this->assertTrue($this->isPruned($cache, 'foo')); - $this->assertTrue($this->isPruned($cache, 'bar')); - $this->assertTrue($this->isPruned($cache, 'baz')); - $this->assertTrue($this->isPruned($cache, 'qux')); - - $doSet('foo', 'foo-val'); - $doSet('bar', 'bar-val', new \DateInterval('PT20S')); - $doSet('baz', 'baz-val', new \DateInterval('PT40S')); - $doSet('qux', 'qux-val', new \DateInterval('PT80S')); - - $cache->prune(); - $this->assertFalse($this->isPruned($cache, 'foo')); - $this->assertFalse($this->isPruned($cache, 'bar')); - $this->assertFalse($this->isPruned($cache, 'baz')); - $this->assertFalse($this->isPruned($cache, 'qux')); - - sleep(30); - $cache->prune(); - $this->assertFalse($this->isPruned($cache, 'foo')); - $this->assertTrue($this->isPruned($cache, 'bar')); - $this->assertFalse($this->isPruned($cache, 'baz')); - $this->assertFalse($this->isPruned($cache, 'qux')); - - sleep(30); - $cache->prune(); - $this->assertFalse($this->isPruned($cache, 'foo')); - $this->assertTrue($this->isPruned($cache, 'baz')); - $this->assertFalse($this->isPruned($cache, 'qux')); - - sleep(30); - $cache->prune(); - $this->assertFalse($this->isPruned($cache, 'foo')); - $this->assertTrue($this->isPruned($cache, 'qux')); - } -} - -class NotUnserializable implements \Serializable -{ - public function serialize() - { - return serialize(123); - } - - public function unserialize($ser) - { - throw new \Exception(__CLASS__); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ApcuAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ApcuAdapterTest.php deleted file mode 100644 index f55a1b9b8..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ApcuAdapterTest.php +++ /dev/null @@ -1,124 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use Psr\Log\NullLogger; -use Symfony\Component\Cache\Adapter\ApcuAdapter; - -class ApcuAdapterTest extends AdapterTestCase -{ - protected $skippedTests = [ - 'testExpiration' => 'Testing expiration slows down the test suite', - 'testHasItemReturnsFalseWhenDeferredItemIsExpired' => 'Testing expiration slows down the test suite', - 'testDefaultLifeTime' => 'Testing expiration slows down the test suite', - ]; - - public function createCachePool($defaultLifetime = 0) - { - if (!\function_exists('apcu_fetch') || !filter_var(ini_get('apc.enabled'), \FILTER_VALIDATE_BOOLEAN)) { - $this->markTestSkipped('APCu extension is required.'); - } - if ('cli' === \PHP_SAPI && !filter_var(ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOLEAN)) { - if ('testWithCliSapi' !== $this->getName()) { - $this->markTestSkipped('apc.enable_cli=1 is required.'); - } - } - if ('\\' === \DIRECTORY_SEPARATOR) { - $this->markTestSkipped('Fails transiently on Windows.'); - } - - return new ApcuAdapter(str_replace('\\', '.', __CLASS__), $defaultLifetime); - } - - public function testUnserializable() - { - $pool = $this->createCachePool(); - - $item = $pool->getItem('foo'); - $item->set(function () {}); - - $this->assertFalse($pool->save($item)); - - $item = $pool->getItem('foo'); - $this->assertFalse($item->isHit()); - } - - public function testVersion() - { - $namespace = str_replace('\\', '.', static::class); - - $pool1 = new ApcuAdapter($namespace, 0, 'p1'); - - $item = $pool1->getItem('foo'); - $this->assertFalse($item->isHit()); - $this->assertTrue($pool1->save($item->set('bar'))); - - $item = $pool1->getItem('foo'); - $this->assertTrue($item->isHit()); - $this->assertSame('bar', $item->get()); - - $pool2 = new ApcuAdapter($namespace, 0, 'p2'); - - $item = $pool2->getItem('foo'); - $this->assertFalse($item->isHit()); - $this->assertNull($item->get()); - - $item = $pool1->getItem('foo'); - $this->assertFalse($item->isHit()); - $this->assertNull($item->get()); - } - - public function testNamespace() - { - $namespace = str_replace('\\', '.', static::class); - - $pool1 = new ApcuAdapter($namespace.'_1', 0, 'p1'); - - $item = $pool1->getItem('foo'); - $this->assertFalse($item->isHit()); - $this->assertTrue($pool1->save($item->set('bar'))); - - $item = $pool1->getItem('foo'); - $this->assertTrue($item->isHit()); - $this->assertSame('bar', $item->get()); - - $pool2 = new ApcuAdapter($namespace.'_2', 0, 'p1'); - - $item = $pool2->getItem('foo'); - $this->assertFalse($item->isHit()); - $this->assertNull($item->get()); - - $item = $pool1->getItem('foo'); - $this->assertTrue($item->isHit()); - $this->assertSame('bar', $item->get()); - } - - public function testWithCliSapi() - { - try { - // disable PHPUnit error handler to mimic a production environment - $isCalled = false; - set_error_handler(function () use (&$isCalled) { - $isCalled = true; - }); - $pool = new ApcuAdapter(str_replace('\\', '.', __CLASS__)); - $pool->setLogger(new NullLogger()); - - $item = $pool->getItem('foo'); - $item->isHit(); - $pool->save($item->set('bar')); - $this->assertFalse($isCalled); - } finally { - restore_error_handler(); - } - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ArrayAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ArrayAdapterTest.php deleted file mode 100644 index e6adc9d01..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ArrayAdapterTest.php +++ /dev/null @@ -1,56 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use Symfony\Component\Cache\Adapter\ArrayAdapter; - -/** - * @group time-sensitive - */ -class ArrayAdapterTest extends AdapterTestCase -{ - protected $skippedTests = [ - 'testDeferredSaveWithoutCommit' => 'Assumes a shared cache which ArrayAdapter is not.', - 'testSaveWithoutExpire' => 'Assumes a shared cache which ArrayAdapter is not.', - ]; - - public function createCachePool($defaultLifetime = 0) - { - return new ArrayAdapter($defaultLifetime); - } - - public function testGetValuesHitAndMiss() - { - /** @var ArrayAdapter $cache */ - $cache = $this->createCachePool(); - - // Hit - $item = $cache->getItem('foo'); - $item->set('4711'); - $cache->save($item); - - $fooItem = $cache->getItem('foo'); - $this->assertTrue($fooItem->isHit()); - $this->assertEquals('4711', $fooItem->get()); - - // Miss (should be present as NULL in $values) - $cache->getItem('bar'); - - $values = $cache->getValues(); - - $this->assertCount(2, $values); - $this->assertArrayHasKey('foo', $values); - $this->assertSame(serialize('4711'), $values['foo']); - $this->assertArrayHasKey('bar', $values); - $this->assertNull($values['bar']); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ChainAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ChainAdapterTest.php deleted file mode 100644 index be811d6fd..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ChainAdapterTest.php +++ /dev/null @@ -1,233 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use PHPUnit\Framework\MockObject\MockObject; -use Symfony\Component\Cache\Adapter\AdapterInterface; -use Symfony\Component\Cache\Adapter\ArrayAdapter; -use Symfony\Component\Cache\Adapter\ChainAdapter; -use Symfony\Component\Cache\Adapter\FilesystemAdapter; -use Symfony\Component\Cache\PruneableInterface; -use Symfony\Component\Cache\Tests\Fixtures\ExternalAdapter; - -/** - * @author Kévin Dunglas - * @group time-sensitive - */ -class ChainAdapterTest extends AdapterTestCase -{ - public function createCachePool($defaultLifetime = 0) - { - return new ChainAdapter([new ArrayAdapter($defaultLifetime), new ExternalAdapter($defaultLifetime), new FilesystemAdapter('', $defaultLifetime)], $defaultLifetime); - } - - public function testEmptyAdaptersException() - { - $this->expectException('Symfony\Component\Cache\Exception\InvalidArgumentException'); - $this->expectExceptionMessage('At least one adapter must be specified.'); - new ChainAdapter([]); - } - - public function testInvalidAdapterException() - { - $this->expectException('Symfony\Component\Cache\Exception\InvalidArgumentException'); - $this->expectExceptionMessage('The class "stdClass" does not implement'); - new ChainAdapter([new \stdClass()]); - } - - public function testPrune() - { - if (isset($this->skippedTests[__FUNCTION__])) { - $this->markTestSkipped($this->skippedTests[__FUNCTION__]); - } - - $cache = new ChainAdapter([ - $this->getPruneableMock(), - $this->getNonPruneableMock(), - $this->getPruneableMock(), - ]); - $this->assertTrue($cache->prune()); - - $cache = new ChainAdapter([ - $this->getPruneableMock(), - $this->getFailingPruneableMock(), - $this->getPruneableMock(), - ]); - $this->assertFalse($cache->prune()); - } - - public function testMultipleCachesExpirationWhenCommonTtlIsNotSet() - { - if (isset($this->skippedTests[__FUNCTION__])) { - $this->markTestSkipped($this->skippedTests[__FUNCTION__]); - } - - $adapter1 = new ArrayAdapter(4); - $adapter2 = new ArrayAdapter(2); - - $cache = new ChainAdapter([$adapter1, $adapter2]); - - $cache->save($cache->getItem('key')->set('value')); - - $item = $adapter1->getItem('key'); - $this->assertTrue($item->isHit()); - $this->assertEquals('value', $item->get()); - - $item = $adapter2->getItem('key'); - $this->assertTrue($item->isHit()); - $this->assertEquals('value', $item->get()); - - sleep(2); - - $item = $adapter1->getItem('key'); - $this->assertTrue($item->isHit()); - $this->assertEquals('value', $item->get()); - - $item = $adapter2->getItem('key'); - $this->assertFalse($item->isHit()); - - sleep(2); - - $item = $adapter1->getItem('key'); - $this->assertFalse($item->isHit()); - - $adapter2->save($adapter2->getItem('key1')->set('value1')); - - $item = $cache->getItem('key1'); - $this->assertTrue($item->isHit()); - $this->assertEquals('value1', $item->get()); - - sleep(2); - - $item = $adapter1->getItem('key1'); - $this->assertTrue($item->isHit()); - $this->assertEquals('value1', $item->get()); - - $item = $adapter2->getItem('key1'); - $this->assertFalse($item->isHit()); - - sleep(2); - - $item = $adapter1->getItem('key1'); - $this->assertFalse($item->isHit()); - } - - public function testMultipleCachesExpirationWhenCommonTtlIsSet() - { - if (isset($this->skippedTests[__FUNCTION__])) { - $this->markTestSkipped($this->skippedTests[__FUNCTION__]); - } - - $adapter1 = new ArrayAdapter(4); - $adapter2 = new ArrayAdapter(2); - - $cache = new ChainAdapter([$adapter1, $adapter2], 6); - - $cache->save($cache->getItem('key')->set('value')); - - $item = $adapter1->getItem('key'); - $this->assertTrue($item->isHit()); - $this->assertEquals('value', $item->get()); - - $item = $adapter2->getItem('key'); - $this->assertTrue($item->isHit()); - $this->assertEquals('value', $item->get()); - - sleep(2); - - $item = $adapter1->getItem('key'); - $this->assertTrue($item->isHit()); - $this->assertEquals('value', $item->get()); - - $item = $adapter2->getItem('key'); - $this->assertFalse($item->isHit()); - - sleep(2); - - $item = $adapter1->getItem('key'); - $this->assertFalse($item->isHit()); - - $adapter2->save($adapter2->getItem('key1')->set('value1')); - - $item = $cache->getItem('key1'); - $this->assertTrue($item->isHit()); - $this->assertEquals('value1', $item->get()); - - sleep(2); - - $item = $adapter1->getItem('key1'); - $this->assertTrue($item->isHit()); - $this->assertEquals('value1', $item->get()); - - $item = $adapter2->getItem('key1'); - $this->assertFalse($item->isHit()); - - sleep(2); - - $item = $adapter1->getItem('key1'); - $this->assertTrue($item->isHit()); - $this->assertEquals('value1', $item->get()); - - sleep(2); - - $item = $adapter1->getItem('key1'); - $this->assertFalse($item->isHit()); - } - - /** - * @return MockObject|PruneableCacheInterface - */ - private function getPruneableMock() - { - $pruneable = $this - ->getMockBuilder(PruneableCacheInterface::class) - ->getMock(); - - $pruneable - ->expects($this->atLeastOnce()) - ->method('prune') - ->willReturn(true); - - return $pruneable; - } - - /** - * @return MockObject|PruneableCacheInterface - */ - private function getFailingPruneableMock() - { - $pruneable = $this - ->getMockBuilder(PruneableCacheInterface::class) - ->getMock(); - - $pruneable - ->expects($this->atLeastOnce()) - ->method('prune') - ->willReturn(false); - - return $pruneable; - } - - /** - * @return MockObject|AdapterInterface - */ - private function getNonPruneableMock() - { - return $this - ->getMockBuilder(AdapterInterface::class) - ->getMock(); - } -} - -interface PruneableCacheInterface extends PruneableInterface, AdapterInterface -{ -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/DoctrineAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/DoctrineAdapterTest.php deleted file mode 100644 index 8f520cb59..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/DoctrineAdapterTest.php +++ /dev/null @@ -1,32 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use Symfony\Component\Cache\Adapter\DoctrineAdapter; -use Symfony\Component\Cache\Tests\Fixtures\ArrayCache; - -/** - * @group time-sensitive - */ -class DoctrineAdapterTest extends AdapterTestCase -{ - protected $skippedTests = [ - 'testDeferredSaveWithoutCommit' => 'Assumes a shared cache which ArrayCache is not.', - 'testSaveWithoutExpire' => 'Assumes a shared cache which ArrayCache is not.', - 'testNotUnserializable' => 'ArrayCache does not use serialize/unserialize', - ]; - - public function createCachePool($defaultLifetime = 0) - { - return new DoctrineAdapter(new ArrayCache($defaultLifetime), '', $defaultLifetime); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/FilesystemAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/FilesystemAdapterTest.php deleted file mode 100644 index fa8306826..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/FilesystemAdapterTest.php +++ /dev/null @@ -1,61 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use Psr\Cache\CacheItemPoolInterface; -use Symfony\Component\Cache\Adapter\FilesystemAdapter; - -/** - * @group time-sensitive - */ -class FilesystemAdapterTest extends AdapterTestCase -{ - public function createCachePool($defaultLifetime = 0) - { - return new FilesystemAdapter('', $defaultLifetime); - } - - public static function tearDownAfterClass() - { - self::rmdir(sys_get_temp_dir().'/symfony-cache'); - } - - public static function rmdir($dir) - { - if (!file_exists($dir)) { - return; - } - if (!$dir || 0 !== strpos(\dirname($dir), sys_get_temp_dir())) { - throw new \Exception(__METHOD__."() operates only on subdirs of system's temp dir"); - } - $children = new \RecursiveIteratorIterator( - new \RecursiveDirectoryIterator($dir, \RecursiveDirectoryIterator::SKIP_DOTS), - \RecursiveIteratorIterator::CHILD_FIRST - ); - foreach ($children as $child) { - if ($child->isDir()) { - rmdir($child); - } else { - unlink($child); - } - } - rmdir($dir); - } - - protected function isPruned(CacheItemPoolInterface $cache, $name) - { - $getFileMethod = (new \ReflectionObject($cache))->getMethod('getFile'); - $getFileMethod->setAccessible(true); - - return !file_exists($getFileMethod->invoke($cache, $name)); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/MaxIdLengthAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/MaxIdLengthAdapterTest.php deleted file mode 100644 index 536e2c2d4..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/MaxIdLengthAdapterTest.php +++ /dev/null @@ -1,87 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Cache\Adapter\AbstractAdapter; - -class MaxIdLengthAdapterTest extends TestCase -{ - public function testLongKey() - { - $cache = $this->getMockBuilder(MaxIdLengthAdapter::class) - ->setConstructorArgs([str_repeat('-', 10)]) - ->setMethods(['doHave', 'doFetch', 'doDelete', 'doSave', 'doClear']) - ->getMock(); - - $cache->expects($this->exactly(2)) - ->method('doHave') - ->withConsecutive( - [$this->equalTo('----------:0GTYWa9n4ed8vqNlOT2iEr:')], - [$this->equalTo('----------:---------------------------------------')] - ); - - $cache->hasItem(str_repeat('-', 40)); - $cache->hasItem(str_repeat('-', 39)); - } - - public function testLongKeyVersioning() - { - $cache = $this->getMockBuilder(MaxIdLengthAdapter::class) - ->setConstructorArgs([str_repeat('-', 26)]) - ->getMock(); - - $cache - ->method('doFetch') - ->willReturn(['2:']); - - $reflectionClass = new \ReflectionClass(AbstractAdapter::class); - - $reflectionMethod = $reflectionClass->getMethod('getId'); - $reflectionMethod->setAccessible(true); - - // No versioning enabled - $this->assertEquals('--------------------------:------------', $reflectionMethod->invokeArgs($cache, [str_repeat('-', 12)])); - $this->assertLessThanOrEqual(50, \strlen($reflectionMethod->invokeArgs($cache, [str_repeat('-', 12)]))); - $this->assertLessThanOrEqual(50, \strlen($reflectionMethod->invokeArgs($cache, [str_repeat('-', 23)]))); - $this->assertLessThanOrEqual(50, \strlen($reflectionMethod->invokeArgs($cache, [str_repeat('-', 40)]))); - - $reflectionProperty = $reflectionClass->getProperty('versioningIsEnabled'); - $reflectionProperty->setAccessible(true); - $reflectionProperty->setValue($cache, true); - - // Versioning enabled - $this->assertEquals('--------------------------:2:------------', $reflectionMethod->invokeArgs($cache, [str_repeat('-', 12)])); - $this->assertLessThanOrEqual(50, \strlen($reflectionMethod->invokeArgs($cache, [str_repeat('-', 12)]))); - $this->assertLessThanOrEqual(50, \strlen($reflectionMethod->invokeArgs($cache, [str_repeat('-', 23)]))); - $this->assertLessThanOrEqual(50, \strlen($reflectionMethod->invokeArgs($cache, [str_repeat('-', 40)]))); - } - - public function testTooLongNamespace() - { - $this->expectException('Symfony\Component\Cache\Exception\InvalidArgumentException'); - $this->expectExceptionMessage('Namespace must be 26 chars max, 40 given ("----------------------------------------")'); - $this->getMockBuilder(MaxIdLengthAdapter::class) - ->setConstructorArgs([str_repeat('-', 40)]) - ->getMock(); - } -} - -abstract class MaxIdLengthAdapter extends AbstractAdapter -{ - protected $maxIdLength = 50; - - public function __construct($ns) - { - parent::__construct($ns); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/MemcachedAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/MemcachedAdapterTest.php deleted file mode 100644 index a9a397dd4..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/MemcachedAdapterTest.php +++ /dev/null @@ -1,204 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use Symfony\Component\Cache\Adapter\AbstractAdapter; -use Symfony\Component\Cache\Adapter\MemcachedAdapter; - -class MemcachedAdapterTest extends AdapterTestCase -{ - protected $skippedTests = [ - 'testHasItemReturnsFalseWhenDeferredItemIsExpired' => 'Testing expiration slows down the test suite', - 'testDefaultLifeTime' => 'Testing expiration slows down the test suite', - ]; - - protected static $client; - - public static function setUpBeforeClass() - { - if (!MemcachedAdapter::isSupported()) { - self::markTestSkipped('Extension memcached >=2.2.0 required.'); - } - self::$client = AbstractAdapter::createConnection('memcached://'.getenv('MEMCACHED_HOST'), ['binary_protocol' => false]); - self::$client->get('foo'); - $code = self::$client->getResultCode(); - - if (\Memcached::RES_SUCCESS !== $code && \Memcached::RES_NOTFOUND !== $code) { - self::markTestSkipped('Memcached error: '.strtolower(self::$client->getResultMessage())); - } - } - - public function createCachePool($defaultLifetime = 0) - { - $client = $defaultLifetime ? AbstractAdapter::createConnection('memcached://'.getenv('MEMCACHED_HOST')) : self::$client; - - return new MemcachedAdapter($client, str_replace('\\', '.', __CLASS__), $defaultLifetime); - } - - public function testOptions() - { - $client = MemcachedAdapter::createConnection([], [ - 'libketama_compatible' => false, - 'distribution' => 'modula', - 'compression' => true, - 'serializer' => 'php', - 'hash' => 'md5', - ]); - - $this->assertSame(\Memcached::SERIALIZER_PHP, $client->getOption(\Memcached::OPT_SERIALIZER)); - $this->assertSame(\Memcached::HASH_MD5, $client->getOption(\Memcached::OPT_HASH)); - $this->assertTrue($client->getOption(\Memcached::OPT_COMPRESSION)); - $this->assertSame(0, $client->getOption(\Memcached::OPT_LIBKETAMA_COMPATIBLE)); - $this->assertSame(\Memcached::DISTRIBUTION_MODULA, $client->getOption(\Memcached::OPT_DISTRIBUTION)); - } - - /** - * @dataProvider provideBadOptions - */ - public function testBadOptions($name, $value) - { - if (\PHP_VERSION_ID < 80000) { - $this->expectException('ErrorException'); - $this->expectExceptionMessage('constant(): Couldn\'t find constant Memcached::'); - } else { - $this->expectException('Error'); - $this->expectExceptionMessage('Undefined constant Memcached::'); - } - - MemcachedAdapter::createConnection([], [$name => $value]); - } - - public function provideBadOptions() - { - return [ - ['foo', 'bar'], - ['hash', 'zyx'], - ['serializer', 'zyx'], - ['distribution', 'zyx'], - ]; - } - - public function testDefaultOptions() - { - $this->assertTrue(MemcachedAdapter::isSupported()); - - $client = MemcachedAdapter::createConnection([]); - - $this->assertTrue($client->getOption(\Memcached::OPT_COMPRESSION)); - $this->assertSame(1, $client->getOption(\Memcached::OPT_BINARY_PROTOCOL)); - $this->assertSame(1, $client->getOption(\Memcached::OPT_TCP_NODELAY)); - $this->assertSame(1, $client->getOption(\Memcached::OPT_LIBKETAMA_COMPATIBLE)); - } - - public function testOptionSerializer() - { - $this->expectException('Symfony\Component\Cache\Exception\CacheException'); - $this->expectExceptionMessage('MemcachedAdapter: "serializer" option must be "php" or "igbinary".'); - if (!\Memcached::HAVE_JSON) { - $this->markTestSkipped('Memcached::HAVE_JSON required'); - } - - new MemcachedAdapter(MemcachedAdapter::createConnection([], ['serializer' => 'json'])); - } - - /** - * @dataProvider provideServersSetting - */ - public function testServersSetting($dsn, $host, $port) - { - $client1 = MemcachedAdapter::createConnection($dsn); - $client2 = MemcachedAdapter::createConnection([$dsn]); - $client3 = MemcachedAdapter::createConnection([[$host, $port]]); - $expect = [ - 'host' => $host, - 'port' => $port, - ]; - - $f = function ($s) { return ['host' => $s['host'], 'port' => $s['port']]; }; - $this->assertSame([$expect], array_map($f, $client1->getServerList())); - $this->assertSame([$expect], array_map($f, $client2->getServerList())); - $this->assertSame([$expect], array_map($f, $client3->getServerList())); - } - - public function provideServersSetting() - { - yield [ - 'memcached://127.0.0.1/50', - '127.0.0.1', - 11211, - ]; - yield [ - 'memcached://localhost:11222?weight=25', - 'localhost', - 11222, - ]; - if (filter_var(ini_get('memcached.use_sasl'), \FILTER_VALIDATE_BOOLEAN)) { - yield [ - 'memcached://user:password@127.0.0.1?weight=50', - '127.0.0.1', - 11211, - ]; - } - yield [ - 'memcached:///var/run/memcached.sock?weight=25', - '/var/run/memcached.sock', - 0, - ]; - yield [ - 'memcached:///var/local/run/memcached.socket?weight=25', - '/var/local/run/memcached.socket', - 0, - ]; - if (filter_var(ini_get('memcached.use_sasl'), \FILTER_VALIDATE_BOOLEAN)) { - yield [ - 'memcached://user:password@/var/local/run/memcached.socket?weight=25', - '/var/local/run/memcached.socket', - 0, - ]; - } - } - - /** - * @dataProvider provideDsnWithOptions - */ - public function testDsnWithOptions($dsn, array $options, array $expectedOptions) - { - $client = MemcachedAdapter::createConnection($dsn, $options); - - foreach ($expectedOptions as $option => $expect) { - $this->assertSame($expect, $client->getOption($option)); - } - } - - public function provideDsnWithOptions() - { - if (!class_exists('\Memcached')) { - self::markTestSkipped('Extension memcached required.'); - } - - yield [ - 'memcached://localhost:11222?retry_timeout=10', - [\Memcached::OPT_RETRY_TIMEOUT => 8], - [\Memcached::OPT_RETRY_TIMEOUT => 10], - ]; - yield [ - 'memcached://localhost:11222?socket_recv_size=1&socket_send_size=2', - [\Memcached::OPT_RETRY_TIMEOUT => 8], - [\Memcached::OPT_SOCKET_RECV_SIZE => 1, \Memcached::OPT_SOCKET_SEND_SIZE => 2, \Memcached::OPT_RETRY_TIMEOUT => 8], - ]; - } - - public function testClear() - { - $this->assertTrue($this->createCachePool()->clear()); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/NamespacedProxyAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/NamespacedProxyAdapterTest.php deleted file mode 100644 index c27140333..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/NamespacedProxyAdapterTest.php +++ /dev/null @@ -1,26 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use Symfony\Component\Cache\Adapter\ArrayAdapter; -use Symfony\Component\Cache\Adapter\ProxyAdapter; - -/** - * @group time-sensitive - */ -class NamespacedProxyAdapterTest extends ProxyAdapterTest -{ - public function createCachePool($defaultLifetime = 0) - { - return new ProxyAdapter(new ArrayAdapter($defaultLifetime), 'foo', $defaultLifetime); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/NullAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/NullAdapterTest.php deleted file mode 100644 index b771fa0ed..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/NullAdapterTest.php +++ /dev/null @@ -1,128 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use PHPUnit\Framework\TestCase; -use Psr\Cache\CacheItemInterface; -use Symfony\Component\Cache\Adapter\NullAdapter; - -/** - * @group time-sensitive - */ -class NullAdapterTest extends TestCase -{ - public function createCachePool() - { - return new NullAdapter(); - } - - public function testGetItem() - { - $adapter = $this->createCachePool(); - - $item = $adapter->getItem('key'); - $this->assertFalse($item->isHit()); - $this->assertNull($item->get(), "Item's value must be null when isHit is false."); - } - - public function testHasItem() - { - $this->assertFalse($this->createCachePool()->hasItem('key')); - } - - public function testGetItems() - { - $adapter = $this->createCachePool(); - - $keys = ['foo', 'bar', 'baz', 'biz']; - - /** @var CacheItemInterface[] $items */ - $items = $adapter->getItems($keys); - $count = 0; - - foreach ($items as $key => $item) { - $itemKey = $item->getKey(); - - $this->assertEquals($itemKey, $key, 'Keys must be preserved when fetching multiple items'); - $this->assertContains($key, $keys, 'Cache key can not change.'); - $this->assertFalse($item->isHit()); - - // Remove $key for $keys - foreach ($keys as $k => $v) { - if ($v === $key) { - unset($keys[$k]); - } - } - - ++$count; - } - - $this->assertSame(4, $count); - } - - public function testIsHit() - { - $adapter = $this->createCachePool(); - - $item = $adapter->getItem('key'); - $this->assertFalse($item->isHit()); - } - - public function testClear() - { - $this->assertTrue($this->createCachePool()->clear()); - } - - public function testDeleteItem() - { - $this->assertTrue($this->createCachePool()->deleteItem('key')); - } - - public function testDeleteItems() - { - $this->assertTrue($this->createCachePool()->deleteItems(['key', 'foo', 'bar'])); - } - - public function testSave() - { - $adapter = $this->createCachePool(); - - $item = $adapter->getItem('key'); - $this->assertFalse($item->isHit()); - $this->assertNull($item->get(), "Item's value must be null when isHit is false."); - - $this->assertFalse($adapter->save($item)); - } - - public function testDeferredSave() - { - $adapter = $this->createCachePool(); - - $item = $adapter->getItem('key'); - $this->assertFalse($item->isHit()); - $this->assertNull($item->get(), "Item's value must be null when isHit is false."); - - $this->assertFalse($adapter->saveDeferred($item)); - } - - public function testCommit() - { - $adapter = $this->createCachePool(); - - $item = $adapter->getItem('key'); - $this->assertFalse($item->isHit()); - $this->assertNull($item->get(), "Item's value must be null when isHit is false."); - - $this->assertFalse($adapter->saveDeferred($item)); - $this->assertFalse($this->createCachePool()->commit()); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PdoAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PdoAdapterTest.php deleted file mode 100644 index dd2a91185..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PdoAdapterTest.php +++ /dev/null @@ -1,73 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use Symfony\Component\Cache\Adapter\PdoAdapter; -use Symfony\Component\Cache\Tests\Traits\PdoPruneableTrait; - -/** - * @group time-sensitive - */ -class PdoAdapterTest extends AdapterTestCase -{ - use PdoPruneableTrait; - - protected static $dbFile; - - public static function setUpBeforeClass() - { - if (!\extension_loaded('pdo_sqlite')) { - self::markTestSkipped('Extension pdo_sqlite required.'); - } - - self::$dbFile = tempnam(sys_get_temp_dir(), 'sf_sqlite_cache'); - - $pool = new PdoAdapter('sqlite:'.self::$dbFile); - $pool->createTable(); - } - - public static function tearDownAfterClass() - { - @unlink(self::$dbFile); - } - - public function createCachePool($defaultLifetime = 0) - { - return new PdoAdapter('sqlite:'.self::$dbFile, 'ns', $defaultLifetime); - } - - public function testCleanupExpiredItems() - { - $pdo = new \PDO('sqlite:'.self::$dbFile); - - $getCacheItemCount = function () use ($pdo) { - return (int) $pdo->query('SELECT COUNT(*) FROM cache_items')->fetch(\PDO::FETCH_COLUMN); - }; - - $this->assertSame(0, $getCacheItemCount()); - - $cache = $this->createCachePool(); - - $item = $cache->getItem('some_nice_key'); - $item->expiresAfter(1); - $item->set(1); - - $cache->save($item); - $this->assertSame(1, $getCacheItemCount()); - - sleep(2); - - $newItem = $cache->getItem($item->getKey()); - $this->assertFalse($newItem->isHit()); - $this->assertSame(0, $getCacheItemCount(), 'PDOAdapter must clean up expired items'); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PdoDbalAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PdoDbalAdapterTest.php deleted file mode 100644 index aa53958cf..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PdoDbalAdapterTest.php +++ /dev/null @@ -1,48 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use Doctrine\DBAL\DriverManager; -use Symfony\Component\Cache\Adapter\PdoAdapter; -use Symfony\Component\Cache\Tests\Traits\PdoPruneableTrait; - -/** - * @group time-sensitive - */ -class PdoDbalAdapterTest extends AdapterTestCase -{ - use PdoPruneableTrait; - - protected static $dbFile; - - public static function setUpBeforeClass() - { - if (!\extension_loaded('pdo_sqlite')) { - self::markTestSkipped('Extension pdo_sqlite required.'); - } - - self::$dbFile = tempnam(sys_get_temp_dir(), 'sf_sqlite_cache'); - - $pool = new PdoAdapter(DriverManager::getConnection(['driver' => 'pdo_sqlite', 'path' => self::$dbFile])); - $pool->createTable(); - } - - public static function tearDownAfterClass() - { - @unlink(self::$dbFile); - } - - public function createCachePool($defaultLifetime = 0) - { - return new PdoAdapter(DriverManager::getConnection(['driver' => 'pdo_sqlite', 'path' => self::$dbFile]), '', $defaultLifetime); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PhpArrayAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PhpArrayAdapterTest.php deleted file mode 100644 index f88a71873..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PhpArrayAdapterTest.php +++ /dev/null @@ -1,135 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use Psr\Cache\CacheItemInterface; -use Symfony\Component\Cache\Adapter\NullAdapter; -use Symfony\Component\Cache\Adapter\PhpArrayAdapter; - -/** - * @group time-sensitive - */ -class PhpArrayAdapterTest extends AdapterTestCase -{ - protected $skippedTests = [ - 'testBasicUsage' => 'PhpArrayAdapter is read-only.', - 'testBasicUsageWithLongKey' => 'PhpArrayAdapter is read-only.', - 'testClear' => 'PhpArrayAdapter is read-only.', - 'testClearWithDeferredItems' => 'PhpArrayAdapter is read-only.', - 'testDeleteItem' => 'PhpArrayAdapter is read-only.', - 'testSaveExpired' => 'PhpArrayAdapter is read-only.', - 'testSaveWithoutExpire' => 'PhpArrayAdapter is read-only.', - 'testDeferredSave' => 'PhpArrayAdapter is read-only.', - 'testDeferredSaveWithoutCommit' => 'PhpArrayAdapter is read-only.', - 'testDeleteItems' => 'PhpArrayAdapter is read-only.', - 'testDeleteDeferredItem' => 'PhpArrayAdapter is read-only.', - 'testCommit' => 'PhpArrayAdapter is read-only.', - 'testSaveDeferredWhenChangingValues' => 'PhpArrayAdapter is read-only.', - 'testSaveDeferredOverwrite' => 'PhpArrayAdapter is read-only.', - 'testIsHitDeferred' => 'PhpArrayAdapter is read-only.', - - 'testExpiresAt' => 'PhpArrayAdapter does not support expiration.', - 'testExpiresAtWithNull' => 'PhpArrayAdapter does not support expiration.', - 'testExpiresAfterWithNull' => 'PhpArrayAdapter does not support expiration.', - 'testDeferredExpired' => 'PhpArrayAdapter does not support expiration.', - 'testExpiration' => 'PhpArrayAdapter does not support expiration.', - - 'testGetItemInvalidKeys' => 'PhpArrayAdapter does not throw exceptions on invalid key.', - 'testGetItemsInvalidKeys' => 'PhpArrayAdapter does not throw exceptions on invalid key.', - 'testHasItemInvalidKeys' => 'PhpArrayAdapter does not throw exceptions on invalid key.', - 'testDeleteItemInvalidKeys' => 'PhpArrayAdapter does not throw exceptions on invalid key.', - 'testDeleteItemsInvalidKeys' => 'PhpArrayAdapter does not throw exceptions on invalid key.', - - 'testDefaultLifeTime' => 'PhpArrayAdapter does not allow configuring a default lifetime.', - 'testPrune' => 'PhpArrayAdapter just proxies', - ]; - - protected static $file; - - public static function setUpBeforeClass() - { - self::$file = sys_get_temp_dir().'/symfony-cache/php-array-adapter-test.php'; - } - - protected function tearDown() - { - $this->createCachePool()->clear(); - - if (file_exists(sys_get_temp_dir().'/symfony-cache')) { - FilesystemAdapterTest::rmdir(sys_get_temp_dir().'/symfony-cache'); - } - } - - public function createCachePool() - { - return new PhpArrayAdapterWrapper(self::$file, new NullAdapter()); - } - - public function testStore() - { - $arrayWithRefs = []; - $arrayWithRefs[0] = 123; - $arrayWithRefs[1] = &$arrayWithRefs[0]; - - $object = (object) [ - 'foo' => 'bar', - 'foo2' => 'bar2', - ]; - - $expected = [ - 'null' => null, - 'serializedString' => serialize($object), - 'arrayWithRefs' => $arrayWithRefs, - 'object' => $object, - 'arrayWithObject' => ['bar' => $object], - ]; - - $adapter = $this->createCachePool(); - $adapter->warmUp($expected); - - foreach ($expected as $key => $value) { - $this->assertSame(serialize($value), serialize($adapter->getItem($key)->get()), 'Warm up should create a PHP file that OPCache can load in memory'); - } - } - - public function testStoredFile() - { - $expected = [ - 'integer' => 42, - 'float' => 42.42, - 'boolean' => true, - 'array_simple' => ['foo', 'bar'], - 'array_associative' => ['foo' => 'bar', 'foo2' => 'bar2'], - ]; - - $adapter = $this->createCachePool(); - $adapter->warmUp($expected); - - $values = eval(substr(file_get_contents(self::$file), 6)); - - $this->assertSame($expected, $values, 'Warm up should create a PHP file that OPCache can load in memory'); - } -} - -class PhpArrayAdapterWrapper extends PhpArrayAdapter -{ - public function save(CacheItemInterface $item) - { - \call_user_func(\Closure::bind(function () use ($item) { - $this->values[$item->getKey()] = $item->get(); - $this->warmUp($this->values); - $this->values = eval(substr(file_get_contents($this->file), 6)); - }, $this, PhpArrayAdapter::class)); - - return true; - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PhpArrayAdapterWithFallbackTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PhpArrayAdapterWithFallbackTest.php deleted file mode 100644 index 0bfd5c394..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PhpArrayAdapterWithFallbackTest.php +++ /dev/null @@ -1,51 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use Symfony\Component\Cache\Adapter\FilesystemAdapter; -use Symfony\Component\Cache\Adapter\PhpArrayAdapter; - -/** - * @group time-sensitive - */ -class PhpArrayAdapterWithFallbackTest extends AdapterTestCase -{ - protected $skippedTests = [ - 'testGetItemInvalidKeys' => 'PhpArrayAdapter does not throw exceptions on invalid key.', - 'testGetItemsInvalidKeys' => 'PhpArrayAdapter does not throw exceptions on invalid key.', - 'testHasItemInvalidKeys' => 'PhpArrayAdapter does not throw exceptions on invalid key.', - 'testDeleteItemInvalidKeys' => 'PhpArrayAdapter does not throw exceptions on invalid key.', - 'testDeleteItemsInvalidKeys' => 'PhpArrayAdapter does not throw exceptions on invalid key.', - 'testPrune' => 'PhpArrayAdapter just proxies', - ]; - - protected static $file; - - public static function setUpBeforeClass() - { - self::$file = sys_get_temp_dir().'/symfony-cache/php-array-adapter-test.php'; - } - - protected function tearDown() - { - $this->createCachePool()->clear(); - - if (file_exists(sys_get_temp_dir().'/symfony-cache')) { - FilesystemAdapterTest::rmdir(sys_get_temp_dir().'/symfony-cache'); - } - } - - public function createCachePool($defaultLifetime = 0) - { - return new PhpArrayAdapter(self::$file, new FilesystemAdapter('php-array-fallback', $defaultLifetime)); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PhpFilesAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PhpFilesAdapterTest.php deleted file mode 100644 index 247160d53..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PhpFilesAdapterTest.php +++ /dev/null @@ -1,47 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use Psr\Cache\CacheItemPoolInterface; -use Symfony\Component\Cache\Adapter\PhpFilesAdapter; - -/** - * @group time-sensitive - */ -class PhpFilesAdapterTest extends AdapterTestCase -{ - protected $skippedTests = [ - 'testDefaultLifeTime' => 'PhpFilesAdapter does not allow configuring a default lifetime.', - ]; - - public function createCachePool() - { - if (!PhpFilesAdapter::isSupported()) { - $this->markTestSkipped('OPcache extension is not enabled.'); - } - - return new PhpFilesAdapter('sf-cache'); - } - - public static function tearDownAfterClass() - { - FilesystemAdapterTest::rmdir(sys_get_temp_dir().'/symfony-cache'); - } - - protected function isPruned(CacheItemPoolInterface $cache, $name) - { - $getFileMethod = (new \ReflectionObject($cache))->getMethod('getFile'); - $getFileMethod->setAccessible(true); - - return !file_exists($getFileMethod->invoke($cache, $name)); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PredisAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PredisAdapterTest.php deleted file mode 100644 index 6aadbf266..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PredisAdapterTest.php +++ /dev/null @@ -1,53 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use Predis\Connection\StreamConnection; -use Symfony\Component\Cache\Adapter\RedisAdapter; - -class PredisAdapterTest extends AbstractRedisAdapterTest -{ - public static function setUpBeforeClass() - { - parent::setUpBeforeClass(); - self::$redis = new \Predis\Client(['host' => getenv('REDIS_HOST')]); - } - - public function testCreateConnection() - { - $redisHost = getenv('REDIS_HOST'); - - $redis = RedisAdapter::createConnection('redis://'.$redisHost.'/1', ['class' => \Predis\Client::class, 'timeout' => 3]); - $this->assertInstanceOf(\Predis\Client::class, $redis); - - $connection = $redis->getConnection(); - $this->assertInstanceOf(StreamConnection::class, $connection); - - $params = [ - 'scheme' => 'tcp', - 'host' => $redisHost, - 'path' => '', - 'dbindex' => '1', - 'port' => 6379, - 'class' => 'Predis\Client', - 'timeout' => 3, - 'persistent' => 0, - 'persistent_id' => null, - 'read_timeout' => 0, - 'retry_interval' => 0, - 'lazy' => false, - 'database' => '1', - 'password' => null, - ]; - $this->assertSame($params, $connection->getParameters()->toArray()); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PredisClusterAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PredisClusterAdapterTest.php deleted file mode 100644 index 1afabaf1d..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PredisClusterAdapterTest.php +++ /dev/null @@ -1,26 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -class PredisClusterAdapterTest extends AbstractRedisAdapterTest -{ - public static function setUpBeforeClass() - { - parent::setUpBeforeClass(); - self::$redis = new \Predis\Client([['host' => getenv('REDIS_HOST')]]); - } - - public static function tearDownAfterClass() - { - self::$redis = null; - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PredisRedisClusterAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PredisRedisClusterAdapterTest.php deleted file mode 100644 index 5b09919e2..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/PredisRedisClusterAdapterTest.php +++ /dev/null @@ -1,28 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -class PredisRedisClusterAdapterTest extends AbstractRedisAdapterTest -{ - public static function setUpBeforeClass() - { - if (!$hosts = getenv('REDIS_CLUSTER_HOSTS')) { - self::markTestSkipped('REDIS_CLUSTER_HOSTS env var is not defined.'); - } - self::$redis = new \Predis\Client(explode(' ', $hosts), ['cluster' => 'redis']); - } - - public static function tearDownAfterClass() - { - self::$redis = null; - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ProxyAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ProxyAdapterTest.php deleted file mode 100644 index 810cb31a2..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/ProxyAdapterTest.php +++ /dev/null @@ -1,69 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use Psr\Cache\CacheItemInterface; -use Symfony\Component\Cache\Adapter\ArrayAdapter; -use Symfony\Component\Cache\Adapter\ProxyAdapter; -use Symfony\Component\Cache\CacheItem; - -/** - * @group time-sensitive - */ -class ProxyAdapterTest extends AdapterTestCase -{ - protected $skippedTests = [ - 'testDeferredSaveWithoutCommit' => 'Assumes a shared cache which ArrayAdapter is not.', - 'testSaveWithoutExpire' => 'Assumes a shared cache which ArrayAdapter is not.', - 'testPrune' => 'ProxyAdapter just proxies', - ]; - - public function createCachePool($defaultLifetime = 0) - { - return new ProxyAdapter(new ArrayAdapter(), '', $defaultLifetime); - } - - public function testProxyfiedItem() - { - $this->expectException('Exception'); - $this->expectExceptionMessage('OK bar'); - $item = new CacheItem(); - $pool = new ProxyAdapter(new TestingArrayAdapter($item)); - - $proxyItem = $pool->getItem('foo'); - - $this->assertNotSame($item, $proxyItem); - $pool->save($proxyItem->set('bar')); - } -} - -class TestingArrayAdapter extends ArrayAdapter -{ - private $item; - - public function __construct(CacheItemInterface $item) - { - $this->item = $item; - } - - public function getItem($key) - { - return $this->item; - } - - public function save(CacheItemInterface $item) - { - if ($item === $this->item) { - throw new \Exception('OK '.$item->get()); - } - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/RedisAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/RedisAdapterTest.php deleted file mode 100644 index 6ec6321a3..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/RedisAdapterTest.php +++ /dev/null @@ -1,92 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use Symfony\Component\Cache\Adapter\AbstractAdapter; -use Symfony\Component\Cache\Adapter\RedisAdapter; -use Symfony\Component\Cache\Traits\RedisProxy; - -class RedisAdapterTest extends AbstractRedisAdapterTest -{ - public static function setUpBeforeClass() - { - parent::setUpBeforeClass(); - self::$redis = AbstractAdapter::createConnection('redis://'.getenv('REDIS_HOST'), ['lazy' => true]); - } - - public function createCachePool($defaultLifetime = 0) - { - $adapter = parent::createCachePool($defaultLifetime); - $this->assertInstanceOf(RedisProxy::class, self::$redis); - - return $adapter; - } - - public function testCreateConnection() - { - $redisHost = getenv('REDIS_HOST'); - - $redis = RedisAdapter::createConnection('redis://'.$redisHost); - $this->assertInstanceOf(\Redis::class, $redis); - $this->assertTrue($redis->isConnected()); - $this->assertSame(0, $redis->getDbNum()); - - $redis = RedisAdapter::createConnection('redis://'.$redisHost.'/2'); - $this->assertSame(2, $redis->getDbNum()); - - $redis = RedisAdapter::createConnection('redis://'.$redisHost, ['timeout' => 3]); - $this->assertEquals(3, $redis->getTimeout()); - - $redis = RedisAdapter::createConnection('redis://'.$redisHost.'?timeout=4'); - $this->assertEquals(4, $redis->getTimeout()); - - $redis = RedisAdapter::createConnection('redis://'.$redisHost, ['read_timeout' => 5]); - $this->assertEquals(5, $redis->getReadTimeout()); - } - - /** - * @dataProvider provideFailedCreateConnection - */ - public function testFailedCreateConnection($dsn) - { - $this->expectException('Symfony\Component\Cache\Exception\InvalidArgumentException'); - $this->expectExceptionMessage('Redis connection '); - RedisAdapter::createConnection($dsn); - } - - public function provideFailedCreateConnection() - { - return [ - ['redis://localhost:1234'], - ['redis://foo@localhost'], - ['redis://localhost/123'], - ]; - } - - /** - * @dataProvider provideInvalidCreateConnection - */ - public function testInvalidCreateConnection($dsn) - { - $this->expectException('Symfony\Component\Cache\Exception\InvalidArgumentException'); - $this->expectExceptionMessage('Invalid Redis DSN'); - RedisAdapter::createConnection($dsn); - } - - public function provideInvalidCreateConnection() - { - return [ - ['foo://localhost'], - ['redis://'], - ]; - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/RedisArrayAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/RedisArrayAdapterTest.php deleted file mode 100644 index bd9def326..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/RedisArrayAdapterTest.php +++ /dev/null @@ -1,24 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -class RedisArrayAdapterTest extends AbstractRedisAdapterTest -{ - public static function setUpBeforeClass() - { - parent::setupBeforeClass(); - if (!class_exists('RedisArray')) { - self::markTestSkipped('The RedisArray class is required.'); - } - self::$redis = new \RedisArray([getenv('REDIS_HOST')], ['lazy_connect' => true]); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/RedisClusterAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/RedisClusterAdapterTest.php deleted file mode 100644 index 9c339d2dd..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/RedisClusterAdapterTest.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -class RedisClusterAdapterTest extends AbstractRedisAdapterTest -{ - public static function setUpBeforeClass() - { - if (!class_exists('RedisCluster')) { - self::markTestSkipped('The RedisCluster class is required.'); - } - if (!$hosts = getenv('REDIS_CLUSTER_HOSTS')) { - self::markTestSkipped('REDIS_CLUSTER_HOSTS env var is not defined.'); - } - - self::$redis = new \RedisCluster(null, explode(' ', $hosts)); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/SimpleCacheAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/SimpleCacheAdapterTest.php deleted file mode 100644 index d8470a2e7..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/SimpleCacheAdapterTest.php +++ /dev/null @@ -1,41 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use Symfony\Component\Cache\Adapter\SimpleCacheAdapter; -use Symfony\Component\Cache\Simple\ArrayCache; -use Symfony\Component\Cache\Simple\FilesystemCache; - -/** - * @group time-sensitive - */ -class SimpleCacheAdapterTest extends AdapterTestCase -{ - protected $skippedTests = [ - 'testPrune' => 'SimpleCache just proxies', - ]; - - public function createCachePool($defaultLifetime = 0) - { - return new SimpleCacheAdapter(new FilesystemCache(), '', $defaultLifetime); - } - - public function testValidCacheKeyWithNamespace() - { - $cache = new SimpleCacheAdapter(new ArrayCache(), 'some_namespace', 0); - $item = $cache->getItem('my_key'); - $item->set('someValue'); - $cache->save($item); - - $this->assertTrue($cache->getItem('my_key')->isHit(), 'Stored item is successfully retrieved.'); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TagAwareAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TagAwareAdapterTest.php deleted file mode 100644 index 11907a031..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TagAwareAdapterTest.php +++ /dev/null @@ -1,338 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use PHPUnit\Framework\MockObject\MockObject; -use Psr\Cache\CacheItemInterface; -use Symfony\Component\Cache\Adapter\AdapterInterface; -use Symfony\Component\Cache\Adapter\ArrayAdapter; -use Symfony\Component\Cache\Adapter\FilesystemAdapter; -use Symfony\Component\Cache\Adapter\TagAwareAdapter; - -/** - * @group time-sensitive - */ -class TagAwareAdapterTest extends AdapterTestCase -{ - public function createCachePool($defaultLifetime = 0) - { - return new TagAwareAdapter(new FilesystemAdapter('', $defaultLifetime)); - } - - public static function tearDownAfterClass() - { - FilesystemAdapterTest::rmdir(sys_get_temp_dir().'/symfony-cache'); - } - - public function testInvalidTag() - { - $this->expectException('Psr\Cache\InvalidArgumentException'); - $pool = $this->createCachePool(); - $item = $pool->getItem('foo'); - $item->tag(':'); - } - - public function testInvalidateTags() - { - $pool = $this->createCachePool(); - - $i0 = $pool->getItem('i0'); - $i1 = $pool->getItem('i1'); - $i2 = $pool->getItem('i2'); - $i3 = $pool->getItem('i3'); - $foo = $pool->getItem('foo'); - - $pool->save($i0->tag('bar')); - $pool->save($i1->tag('foo')); - $pool->save($i2->tag('foo')->tag('bar')); - $pool->save($i3->tag('foo')->tag('baz')); - $pool->save($foo); - - $pool->invalidateTags(['bar']); - - $this->assertFalse($pool->getItem('i0')->isHit()); - $this->assertTrue($pool->getItem('i1')->isHit()); - $this->assertFalse($pool->getItem('i2')->isHit()); - $this->assertTrue($pool->getItem('i3')->isHit()); - $this->assertTrue($pool->getItem('foo')->isHit()); - - $pool->invalidateTags(['foo']); - - $this->assertFalse($pool->getItem('i1')->isHit()); - $this->assertFalse($pool->getItem('i3')->isHit()); - $this->assertTrue($pool->getItem('foo')->isHit()); - - $anotherPoolInstance = $this->createCachePool(); - - $this->assertFalse($anotherPoolInstance->getItem('i1')->isHit()); - $this->assertFalse($anotherPoolInstance->getItem('i3')->isHit()); - $this->assertTrue($anotherPoolInstance->getItem('foo')->isHit()); - } - - public function testInvalidateCommits() - { - $pool1 = $this->createCachePool(); - - $foo = $pool1->getItem('foo'); - $foo->tag('tag'); - - $pool1->saveDeferred($foo->set('foo')); - $pool1->invalidateTags(['tag']); - - $pool2 = $this->createCachePool(); - $foo = $pool2->getItem('foo'); - - $this->assertTrue($foo->isHit()); - } - - public function testTagsAreCleanedOnSave() - { - $pool = $this->createCachePool(); - - $i = $pool->getItem('k'); - $pool->save($i->tag('foo')); - - $i = $pool->getItem('k'); - $pool->save($i->tag('bar')); - - $pool->invalidateTags(['foo']); - $this->assertTrue($pool->getItem('k')->isHit()); - } - - public function testTagsAreCleanedOnDelete() - { - $pool = $this->createCachePool(); - - $i = $pool->getItem('k'); - $pool->save($i->tag('foo')); - $pool->deleteItem('k'); - - $pool->save($pool->getItem('k')); - $pool->invalidateTags(['foo']); - - $this->assertTrue($pool->getItem('k')->isHit()); - } - - public function testTagItemExpiry() - { - $pool = $this->createCachePool(10); - - $item = $pool->getItem('foo'); - $item->tag(['baz']); - $item->expiresAfter(100); - - $pool->save($item); - $pool->invalidateTags(['baz']); - $this->assertFalse($pool->getItem('foo')->isHit()); - - sleep(20); - - $this->assertFalse($pool->getItem('foo')->isHit()); - } - - public function testGetPreviousTags() - { - $pool = $this->createCachePool(); - - $i = $pool->getItem('k'); - $pool->save($i->tag('foo')); - - $i = $pool->getItem('k'); - $this->assertSame(['foo' => 'foo'], $i->getPreviousTags()); - } - - public function testPrune() - { - $cache = new TagAwareAdapter($this->getPruneableMock()); - $this->assertTrue($cache->prune()); - - $cache = new TagAwareAdapter($this->getNonPruneableMock()); - $this->assertFalse($cache->prune()); - - $cache = new TagAwareAdapter($this->getFailingPruneableMock()); - $this->assertFalse($cache->prune()); - } - - public function testKnownTagVersionsTtl() - { - $itemsPool = new FilesystemAdapter('', 10); - $tagsPool = $this - ->getMockBuilder(AdapterInterface::class) - ->getMock(); - - $pool = new TagAwareAdapter($itemsPool, $tagsPool, 10); - - $item = $pool->getItem('foo'); - $item->tag(['baz']); - $item->expiresAfter(100); - - $tag = $this->getMockBuilder(CacheItemInterface::class)->getMock(); - $tag->expects(self::exactly(2))->method('get')->willReturn(10); - - $tagsPool->expects(self::exactly(2))->method('getItems')->willReturn([ - 'baz'.TagAwareAdapter::TAGS_PREFIX => $tag, - ]); - - $pool->save($item); - $this->assertTrue($pool->getItem('foo')->isHit()); - $this->assertTrue($pool->getItem('foo')->isHit()); - - sleep(20); - - $this->assertTrue($pool->getItem('foo')->isHit()); - - sleep(5); - - $this->assertTrue($pool->getItem('foo')->isHit()); - } - - public function testTagEntryIsCreatedForItemWithoutTags() - { - $pool = $this->createCachePool(); - - $itemKey = 'foo'; - $item = $pool->getItem($itemKey); - $pool->save($item); - - $adapter = new FilesystemAdapter(); - $this->assertTrue($adapter->hasItem(TagAwareAdapter::TAGS_PREFIX.$itemKey)); - } - - public function testHasItemReturnsFalseWhenPoolDoesNotHaveItemTags() - { - $pool = $this->createCachePool(); - - $itemKey = 'foo'; - $item = $pool->getItem($itemKey); - $pool->save($item); - - $anotherPool = $this->createCachePool(); - - $adapter = new FilesystemAdapter(); - $adapter->deleteItem(TagAwareAdapter::TAGS_PREFIX.$itemKey); //simulate item losing tags pair - - $this->assertFalse($anotherPool->hasItem($itemKey)); - } - - public function testGetItemReturnsCacheMissWhenPoolDoesNotHaveItemTags() - { - $pool = $this->createCachePool(); - - $itemKey = 'foo'; - $item = $pool->getItem($itemKey); - $pool->save($item); - - $anotherPool = $this->createCachePool(); - - $adapter = new FilesystemAdapter(); - $adapter->deleteItem(TagAwareAdapter::TAGS_PREFIX.$itemKey); //simulate item losing tags pair - - $item = $anotherPool->getItem($itemKey); - $this->assertFalse($item->isHit()); - } - - public function testHasItemReturnsFalseWhenPoolDoesNotHaveItemAndOnlyHasTags() - { - $pool = $this->createCachePool(); - - $itemKey = 'foo'; - $item = $pool->getItem($itemKey); - $pool->save($item); - - $anotherPool = $this->createCachePool(); - - $adapter = new FilesystemAdapter(); - $adapter->deleteItem($itemKey); //simulate losing item but keeping tags - - $this->assertFalse($anotherPool->hasItem($itemKey)); - } - - public function testInvalidateTagsWithArrayAdapter() - { - $adapter = new TagAwareAdapter(new ArrayAdapter()); - - $item = $adapter->getItem('foo'); - - $this->assertFalse($item->isHit()); - - $item->tag('bar'); - $item->expiresAfter(100); - $adapter->save($item); - - $this->assertTrue($adapter->getItem('foo')->isHit()); - - $adapter->invalidateTags(['bar']); - - $this->assertFalse($adapter->getItem('foo')->isHit()); - } - - public function testGetItemReturnsCacheMissWhenPoolDoesNotHaveItemAndOnlyHasTags() - { - $pool = $this->createCachePool(); - - $itemKey = 'foo'; - $item = $pool->getItem($itemKey); - $pool->save($item); - - $anotherPool = $this->createCachePool(); - - $adapter = new FilesystemAdapter(); - $adapter->deleteItem($itemKey); //simulate losing item but keeping tags - - $item = $anotherPool->getItem($itemKey); - $this->assertFalse($item->isHit()); - } - - /** - * @return MockObject|PruneableCacheInterface - */ - private function getPruneableMock() - { - $pruneable = $this - ->getMockBuilder(PruneableCacheInterface::class) - ->getMock(); - - $pruneable - ->expects($this->atLeastOnce()) - ->method('prune') - ->willReturn(true); - - return $pruneable; - } - - /** - * @return MockObject|PruneableCacheInterface - */ - private function getFailingPruneableMock() - { - $pruneable = $this - ->getMockBuilder(PruneableCacheInterface::class) - ->getMock(); - - $pruneable - ->expects($this->atLeastOnce()) - ->method('prune') - ->willReturn(false); - - return $pruneable; - } - - /** - * @return MockObject|AdapterInterface - */ - private function getNonPruneableMock() - { - return $this - ->getMockBuilder(AdapterInterface::class) - ->getMock(); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TagAwareAndProxyAdapterIntegrationTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TagAwareAndProxyAdapterIntegrationTest.php deleted file mode 100644 index b11c1f287..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TagAwareAndProxyAdapterIntegrationTest.php +++ /dev/null @@ -1,38 +0,0 @@ -getItem('foo'); - $item->tag(['tag1', 'tag2']); - $item->set('bar'); - $cache->save($item); - - $this->assertSame('bar', $cache->getItem('foo')->get()); - } - - public function dataProvider() - { - return [ - [new ArrayAdapter()], - // also testing with a non-AdapterInterface implementation - // because the ProxyAdapter behaves slightly different for those - [new ExternalAdapter()], - ]; - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TraceableAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TraceableAdapterTest.php deleted file mode 100644 index 35eba7d77..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TraceableAdapterTest.php +++ /dev/null @@ -1,191 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use Symfony\Component\Cache\Adapter\FilesystemAdapter; -use Symfony\Component\Cache\Adapter\TraceableAdapter; - -/** - * @group time-sensitive - */ -class TraceableAdapterTest extends AdapterTestCase -{ - protected $skippedTests = [ - 'testPrune' => 'TraceableAdapter just proxies', - ]; - - public function createCachePool($defaultLifetime = 0) - { - return new TraceableAdapter(new FilesystemAdapter('', $defaultLifetime)); - } - - public function testGetItemMissTrace() - { - $pool = $this->createCachePool(); - $pool->getItem('k'); - $calls = $pool->getCalls(); - $this->assertCount(1, $calls); - - $call = $calls[0]; - $this->assertSame('getItem', $call->name); - $this->assertSame(['k' => false], $call->result); - $this->assertSame(0, $call->hits); - $this->assertSame(1, $call->misses); - $this->assertNotEmpty($call->start); - $this->assertNotEmpty($call->end); - } - - public function testGetItemHitTrace() - { - $pool = $this->createCachePool(); - $item = $pool->getItem('k')->set('foo'); - $pool->save($item); - $pool->getItem('k'); - $calls = $pool->getCalls(); - $this->assertCount(3, $calls); - - $call = $calls[2]; - $this->assertSame(1, $call->hits); - $this->assertSame(0, $call->misses); - } - - public function testGetItemsMissTrace() - { - $pool = $this->createCachePool(); - $arg = ['k0', 'k1']; - $items = $pool->getItems($arg); - foreach ($items as $item) { - } - $calls = $pool->getCalls(); - $this->assertCount(1, $calls); - - $call = $calls[0]; - $this->assertSame('getItems', $call->name); - $this->assertSame(['k0' => false, 'k1' => false], $call->result); - $this->assertSame(2, $call->misses); - $this->assertNotEmpty($call->start); - $this->assertNotEmpty($call->end); - } - - public function testHasItemMissTrace() - { - $pool = $this->createCachePool(); - $pool->hasItem('k'); - $calls = $pool->getCalls(); - $this->assertCount(1, $calls); - - $call = $calls[0]; - $this->assertSame('hasItem', $call->name); - $this->assertSame(['k' => false], $call->result); - $this->assertNotEmpty($call->start); - $this->assertNotEmpty($call->end); - } - - public function testHasItemHitTrace() - { - $pool = $this->createCachePool(); - $item = $pool->getItem('k')->set('foo'); - $pool->save($item); - $pool->hasItem('k'); - $calls = $pool->getCalls(); - $this->assertCount(3, $calls); - - $call = $calls[2]; - $this->assertSame('hasItem', $call->name); - $this->assertSame(['k' => true], $call->result); - $this->assertNotEmpty($call->start); - $this->assertNotEmpty($call->end); - } - - public function testDeleteItemTrace() - { - $pool = $this->createCachePool(); - $pool->deleteItem('k'); - $calls = $pool->getCalls(); - $this->assertCount(1, $calls); - - $call = $calls[0]; - $this->assertSame('deleteItem', $call->name); - $this->assertSame(['k' => true], $call->result); - $this->assertSame(0, $call->hits); - $this->assertSame(0, $call->misses); - $this->assertNotEmpty($call->start); - $this->assertNotEmpty($call->end); - } - - public function testDeleteItemsTrace() - { - $pool = $this->createCachePool(); - $arg = ['k0', 'k1']; - $pool->deleteItems($arg); - $calls = $pool->getCalls(); - $this->assertCount(1, $calls); - - $call = $calls[0]; - $this->assertSame('deleteItems', $call->name); - $this->assertSame(['keys' => $arg, 'result' => true], $call->result); - $this->assertSame(0, $call->hits); - $this->assertSame(0, $call->misses); - $this->assertNotEmpty($call->start); - $this->assertNotEmpty($call->end); - } - - public function testSaveTrace() - { - $pool = $this->createCachePool(); - $item = $pool->getItem('k')->set('foo'); - $pool->save($item); - $calls = $pool->getCalls(); - $this->assertCount(2, $calls); - - $call = $calls[1]; - $this->assertSame('save', $call->name); - $this->assertSame(['k' => true], $call->result); - $this->assertSame(0, $call->hits); - $this->assertSame(0, $call->misses); - $this->assertNotEmpty($call->start); - $this->assertNotEmpty($call->end); - } - - public function testSaveDeferredTrace() - { - $pool = $this->createCachePool(); - $item = $pool->getItem('k')->set('foo'); - $pool->saveDeferred($item); - $calls = $pool->getCalls(); - $this->assertCount(2, $calls); - - $call = $calls[1]; - $this->assertSame('saveDeferred', $call->name); - $this->assertSame(['k' => true], $call->result); - $this->assertSame(0, $call->hits); - $this->assertSame(0, $call->misses); - $this->assertNotEmpty($call->start); - $this->assertNotEmpty($call->end); - } - - public function testCommitTrace() - { - $pool = $this->createCachePool(); - $pool->commit(); - $calls = $pool->getCalls(); - $this->assertCount(1, $calls); - - $call = $calls[0]; - $this->assertSame('commit', $call->name); - $this->assertTrue($call->result); - $this->assertSame(0, $call->hits); - $this->assertSame(0, $call->misses); - $this->assertNotEmpty($call->start); - $this->assertNotEmpty($call->end); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TraceableTagAwareAdapterTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TraceableTagAwareAdapterTest.php deleted file mode 100644 index 5cd4185cb..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Adapter/TraceableTagAwareAdapterTest.php +++ /dev/null @@ -1,37 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Adapter; - -use Symfony\Component\Cache\Adapter\FilesystemAdapter; -use Symfony\Component\Cache\Adapter\TagAwareAdapter; -use Symfony\Component\Cache\Adapter\TraceableTagAwareAdapter; - -/** - * @group time-sensitive - */ -class TraceableTagAwareAdapterTest extends TraceableAdapterTest -{ - public function testInvalidateTags() - { - $pool = new TraceableTagAwareAdapter(new TagAwareAdapter(new FilesystemAdapter())); - $pool->invalidateTags(['foo']); - $calls = $pool->getCalls(); - $this->assertCount(1, $calls); - - $call = $calls[0]; - $this->assertSame('invalidateTags', $call->name); - $this->assertSame(0, $call->hits); - $this->assertSame(0, $call->misses); - $this->assertNotEmpty($call->start); - $this->assertNotEmpty($call->end); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/CacheItemTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/CacheItemTest.php deleted file mode 100644 index 28c681d15..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/CacheItemTest.php +++ /dev/null @@ -1,77 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Cache\CacheItem; - -class CacheItemTest extends TestCase -{ - public function testValidKey() - { - $this->assertSame('foo', CacheItem::validateKey('foo')); - } - - /** - * @dataProvider provideInvalidKey - */ - public function testInvalidKey($key) - { - $this->expectException('Symfony\Component\Cache\Exception\InvalidArgumentException'); - $this->expectExceptionMessage('Cache key'); - CacheItem::validateKey($key); - } - - public function provideInvalidKey() - { - return [ - [''], - ['{'], - ['}'], - ['('], - [')'], - ['/'], - ['\\'], - ['@'], - [':'], - [true], - [null], - [1], - [1.1], - [[[]]], - [new \Exception('foo')], - ]; - } - - public function testTag() - { - $item = new CacheItem(); - - $this->assertSame($item, $item->tag('foo')); - $this->assertSame($item, $item->tag(['bar', 'baz'])); - - \call_user_func(\Closure::bind(function () use ($item) { - $this->assertSame(['foo' => 'foo', 'bar' => 'bar', 'baz' => 'baz'], $item->tags); - }, $this, CacheItem::class)); - } - - /** - * @dataProvider provideInvalidKey - */ - public function testInvalidTag($tag) - { - $this->expectException('Symfony\Component\Cache\Exception\InvalidArgumentException'); - $this->expectExceptionMessage('Cache tag'); - $item = new CacheItem(); - $item->tag($tag); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/DoctrineProviderTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/DoctrineProviderTest.php deleted file mode 100644 index 91a5516ab..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/DoctrineProviderTest.php +++ /dev/null @@ -1,45 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests; - -use Doctrine\Common\Cache\CacheProvider; -use PHPUnit\Framework\TestCase; -use Symfony\Component\Cache\Adapter\ArrayAdapter; -use Symfony\Component\Cache\DoctrineProvider; - -class DoctrineProviderTest extends TestCase -{ - public function testProvider() - { - $pool = new ArrayAdapter(); - $cache = new DoctrineProvider($pool); - - $this->assertInstanceOf(CacheProvider::class, $cache); - - $key = '{}()/\@:'; - - $this->assertTrue($cache->delete($key)); - $this->assertFalse($cache->contains($key)); - - $this->assertTrue($cache->save($key, 'bar')); - $this->assertTrue($cache->contains($key)); - $this->assertSame('bar', $cache->fetch($key)); - - $this->assertTrue($cache->delete($key)); - $this->assertFalse($cache->fetch($key)); - $this->assertTrue($cache->save($key, 'bar')); - - $cache->flushAll(); - $this->assertFalse($cache->fetch($key)); - $this->assertFalse($cache->contains($key)); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Fixtures/ArrayCache.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Fixtures/ArrayCache.php deleted file mode 100644 index 13b4f3306..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Fixtures/ArrayCache.php +++ /dev/null @@ -1,52 +0,0 @@ -doContains($id) ? $this->data[$id][0] : false; - } - - protected function doContains($id) - { - if (!isset($this->data[$id])) { - return false; - } - - $expiry = $this->data[$id][1]; - - return !$expiry || time() < $expiry || !$this->doDelete($id); - } - - protected function doSave($id, $data, $lifeTime = 0) - { - $this->data[$id] = [$data, $lifeTime ? time() + $lifeTime : false]; - - return true; - } - - protected function doDelete($id) - { - unset($this->data[$id]); - - return true; - } - - protected function doFlush() - { - $this->data = []; - - return true; - } - - protected function doGetStats() - { - return null; - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Fixtures/ExternalAdapter.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Fixtures/ExternalAdapter.php deleted file mode 100644 index be1f99012..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Fixtures/ExternalAdapter.php +++ /dev/null @@ -1,76 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Fixtures; - -use Psr\Cache\CacheItemInterface; -use Psr\Cache\CacheItemPoolInterface; -use Symfony\Component\Cache\Adapter\ArrayAdapter; - -/** - * Adapter not implementing the {@see \Symfony\Component\Cache\Adapter\AdapterInterface}. - * - * @author Kévin Dunglas - */ -class ExternalAdapter implements CacheItemPoolInterface -{ - private $cache; - - public function __construct($defaultLifetime = 0) - { - $this->cache = new ArrayAdapter($defaultLifetime); - } - - public function getItem($key) - { - return $this->cache->getItem($key); - } - - public function getItems(array $keys = []) - { - return $this->cache->getItems($keys); - } - - public function hasItem($key) - { - return $this->cache->hasItem($key); - } - - public function clear() - { - return $this->cache->clear(); - } - - public function deleteItem($key) - { - return $this->cache->deleteItem($key); - } - - public function deleteItems(array $keys) - { - return $this->cache->deleteItems($keys); - } - - public function save(CacheItemInterface $item) - { - return $this->cache->save($item); - } - - public function saveDeferred(CacheItemInterface $item) - { - return $this->cache->saveDeferred($item); - } - - public function commit() - { - return $this->cache->commit(); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/AbstractRedisCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/AbstractRedisCacheTest.php deleted file mode 100644 index 7a6cabe8c..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/AbstractRedisCacheTest.php +++ /dev/null @@ -1,47 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Simple; - -use Symfony\Component\Cache\Simple\RedisCache; - -abstract class AbstractRedisCacheTest extends CacheTestCase -{ - protected $skippedTests = [ - 'testSetTtl' => 'Testing expiration slows down the test suite', - 'testSetMultipleTtl' => 'Testing expiration slows down the test suite', - 'testDefaultLifeTime' => 'Testing expiration slows down the test suite', - ]; - - protected static $redis; - - public function createSimpleCache($defaultLifetime = 0) - { - return new RedisCache(self::$redis, str_replace('\\', '.', __CLASS__), $defaultLifetime); - } - - public static function setUpBeforeClass() - { - if (!\extension_loaded('redis')) { - self::markTestSkipped('Extension redis required.'); - } - try { - (new \Redis())->connect(getenv('REDIS_HOST')); - } catch (\Exception $e) { - self::markTestSkipped($e->getMessage()); - } - } - - public static function tearDownAfterClass() - { - self::$redis = null; - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/ApcuCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/ApcuCacheTest.php deleted file mode 100644 index fad0c0432..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/ApcuCacheTest.php +++ /dev/null @@ -1,35 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Simple; - -use Symfony\Component\Cache\Simple\ApcuCache; - -class ApcuCacheTest extends CacheTestCase -{ - protected $skippedTests = [ - 'testSetTtl' => 'Testing expiration slows down the test suite', - 'testSetMultipleTtl' => 'Testing expiration slows down the test suite', - 'testDefaultLifeTime' => 'Testing expiration slows down the test suite', - ]; - - public function createSimpleCache($defaultLifetime = 0) - { - if (!\function_exists('apcu_fetch') || !filter_var(ini_get('apc.enabled'), \FILTER_VALIDATE_BOOLEAN) || ('cli' === \PHP_SAPI && !filter_var(ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOLEAN))) { - $this->markTestSkipped('APCu extension is required.'); - } - if ('\\' === \DIRECTORY_SEPARATOR) { - $this->markTestSkipped('Fails transiently on Windows.'); - } - - return new ApcuCache(str_replace('\\', '.', __CLASS__), $defaultLifetime); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/ArrayCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/ArrayCacheTest.php deleted file mode 100644 index 26c3e14d0..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/ArrayCacheTest.php +++ /dev/null @@ -1,25 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Simple; - -use Symfony\Component\Cache\Simple\ArrayCache; - -/** - * @group time-sensitive - */ -class ArrayCacheTest extends CacheTestCase -{ - public function createSimpleCache($defaultLifetime = 0) - { - return new ArrayCache($defaultLifetime); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/CacheTestCase.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/CacheTestCase.php deleted file mode 100644 index ff9944a34..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/CacheTestCase.php +++ /dev/null @@ -1,150 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Simple; - -use Cache\IntegrationTests\SimpleCacheTest; -use Psr\SimpleCache\CacheInterface; -use Symfony\Component\Cache\PruneableInterface; - -abstract class CacheTestCase extends SimpleCacheTest -{ - protected function setUp() - { - parent::setUp(); - - if (!\array_key_exists('testPrune', $this->skippedTests) && !$this->createSimpleCache() instanceof PruneableInterface) { - $this->skippedTests['testPrune'] = 'Not a pruneable cache pool.'; - } - } - - public static function validKeys() - { - if (\defined('HHVM_VERSION')) { - return parent::validKeys(); - } - - return array_merge(parent::validKeys(), [["a\0b"]]); - } - - public function testDefaultLifeTime() - { - if (isset($this->skippedTests[__FUNCTION__])) { - $this->markTestSkipped($this->skippedTests[__FUNCTION__]); - } - - $cache = $this->createSimpleCache(2); - $cache->clear(); - - $cache->set('key.dlt', 'value'); - sleep(1); - - $this->assertSame('value', $cache->get('key.dlt')); - - sleep(2); - $this->assertNull($cache->get('key.dlt')); - - $cache->clear(); - } - - public function testNotUnserializable() - { - if (isset($this->skippedTests[__FUNCTION__])) { - $this->markTestSkipped($this->skippedTests[__FUNCTION__]); - } - - $cache = $this->createSimpleCache(); - $cache->clear(); - - $cache->set('foo', new NotUnserializable()); - - $this->assertNull($cache->get('foo')); - - $cache->setMultiple(['foo' => new NotUnserializable()]); - - foreach ($cache->getMultiple(['foo']) as $value) { - } - $this->assertNull($value); - - $cache->clear(); - } - - public function testPrune() - { - if (isset($this->skippedTests[__FUNCTION__])) { - $this->markTestSkipped($this->skippedTests[__FUNCTION__]); - } - - if (!method_exists($this, 'isPruned')) { - $this->fail('Test classes for pruneable caches must implement `isPruned($cache, $name)` method.'); - } - - /** @var PruneableInterface|CacheInterface $cache */ - $cache = $this->createSimpleCache(); - $cache->clear(); - - $cache->set('foo', 'foo-val', new \DateInterval('PT05S')); - $cache->set('bar', 'bar-val', new \DateInterval('PT10S')); - $cache->set('baz', 'baz-val', new \DateInterval('PT15S')); - $cache->set('qux', 'qux-val', new \DateInterval('PT20S')); - - sleep(30); - $cache->prune(); - $this->assertTrue($this->isPruned($cache, 'foo')); - $this->assertTrue($this->isPruned($cache, 'bar')); - $this->assertTrue($this->isPruned($cache, 'baz')); - $this->assertTrue($this->isPruned($cache, 'qux')); - - $cache->set('foo', 'foo-val'); - $cache->set('bar', 'bar-val', new \DateInterval('PT20S')); - $cache->set('baz', 'baz-val', new \DateInterval('PT40S')); - $cache->set('qux', 'qux-val', new \DateInterval('PT80S')); - - $cache->prune(); - $this->assertFalse($this->isPruned($cache, 'foo')); - $this->assertFalse($this->isPruned($cache, 'bar')); - $this->assertFalse($this->isPruned($cache, 'baz')); - $this->assertFalse($this->isPruned($cache, 'qux')); - - sleep(30); - $cache->prune(); - $this->assertFalse($this->isPruned($cache, 'foo')); - $this->assertTrue($this->isPruned($cache, 'bar')); - $this->assertFalse($this->isPruned($cache, 'baz')); - $this->assertFalse($this->isPruned($cache, 'qux')); - - sleep(30); - $cache->prune(); - $this->assertFalse($this->isPruned($cache, 'foo')); - $this->assertTrue($this->isPruned($cache, 'baz')); - $this->assertFalse($this->isPruned($cache, 'qux')); - - sleep(30); - $cache->prune(); - $this->assertFalse($this->isPruned($cache, 'foo')); - $this->assertTrue($this->isPruned($cache, 'qux')); - - $cache->clear(); - } -} - -class NotUnserializable implements \Serializable -{ - public function serialize() - { - return serialize(123); - } - - public function unserialize($ser) - { - throw new \Exception(__CLASS__); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/ChainCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/ChainCacheTest.php deleted file mode 100644 index f216bc1f3..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/ChainCacheTest.php +++ /dev/null @@ -1,113 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Simple; - -use PHPUnit\Framework\MockObject\MockObject; -use Psr\SimpleCache\CacheInterface; -use Symfony\Component\Cache\PruneableInterface; -use Symfony\Component\Cache\Simple\ArrayCache; -use Symfony\Component\Cache\Simple\ChainCache; -use Symfony\Component\Cache\Simple\FilesystemCache; - -/** - * @group time-sensitive - */ -class ChainCacheTest extends CacheTestCase -{ - public function createSimpleCache($defaultLifetime = 0) - { - return new ChainCache([new ArrayCache($defaultLifetime), new FilesystemCache('', $defaultLifetime)], $defaultLifetime); - } - - public function testEmptyCachesException() - { - $this->expectException('Symfony\Component\Cache\Exception\InvalidArgumentException'); - $this->expectExceptionMessage('At least one cache must be specified.'); - new ChainCache([]); - } - - public function testInvalidCacheException() - { - $this->expectException('Symfony\Component\Cache\Exception\InvalidArgumentException'); - $this->expectExceptionMessage('The class "stdClass" does not implement'); - new ChainCache([new \stdClass()]); - } - - public function testPrune() - { - if (isset($this->skippedTests[__FUNCTION__])) { - $this->markTestSkipped($this->skippedTests[__FUNCTION__]); - } - - $cache = new ChainCache([ - $this->getPruneableMock(), - $this->getNonPruneableMock(), - $this->getPruneableMock(), - ]); - $this->assertTrue($cache->prune()); - - $cache = new ChainCache([ - $this->getPruneableMock(), - $this->getFailingPruneableMock(), - $this->getPruneableMock(), - ]); - $this->assertFalse($cache->prune()); - } - - /** - * @return MockObject|PruneableCacheInterface - */ - private function getPruneableMock() - { - $pruneable = $this - ->getMockBuilder(PruneableCacheInterface::class) - ->getMock(); - - $pruneable - ->expects($this->atLeastOnce()) - ->method('prune') - ->willReturn(true); - - return $pruneable; - } - - /** - * @return MockObject|PruneableCacheInterface - */ - private function getFailingPruneableMock() - { - $pruneable = $this - ->getMockBuilder(PruneableCacheInterface::class) - ->getMock(); - - $pruneable - ->expects($this->atLeastOnce()) - ->method('prune') - ->willReturn(false); - - return $pruneable; - } - - /** - * @return MockObject|CacheInterface - */ - private function getNonPruneableMock() - { - return $this - ->getMockBuilder(CacheInterface::class) - ->getMock(); - } -} - -interface PruneableCacheInterface extends PruneableInterface, CacheInterface -{ -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/DoctrineCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/DoctrineCacheTest.php deleted file mode 100644 index af4331d69..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/DoctrineCacheTest.php +++ /dev/null @@ -1,31 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Simple; - -use Symfony\Component\Cache\Simple\DoctrineCache; -use Symfony\Component\Cache\Tests\Fixtures\ArrayCache; - -/** - * @group time-sensitive - */ -class DoctrineCacheTest extends CacheTestCase -{ - protected $skippedTests = [ - 'testObjectDoesNotChangeInCache' => 'ArrayCache does not use serialize/unserialize', - 'testNotUnserializable' => 'ArrayCache does not use serialize/unserialize', - ]; - - public function createSimpleCache($defaultLifetime = 0) - { - return new DoctrineCache(new ArrayCache($defaultLifetime), '', $defaultLifetime); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/FilesystemCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/FilesystemCacheTest.php deleted file mode 100644 index 620305a58..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/FilesystemCacheTest.php +++ /dev/null @@ -1,34 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Simple; - -use Psr\SimpleCache\CacheInterface; -use Symfony\Component\Cache\Simple\FilesystemCache; - -/** - * @group time-sensitive - */ -class FilesystemCacheTest extends CacheTestCase -{ - public function createSimpleCache($defaultLifetime = 0) - { - return new FilesystemCache('', $defaultLifetime); - } - - protected function isPruned(CacheInterface $cache, $name) - { - $getFileMethod = (new \ReflectionObject($cache))->getMethod('getFile'); - $getFileMethod->setAccessible(true); - - return !file_exists($getFileMethod->invoke($cache, $name)); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/MemcachedCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/MemcachedCacheTest.php deleted file mode 100644 index 6df682e9f..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/MemcachedCacheTest.php +++ /dev/null @@ -1,178 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Simple; - -use Symfony\Component\Cache\Adapter\AbstractAdapter; -use Symfony\Component\Cache\Simple\MemcachedCache; - -class MemcachedCacheTest extends CacheTestCase -{ - protected $skippedTests = [ - 'testSetTtl' => 'Testing expiration slows down the test suite', - 'testSetMultipleTtl' => 'Testing expiration slows down the test suite', - 'testDefaultLifeTime' => 'Testing expiration slows down the test suite', - ]; - - protected static $client; - - public static function setUpBeforeClass() - { - if (!MemcachedCache::isSupported()) { - self::markTestSkipped('Extension memcached >=2.2.0 required.'); - } - self::$client = AbstractAdapter::createConnection('memcached://'.getenv('MEMCACHED_HOST')); - self::$client->get('foo'); - $code = self::$client->getResultCode(); - - if (\Memcached::RES_SUCCESS !== $code && \Memcached::RES_NOTFOUND !== $code) { - self::markTestSkipped('Memcached error: '.strtolower(self::$client->getResultMessage())); - } - } - - public function createSimpleCache($defaultLifetime = 0) - { - $client = $defaultLifetime ? AbstractAdapter::createConnection('memcached://'.getenv('MEMCACHED_HOST'), ['binary_protocol' => false]) : self::$client; - - return new MemcachedCache($client, str_replace('\\', '.', __CLASS__), $defaultLifetime); - } - - public function testCreatePersistentConnectionShouldNotDupServerList() - { - $instance = MemcachedCache::createConnection('memcached://'.getenv('MEMCACHED_HOST'), ['persistent_id' => 'persistent']); - $this->assertCount(1, $instance->getServerList()); - - $instance = MemcachedCache::createConnection('memcached://'.getenv('MEMCACHED_HOST'), ['persistent_id' => 'persistent']); - $this->assertCount(1, $instance->getServerList()); - } - - public function testOptions() - { - $client = MemcachedCache::createConnection([], [ - 'libketama_compatible' => false, - 'distribution' => 'modula', - 'compression' => true, - 'serializer' => 'php', - 'hash' => 'md5', - ]); - - $this->assertSame(\Memcached::SERIALIZER_PHP, $client->getOption(\Memcached::OPT_SERIALIZER)); - $this->assertSame(\Memcached::HASH_MD5, $client->getOption(\Memcached::OPT_HASH)); - $this->assertTrue($client->getOption(\Memcached::OPT_COMPRESSION)); - $this->assertSame(0, $client->getOption(\Memcached::OPT_LIBKETAMA_COMPATIBLE)); - $this->assertSame(\Memcached::DISTRIBUTION_MODULA, $client->getOption(\Memcached::OPT_DISTRIBUTION)); - } - - /** - * @dataProvider provideBadOptions - */ - public function testBadOptions($name, $value) - { - if (\PHP_VERSION_ID < 80000) { - $this->expectException('ErrorException'); - $this->expectExceptionMessage('constant(): Couldn\'t find constant Memcached::'); - } else { - $this->expectException('Error'); - $this->expectExceptionMessage('Undefined constant Memcached::'); - } - - MemcachedCache::createConnection([], [$name => $value]); - } - - public function provideBadOptions() - { - return [ - ['foo', 'bar'], - ['hash', 'zyx'], - ['serializer', 'zyx'], - ['distribution', 'zyx'], - ]; - } - - public function testDefaultOptions() - { - $this->assertTrue(MemcachedCache::isSupported()); - - $client = MemcachedCache::createConnection([]); - - $this->assertTrue($client->getOption(\Memcached::OPT_COMPRESSION)); - $this->assertSame(1, $client->getOption(\Memcached::OPT_BINARY_PROTOCOL)); - $this->assertSame(1, $client->getOption(\Memcached::OPT_LIBKETAMA_COMPATIBLE)); - } - - public function testOptionSerializer() - { - $this->expectException('Symfony\Component\Cache\Exception\CacheException'); - $this->expectExceptionMessage('MemcachedAdapter: "serializer" option must be "php" or "igbinary".'); - if (!\Memcached::HAVE_JSON) { - $this->markTestSkipped('Memcached::HAVE_JSON required'); - } - - new MemcachedCache(MemcachedCache::createConnection([], ['serializer' => 'json'])); - } - - /** - * @dataProvider provideServersSetting - */ - public function testServersSetting($dsn, $host, $port) - { - $client1 = MemcachedCache::createConnection($dsn); - $client2 = MemcachedCache::createConnection([$dsn]); - $client3 = MemcachedCache::createConnection([[$host, $port]]); - $expect = [ - 'host' => $host, - 'port' => $port, - ]; - - $f = function ($s) { return ['host' => $s['host'], 'port' => $s['port']]; }; - $this->assertSame([$expect], array_map($f, $client1->getServerList())); - $this->assertSame([$expect], array_map($f, $client2->getServerList())); - $this->assertSame([$expect], array_map($f, $client3->getServerList())); - } - - public function provideServersSetting() - { - yield [ - 'memcached://127.0.0.1/50', - '127.0.0.1', - 11211, - ]; - yield [ - 'memcached://localhost:11222?weight=25', - 'localhost', - 11222, - ]; - if (filter_var(ini_get('memcached.use_sasl'), \FILTER_VALIDATE_BOOLEAN)) { - yield [ - 'memcached://user:password@127.0.0.1?weight=50', - '127.0.0.1', - 11211, - ]; - } - yield [ - 'memcached:///var/run/memcached.sock?weight=25', - '/var/run/memcached.sock', - 0, - ]; - yield [ - 'memcached:///var/local/run/memcached.socket?weight=25', - '/var/local/run/memcached.socket', - 0, - ]; - if (filter_var(ini_get('memcached.use_sasl'), \FILTER_VALIDATE_BOOLEAN)) { - yield [ - 'memcached://user:password@/var/local/run/memcached.socket?weight=25', - '/var/local/run/memcached.socket', - 0, - ]; - } - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/MemcachedCacheTextModeTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/MemcachedCacheTextModeTest.php deleted file mode 100644 index 13865a609..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/MemcachedCacheTextModeTest.php +++ /dev/null @@ -1,25 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Simple; - -use Symfony\Component\Cache\Adapter\AbstractAdapter; -use Symfony\Component\Cache\Simple\MemcachedCache; - -class MemcachedCacheTextModeTest extends MemcachedCacheTest -{ - public function createSimpleCache($defaultLifetime = 0) - { - $client = AbstractAdapter::createConnection('memcached://'.getenv('MEMCACHED_HOST'), ['binary_protocol' => false]); - - return new MemcachedCache($client, str_replace('\\', '.', __CLASS__), $defaultLifetime); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/NullCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/NullCacheTest.php deleted file mode 100644 index 31f42c32b..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/NullCacheTest.php +++ /dev/null @@ -1,96 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Simple; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Cache\Simple\NullCache; - -/** - * @group time-sensitive - */ -class NullCacheTest extends TestCase -{ - public function createCachePool() - { - return new NullCache(); - } - - public function testGetItem() - { - $cache = $this->createCachePool(); - - $this->assertNull($cache->get('key')); - } - - public function testHas() - { - $this->assertFalse($this->createCachePool()->has('key')); - } - - public function testGetMultiple() - { - $cache = $this->createCachePool(); - - $keys = ['foo', 'bar', 'baz', 'biz']; - - $default = new \stdClass(); - $items = $cache->getMultiple($keys, $default); - $count = 0; - - foreach ($items as $key => $item) { - $this->assertContains($key, $keys, 'Cache key can not change.'); - $this->assertSame($default, $item); - - // Remove $key for $keys - foreach ($keys as $k => $v) { - if ($v === $key) { - unset($keys[$k]); - } - } - - ++$count; - } - - $this->assertSame(4, $count); - } - - public function testClear() - { - $this->assertTrue($this->createCachePool()->clear()); - } - - public function testDelete() - { - $this->assertTrue($this->createCachePool()->delete('key')); - } - - public function testDeleteMultiple() - { - $this->assertTrue($this->createCachePool()->deleteMultiple(['key', 'foo', 'bar'])); - } - - public function testSet() - { - $cache = $this->createCachePool(); - - $this->assertFalse($cache->set('key', 'val')); - $this->assertNull($cache->get('key')); - } - - public function testSetMultiple() - { - $cache = $this->createCachePool(); - - $this->assertFalse($cache->setMultiple(['key' => 'val'])); - $this->assertNull($cache->get('key')); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PdoCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PdoCacheTest.php deleted file mode 100644 index f5a26341f..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PdoCacheTest.php +++ /dev/null @@ -1,47 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Simple; - -use Symfony\Component\Cache\Simple\PdoCache; -use Symfony\Component\Cache\Tests\Traits\PdoPruneableTrait; - -/** - * @group time-sensitive - */ -class PdoCacheTest extends CacheTestCase -{ - use PdoPruneableTrait; - - protected static $dbFile; - - public static function setUpBeforeClass() - { - if (!\extension_loaded('pdo_sqlite')) { - self::markTestSkipped('Extension pdo_sqlite required.'); - } - - self::$dbFile = tempnam(sys_get_temp_dir(), 'sf_sqlite_cache'); - - $pool = new PdoCache('sqlite:'.self::$dbFile); - $pool->createTable(); - } - - public static function tearDownAfterClass() - { - @unlink(self::$dbFile); - } - - public function createSimpleCache($defaultLifetime = 0) - { - return new PdoCache('sqlite:'.self::$dbFile, 'ns', $defaultLifetime); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PdoDbalCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PdoDbalCacheTest.php deleted file mode 100644 index 4da2b603c..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PdoDbalCacheTest.php +++ /dev/null @@ -1,48 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Simple; - -use Doctrine\DBAL\DriverManager; -use Symfony\Component\Cache\Simple\PdoCache; -use Symfony\Component\Cache\Tests\Traits\PdoPruneableTrait; - -/** - * @group time-sensitive - */ -class PdoDbalCacheTest extends CacheTestCase -{ - use PdoPruneableTrait; - - protected static $dbFile; - - public static function setUpBeforeClass() - { - if (!\extension_loaded('pdo_sqlite')) { - self::markTestSkipped('Extension pdo_sqlite required.'); - } - - self::$dbFile = tempnam(sys_get_temp_dir(), 'sf_sqlite_cache'); - - $pool = new PdoCache(DriverManager::getConnection(['driver' => 'pdo_sqlite', 'path' => self::$dbFile])); - $pool->createTable(); - } - - public static function tearDownAfterClass() - { - @unlink(self::$dbFile); - } - - public function createSimpleCache($defaultLifetime = 0) - { - return new PdoCache(DriverManager::getConnection(['driver' => 'pdo_sqlite', 'path' => self::$dbFile]), '', $defaultLifetime); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PhpArrayCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PhpArrayCacheTest.php deleted file mode 100644 index bcd7dea55..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PhpArrayCacheTest.php +++ /dev/null @@ -1,145 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Simple; - -use Symfony\Component\Cache\Simple\NullCache; -use Symfony\Component\Cache\Simple\PhpArrayCache; -use Symfony\Component\Cache\Tests\Adapter\FilesystemAdapterTest; - -/** - * @group time-sensitive - */ -class PhpArrayCacheTest extends CacheTestCase -{ - protected $skippedTests = [ - 'testBasicUsageWithLongKey' => 'PhpArrayCache does no writes', - - 'testDelete' => 'PhpArrayCache does no writes', - 'testDeleteMultiple' => 'PhpArrayCache does no writes', - 'testDeleteMultipleGenerator' => 'PhpArrayCache does no writes', - - 'testSetTtl' => 'PhpArrayCache does no expiration', - 'testSetMultipleTtl' => 'PhpArrayCache does no expiration', - 'testSetExpiredTtl' => 'PhpArrayCache does no expiration', - 'testSetMultipleExpiredTtl' => 'PhpArrayCache does no expiration', - - 'testGetInvalidKeys' => 'PhpArrayCache does no validation', - 'testGetMultipleInvalidKeys' => 'PhpArrayCache does no validation', - 'testSetInvalidKeys' => 'PhpArrayCache does no validation', - 'testDeleteInvalidKeys' => 'PhpArrayCache does no validation', - 'testDeleteMultipleInvalidKeys' => 'PhpArrayCache does no validation', - 'testSetInvalidTtl' => 'PhpArrayCache does no validation', - 'testSetMultipleInvalidKeys' => 'PhpArrayCache does no validation', - 'testSetMultipleInvalidTtl' => 'PhpArrayCache does no validation', - 'testHasInvalidKeys' => 'PhpArrayCache does no validation', - 'testSetValidData' => 'PhpArrayCache does no validation', - - 'testDefaultLifeTime' => 'PhpArrayCache does not allow configuring a default lifetime.', - 'testPrune' => 'PhpArrayCache just proxies', - ]; - - protected static $file; - - public static function setUpBeforeClass() - { - self::$file = sys_get_temp_dir().'/symfony-cache/php-array-adapter-test.php'; - } - - protected function tearDown() - { - $this->createSimpleCache()->clear(); - - if (file_exists(sys_get_temp_dir().'/symfony-cache')) { - FilesystemAdapterTest::rmdir(sys_get_temp_dir().'/symfony-cache'); - } - } - - public function createSimpleCache() - { - return new PhpArrayCacheWrapper(self::$file, new NullCache()); - } - - public function testStore() - { - $arrayWithRefs = []; - $arrayWithRefs[0] = 123; - $arrayWithRefs[1] = &$arrayWithRefs[0]; - - $object = (object) [ - 'foo' => 'bar', - 'foo2' => 'bar2', - ]; - - $expected = [ - 'null' => null, - 'serializedString' => serialize($object), - 'arrayWithRefs' => $arrayWithRefs, - 'object' => $object, - 'arrayWithObject' => ['bar' => $object], - ]; - - $cache = new PhpArrayCache(self::$file, new NullCache()); - $cache->warmUp($expected); - - foreach ($expected as $key => $value) { - $this->assertSame(serialize($value), serialize($cache->get($key)), 'Warm up should create a PHP file that OPCache can load in memory'); - } - } - - public function testStoredFile() - { - $expected = [ - 'integer' => 42, - 'float' => 42.42, - 'boolean' => true, - 'array_simple' => ['foo', 'bar'], - 'array_associative' => ['foo' => 'bar', 'foo2' => 'bar2'], - ]; - - $cache = new PhpArrayCache(self::$file, new NullCache()); - $cache->warmUp($expected); - - $values = eval(substr(file_get_contents(self::$file), 6)); - - $this->assertSame($expected, $values, 'Warm up should create a PHP file that OPCache can load in memory'); - } -} - -class PhpArrayCacheWrapper extends PhpArrayCache -{ - public function set($key, $value, $ttl = null) - { - \call_user_func(\Closure::bind(function () use ($key, $value) { - $this->values[$key] = $value; - $this->warmUp($this->values); - $this->values = eval(substr(file_get_contents($this->file), 6)); - }, $this, PhpArrayCache::class)); - - return true; - } - - public function setMultiple($values, $ttl = null) - { - if (!\is_array($values) && !$values instanceof \Traversable) { - return parent::setMultiple($values, $ttl); - } - \call_user_func(\Closure::bind(function () use ($values) { - foreach ($values as $key => $value) { - $this->values[$key] = $value; - } - $this->warmUp($this->values); - $this->values = eval(substr(file_get_contents($this->file), 6)); - }, $this, PhpArrayCache::class)); - - return true; - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PhpArrayCacheWithFallbackTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PhpArrayCacheWithFallbackTest.php deleted file mode 100644 index b08c16043..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PhpArrayCacheWithFallbackTest.php +++ /dev/null @@ -1,57 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Simple; - -use Symfony\Component\Cache\Simple\FilesystemCache; -use Symfony\Component\Cache\Simple\PhpArrayCache; -use Symfony\Component\Cache\Tests\Adapter\FilesystemAdapterTest; - -/** - * @group time-sensitive - */ -class PhpArrayCacheWithFallbackTest extends CacheTestCase -{ - protected $skippedTests = [ - 'testGetInvalidKeys' => 'PhpArrayCache does no validation', - 'testGetMultipleInvalidKeys' => 'PhpArrayCache does no validation', - 'testDeleteInvalidKeys' => 'PhpArrayCache does no validation', - 'testDeleteMultipleInvalidKeys' => 'PhpArrayCache does no validation', - //'testSetValidData' => 'PhpArrayCache does no validation', - 'testSetInvalidKeys' => 'PhpArrayCache does no validation', - 'testSetInvalidTtl' => 'PhpArrayCache does no validation', - 'testSetMultipleInvalidKeys' => 'PhpArrayCache does no validation', - 'testSetMultipleInvalidTtl' => 'PhpArrayCache does no validation', - 'testHasInvalidKeys' => 'PhpArrayCache does no validation', - 'testPrune' => 'PhpArrayCache just proxies', - ]; - - protected static $file; - - public static function setUpBeforeClass() - { - self::$file = sys_get_temp_dir().'/symfony-cache/php-array-adapter-test.php'; - } - - protected function tearDown() - { - $this->createSimpleCache()->clear(); - - if (file_exists(sys_get_temp_dir().'/symfony-cache')) { - FilesystemAdapterTest::rmdir(sys_get_temp_dir().'/symfony-cache'); - } - } - - public function createSimpleCache($defaultLifetime = 0) - { - return new PhpArrayCache(self::$file, new FilesystemCache('php-array-fallback', $defaultLifetime)); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PhpFilesCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PhpFilesCacheTest.php deleted file mode 100644 index 936f29a43..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/PhpFilesCacheTest.php +++ /dev/null @@ -1,42 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Simple; - -use Psr\SimpleCache\CacheInterface; -use Symfony\Component\Cache\Simple\PhpFilesCache; - -/** - * @group time-sensitive - */ -class PhpFilesCacheTest extends CacheTestCase -{ - protected $skippedTests = [ - 'testDefaultLifeTime' => 'PhpFilesCache does not allow configuring a default lifetime.', - ]; - - public function createSimpleCache() - { - if (!PhpFilesCache::isSupported()) { - $this->markTestSkipped('OPcache extension is not enabled.'); - } - - return new PhpFilesCache('sf-cache'); - } - - protected function isPruned(CacheInterface $cache, $name) - { - $getFileMethod = (new \ReflectionObject($cache))->getMethod('getFile'); - $getFileMethod->setAccessible(true); - - return !file_exists($getFileMethod->invoke($cache, $name)); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/Psr6CacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/Psr6CacheTest.php deleted file mode 100644 index 1bc75c906..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/Psr6CacheTest.php +++ /dev/null @@ -1,30 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Simple; - -use Symfony\Component\Cache\Adapter\FilesystemAdapter; -use Symfony\Component\Cache\Simple\Psr6Cache; - -/** - * @group time-sensitive - */ -class Psr6CacheTest extends CacheTestCase -{ - protected $skippedTests = [ - 'testPrune' => 'Psr6Cache just proxies', - ]; - - public function createSimpleCache($defaultLifetime = 0) - { - return new Psr6Cache(new FilesystemAdapter('', $defaultLifetime)); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/RedisArrayCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/RedisArrayCacheTest.php deleted file mode 100644 index ec5e4c06e..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/RedisArrayCacheTest.php +++ /dev/null @@ -1,24 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Simple; - -class RedisArrayCacheTest extends AbstractRedisCacheTest -{ - public static function setUpBeforeClass() - { - parent::setupBeforeClass(); - if (!class_exists('RedisArray')) { - self::markTestSkipped('The RedisArray class is required.'); - } - self::$redis = new \RedisArray([getenv('REDIS_HOST')], ['lazy_connect' => true]); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/RedisCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/RedisCacheTest.php deleted file mode 100644 index 8e3f60883..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/RedisCacheTest.php +++ /dev/null @@ -1,82 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Simple; - -use Symfony\Component\Cache\Simple\RedisCache; - -class RedisCacheTest extends AbstractRedisCacheTest -{ - public static function setUpBeforeClass() - { - parent::setupBeforeClass(); - self::$redis = RedisCache::createConnection('redis://'.getenv('REDIS_HOST')); - } - - public function testCreateConnection() - { - $redisHost = getenv('REDIS_HOST'); - - $redis = RedisCache::createConnection('redis://'.$redisHost); - $this->assertInstanceOf(\Redis::class, $redis); - $this->assertTrue($redis->isConnected()); - $this->assertSame(0, $redis->getDbNum()); - - $redis = RedisCache::createConnection('redis://'.$redisHost.'/2'); - $this->assertSame(2, $redis->getDbNum()); - - $redis = RedisCache::createConnection('redis://'.$redisHost, ['timeout' => 3]); - $this->assertEquals(3, $redis->getTimeout()); - - $redis = RedisCache::createConnection('redis://'.$redisHost.'?timeout=4'); - $this->assertEquals(4, $redis->getTimeout()); - - $redis = RedisCache::createConnection('redis://'.$redisHost, ['read_timeout' => 5]); - $this->assertEquals(5, $redis->getReadTimeout()); - } - - /** - * @dataProvider provideFailedCreateConnection - */ - public function testFailedCreateConnection($dsn) - { - $this->expectException('Symfony\Component\Cache\Exception\InvalidArgumentException'); - $this->expectExceptionMessage('Redis connection '); - RedisCache::createConnection($dsn); - } - - public function provideFailedCreateConnection() - { - return [ - ['redis://localhost:1234'], - ['redis://foo@localhost'], - ['redis://localhost/123'], - ]; - } - - /** - * @dataProvider provideInvalidCreateConnection - */ - public function testInvalidCreateConnection($dsn) - { - $this->expectException('Symfony\Component\Cache\Exception\InvalidArgumentException'); - $this->expectExceptionMessage('Invalid Redis DSN'); - RedisCache::createConnection($dsn); - } - - public function provideInvalidCreateConnection() - { - return [ - ['foo://localhost'], - ['redis://'], - ]; - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/RedisClusterCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/RedisClusterCacheTest.php deleted file mode 100644 index 6b7f8039d..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/RedisClusterCacheTest.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Simple; - -class RedisClusterCacheTest extends AbstractRedisCacheTest -{ - public static function setUpBeforeClass() - { - if (!class_exists('RedisCluster')) { - self::markTestSkipped('The RedisCluster class is required.'); - } - if (!$hosts = getenv('REDIS_CLUSTER_HOSTS')) { - self::markTestSkipped('REDIS_CLUSTER_HOSTS env var is not defined.'); - } - - self::$redis = new \RedisCluster(null, explode(' ', $hosts)); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/TraceableCacheTest.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/TraceableCacheTest.php deleted file mode 100644 index e684caf36..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Simple/TraceableCacheTest.php +++ /dev/null @@ -1,171 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Simple; - -use Symfony\Component\Cache\Simple\FilesystemCache; -use Symfony\Component\Cache\Simple\TraceableCache; - -/** - * @group time-sensitive - */ -class TraceableCacheTest extends CacheTestCase -{ - protected $skippedTests = [ - 'testPrune' => 'TraceableCache just proxies', - ]; - - public function createSimpleCache($defaultLifetime = 0) - { - return new TraceableCache(new FilesystemCache('', $defaultLifetime)); - } - - public function testGetMissTrace() - { - $pool = $this->createSimpleCache(); - $pool->get('k'); - $calls = $pool->getCalls(); - $this->assertCount(1, $calls); - - $call = $calls[0]; - $this->assertSame('get', $call->name); - $this->assertSame(['k' => false], $call->result); - $this->assertSame(0, $call->hits); - $this->assertSame(1, $call->misses); - $this->assertNotEmpty($call->start); - $this->assertNotEmpty($call->end); - } - - public function testGetHitTrace() - { - $pool = $this->createSimpleCache(); - $pool->set('k', 'foo'); - $pool->get('k'); - $calls = $pool->getCalls(); - $this->assertCount(2, $calls); - - $call = $calls[1]; - $this->assertSame(1, $call->hits); - $this->assertSame(0, $call->misses); - } - - public function testGetMultipleMissTrace() - { - $pool = $this->createSimpleCache(); - $pool->set('k1', 123); - $values = $pool->getMultiple(['k0', 'k1']); - foreach ($values as $value) { - } - $calls = $pool->getCalls(); - $this->assertCount(2, $calls); - - $call = $calls[1]; - $this->assertSame('getMultiple', $call->name); - $this->assertSame(['k1' => true, 'k0' => false], $call->result); - $this->assertSame(1, $call->misses); - $this->assertNotEmpty($call->start); - $this->assertNotEmpty($call->end); - } - - public function testHasMissTrace() - { - $pool = $this->createSimpleCache(); - $pool->has('k'); - $calls = $pool->getCalls(); - $this->assertCount(1, $calls); - - $call = $calls[0]; - $this->assertSame('has', $call->name); - $this->assertSame(['k' => false], $call->result); - $this->assertNotEmpty($call->start); - $this->assertNotEmpty($call->end); - } - - public function testHasHitTrace() - { - $pool = $this->createSimpleCache(); - $pool->set('k', 'foo'); - $pool->has('k'); - $calls = $pool->getCalls(); - $this->assertCount(2, $calls); - - $call = $calls[1]; - $this->assertSame('has', $call->name); - $this->assertSame(['k' => true], $call->result); - $this->assertNotEmpty($call->start); - $this->assertNotEmpty($call->end); - } - - public function testDeleteTrace() - { - $pool = $this->createSimpleCache(); - $pool->delete('k'); - $calls = $pool->getCalls(); - $this->assertCount(1, $calls); - - $call = $calls[0]; - $this->assertSame('delete', $call->name); - $this->assertSame(['k' => true], $call->result); - $this->assertSame(0, $call->hits); - $this->assertSame(0, $call->misses); - $this->assertNotEmpty($call->start); - $this->assertNotEmpty($call->end); - } - - public function testDeleteMultipleTrace() - { - $pool = $this->createSimpleCache(); - $arg = ['k0', 'k1']; - $pool->deleteMultiple($arg); - $calls = $pool->getCalls(); - $this->assertCount(1, $calls); - - $call = $calls[0]; - $this->assertSame('deleteMultiple', $call->name); - $this->assertSame(['keys' => $arg, 'result' => true], $call->result); - $this->assertSame(0, $call->hits); - $this->assertSame(0, $call->misses); - $this->assertNotEmpty($call->start); - $this->assertNotEmpty($call->end); - } - - public function testTraceSetTrace() - { - $pool = $this->createSimpleCache(); - $pool->set('k', 'foo'); - $calls = $pool->getCalls(); - $this->assertCount(1, $calls); - - $call = $calls[0]; - $this->assertSame('set', $call->name); - $this->assertSame(['k' => true], $call->result); - $this->assertSame(0, $call->hits); - $this->assertSame(0, $call->misses); - $this->assertNotEmpty($call->start); - $this->assertNotEmpty($call->end); - } - - public function testSetMultipleTrace() - { - $pool = $this->createSimpleCache(); - $pool->setMultiple(['k' => 'foo']); - $calls = $pool->getCalls(); - $this->assertCount(1, $calls); - - $call = $calls[0]; - $this->assertSame('setMultiple', $call->name); - $this->assertSame(['keys' => ['k'], 'result' => true], $call->result); - $this->assertSame(0, $call->hits); - $this->assertSame(0, $call->misses); - $this->assertNotEmpty($call->start); - $this->assertNotEmpty($call->end); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/Tests/Traits/PdoPruneableTrait.php b/advancedcontentfilter/vendor/symfony/cache/Tests/Traits/PdoPruneableTrait.php deleted file mode 100644 index c405de703..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/Tests/Traits/PdoPruneableTrait.php +++ /dev/null @@ -1,34 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Tests\Traits; - -trait PdoPruneableTrait -{ - protected function isPruned($cache, $name) - { - $o = new \ReflectionObject($cache); - - if (!$o->hasMethod('getConnection')) { - self::fail('Cache does not have "getConnection()" method.'); - } - - $getPdoConn = $o->getMethod('getConnection'); - $getPdoConn->setAccessible(true); - - /** @var \Doctrine\DBAL\Statement|\PDOStatement $select */ - $select = $getPdoConn->invoke($cache)->prepare('SELECT 1 FROM cache_items WHERE item_id LIKE :id'); - $select->bindValue(':id', sprintf('%%%s', $name)); - $result = $select->execute(); - - return 1 !== (int) (\is_object($result) ? $result->fetchOne() : $select->fetch(\PDO::FETCH_COLUMN)); - } -} diff --git a/advancedcontentfilter/vendor/symfony/cache/phpunit.xml.dist b/advancedcontentfilter/vendor/symfony/cache/phpunit.xml.dist deleted file mode 100644 index c35458ca4..000000000 --- a/advancedcontentfilter/vendor/symfony/cache/phpunit.xml.dist +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - ./Tests/ - - - - - - ./ - - ./Tests - ./vendor - - - - - - - - - - - Cache\IntegrationTests - Doctrine\Common\Cache - Symfony\Component\Cache - Symfony\Component\Cache\Tests\Fixtures - Symfony\Component\Cache\Traits - - - - - - - diff --git a/advancedcontentfilter/vendor/symfony/polyfill-apcu/Apcu.php b/advancedcontentfilter/vendor/symfony/polyfill-apcu/Apcu.php deleted file mode 100644 index 4dc5bf9a3..000000000 --- a/advancedcontentfilter/vendor/symfony/polyfill-apcu/Apcu.php +++ /dev/null @@ -1,106 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Apcu; - -/** - * Apcu for Zend Server Data Cache. - * - * @author Kate Gray - * @author Nicolas Grekas - * - * @internal - */ -final class Apcu -{ - public static function apcu_add($key, $var = null, $ttl = 0) - { - if (!\is_array($key)) { - return apc_add($key, $var, $ttl); - } - - $errors = []; - foreach ($key as $k => $v) { - if (!apc_add($k, $v, $ttl)) { - $errors[$k] = -1; - } - } - - return $errors; - } - - public static function apcu_store($key, $var = null, $ttl = 0) - { - if (!\is_array($key)) { - return apc_store($key, $var, $ttl); - } - - $errors = []; - foreach ($key as $k => $v) { - if (!apc_store($k, $v, $ttl)) { - $errors[$k] = -1; - } - } - - return $errors; - } - - public static function apcu_exists($keys) - { - if (!\is_array($keys)) { - return apc_exists($keys); - } - - $existing = []; - foreach ($keys as $k) { - if (apc_exists($k)) { - $existing[$k] = true; - } - } - - return $existing; - } - - public static function apcu_fetch($key, &$success = null) - { - if (!\is_array($key)) { - return apc_fetch($key, $success); - } - - $succeeded = true; - $values = []; - foreach ($key as $k) { - $v = apc_fetch($k, $success); - if ($success) { - $values[$k] = $v; - } else { - $succeeded = false; - } - } - $success = $succeeded; - - return $values; - } - - public static function apcu_delete($key) - { - if (!\is_array($key)) { - return apc_delete($key); - } - - $success = true; - foreach ($key as $k) { - $success = apc_delete($k) && $success; - } - - return $success; - } -} diff --git a/advancedcontentfilter/vendor/symfony/polyfill-apcu/LICENSE b/advancedcontentfilter/vendor/symfony/polyfill-apcu/LICENSE deleted file mode 100644 index 6e3afce69..000000000 --- a/advancedcontentfilter/vendor/symfony/polyfill-apcu/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2015-present Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/advancedcontentfilter/vendor/symfony/polyfill-apcu/README.md b/advancedcontentfilter/vendor/symfony/polyfill-apcu/README.md deleted file mode 100644 index 57f4bf6bb..000000000 --- a/advancedcontentfilter/vendor/symfony/polyfill-apcu/README.md +++ /dev/null @@ -1,12 +0,0 @@ -Symfony Polyfill / APCu -======================== - -This component provides `apcu_*` functions and the `APCuIterator` class to users of the legacy APC extension. - -More information can be found in the -[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md). - -License -======= - -This library is released under the [MIT license](LICENSE). diff --git a/advancedcontentfilter/vendor/symfony/polyfill-apcu/bootstrap.php b/advancedcontentfilter/vendor/symfony/polyfill-apcu/bootstrap.php deleted file mode 100644 index 96b2706ad..000000000 --- a/advancedcontentfilter/vendor/symfony/polyfill-apcu/bootstrap.php +++ /dev/null @@ -1,83 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -use Symfony\Polyfill\Apcu as p; - -if (!extension_loaded('apc') && !extension_loaded('apcu')) { - return; -} - -if (\PHP_VERSION_ID >= 80000) { - return require __DIR__.'/bootstrap80.php'; -} - -if (extension_loaded('Zend Data Cache')) { - if (!function_exists('apcu_add')) { - function apcu_add($key, $value = null, $ttl = 0) { return p\Apcu::apcu_add($key, $value, $ttl); } - } - if (!function_exists('apcu_delete')) { - function apcu_delete($key) { return p\Apcu::apcu_delete($key); } - } - if (!function_exists('apcu_exists')) { - function apcu_exists($key) { return p\Apcu::apcu_exists($key); } - } - if (!function_exists('apcu_fetch')) { - function apcu_fetch($key, &$success = null) { return p\Apcu::apcu_fetch($key, $success); } - } - if (!function_exists('apcu_store')) { - function apcu_store($key, $value = null, $ttl = 0) { return p\Apcu::apcu_store($key, $value, $ttl); } - } -} else { - if (!function_exists('apcu_add')) { - function apcu_add($key, $value = null, $ttl = 0) { return apc_add($key, $value, $ttl); } - } - if (!function_exists('apcu_delete')) { - function apcu_delete($key) { return apc_delete($key); } - } - if (!function_exists('apcu_exists')) { - function apcu_exists($key) { return apc_exists($key); } - } - if (!function_exists('apcu_fetch')) { - function apcu_fetch($key, &$success = null) { return apc_fetch($key, $success); } - } - if (!function_exists('apcu_store')) { - function apcu_store($key, $value = null, $ttl = 0) { return apc_store($key, $value, $ttl); } - } -} - -if (!function_exists('apcu_cache_info')) { - function apcu_cache_info($limited = false) { return apc_cache_info('user', $limited); } -} -if (!function_exists('apcu_cas')) { - function apcu_cas($key, $old, $new) { return apc_cas($key, $old, $new); } -} -if (!function_exists('apcu_clear_cache')) { - function apcu_clear_cache() { return apc_clear_cache('user'); } -} -if (!function_exists('apcu_dec')) { - function apcu_dec($key, $step = 1, &$success = false) { return apc_dec($key, $step, $success); } -} -if (!function_exists('apcu_inc')) { - function apcu_inc($key, $step = 1, &$success = false) { return apc_inc($key, $step, $success); } -} -if (!function_exists('apcu_sma_info')) { - function apcu_sma_info($limited = false) { return apc_sma_info($limited); } -} - -if (!class_exists('APCuIterator', false) && class_exists('APCIterator', false)) { - class APCuIterator extends APCIterator - { - public function __construct($search = null, $format = \APC_ITER_ALL, $chunk_size = 100, $list = \APC_LIST_ACTIVE) - { - parent::__construct('user', $search, $format, $chunk_size, $list); - } - } -} diff --git a/advancedcontentfilter/vendor/symfony/polyfill-apcu/bootstrap80.php b/advancedcontentfilter/vendor/symfony/polyfill-apcu/bootstrap80.php deleted file mode 100644 index 69e9f1603..000000000 --- a/advancedcontentfilter/vendor/symfony/polyfill-apcu/bootstrap80.php +++ /dev/null @@ -1,75 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -use Symfony\Polyfill\Apcu as p; - -if (extension_loaded('Zend Data Cache')) { - if (!function_exists('apcu_add')) { - function apcu_add($key, mixed $value, ?int $ttl = 0): array|bool { return p\Apcu::apcu_add($key, $value, (int) $ttl); } - } - if (!function_exists('apcu_delete')) { - function apcu_delete($key): array|bool { return p\Apcu::apcu_delete($key); } - } - if (!function_exists('apcu_exists')) { - function apcu_exists($key): array|bool { return p\Apcu::apcu_exists($key); } - } - if (!function_exists('apcu_fetch')) { - function apcu_fetch($key, &$success = null): mixed { return p\Apcu::apcu_fetch($key, $success); } - } - if (!function_exists('apcu_store')) { - function apcu_store($key, mixed $value, ?int $ttl = 0): array|bool { return p\Apcu::apcu_store($key, $value, (int) $ttl); } - } -} else { - if (!function_exists('apcu_add')) { - function apcu_add($key, mixed $value, ?int $ttl = 0): array|bool { return apc_add($key, $value, (int) $ttl); } - } - if (!function_exists('apcu_delete')) { - function apcu_delete($key): array|bool { return apc_delete($key); } - } - if (!function_exists('apcu_exists')) { - function apcu_exists($key): array|bool { return apc_exists($key); } - } - if (!function_exists('apcu_fetch')) { - function apcu_fetch($key, &$success = null) { return apc_fetch($key, $success); } - } - if (!function_exists('apcu_store')) { - function apcu_store($key, mixed $value, ?int $ttl = 0): array|bool { return apc_store($key, $value, (int) $ttl); } - } -} - -if (!function_exists('apcu_cache_info')) { - function apcu_cache_info($limited = false) { return apc_cache_info('user', $limited); } -} -if (!function_exists('apcu_cas')) { - function apcu_cas($key, $old, $new) { return apc_cas($key, $old, $new); } -} -if (!function_exists('apcu_clear_cache')) { - function apcu_clear_cache() { return apc_clear_cache('user'); } -} -if (!function_exists('apcu_dec')) { - function apcu_dec($key, $step = 1, &$success = false) { return apc_dec($key, $step, $success); } -} -if (!function_exists('apcu_inc')) { - function apcu_inc($key, $step = 1, &$success = false) { return apc_inc($key, $step, $success); } -} -if (!function_exists('apcu_sma_info')) { - function apcu_sma_info($limited = false) { return apc_sma_info($limited); } -} - -if (!class_exists('APCuIterator', false) && class_exists('APCIterator', false)) { - class APCuIterator extends APCIterator - { - public function __construct($search = null, $format = APC_ITER_ALL, $chunk_size = 100, $list = APC_LIST_ACTIVE) - { - parent::__construct('user', $search, $format, $chunk_size, $list); - } - } -} diff --git a/advancedcontentfilter/vendor/symfony/polyfill-apcu/composer.json b/advancedcontentfilter/vendor/symfony/polyfill-apcu/composer.json deleted file mode 100644 index e92524f3b..000000000 --- a/advancedcontentfilter/vendor/symfony/polyfill-apcu/composer.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "name": "symfony/polyfill-apcu", - "type": "library", - "description": "Symfony polyfill backporting apcu_* functions to lower PHP versions", - "keywords": ["polyfill", "shim", "compatibility", "portable", "apcu"], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.1" - }, - "autoload": { - "psr-4": { "Symfony\\Polyfill\\Apcu\\": "" }, - "files": [ "bootstrap.php" ] - }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - } -} From 7fcbd76c6b9a0d2b8a704fc5739c4f2d31f15c9f Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 20 Nov 2024 07:03:42 +0000 Subject: [PATCH 220/388] Bluesky: Improved handling of starter packs --- bluesky/bluesky.php | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index d719eecb7..a78480b61 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -1481,11 +1481,7 @@ function bluesky_add_media(stdClass $embed, array $item, int $fetch_uid, int $le if (!empty($embed->record->record->$type)) { $embed_type = $embed->record->record->$type; if ($embed_type == 'app.bsky.graph.starterpack') { - Logger::debug('Starterpacks are not fetched like posts', ['original-uri' => $original_uri]); - if (empty($item['body'])) { - // @todo process starterpack - $item['body'] = '[url=' . $embed->record->record->list . ']' . $embed->record->record->name . '[/url]'; - } + bluesky_add_starterpack($item, $embed->record); break; } } @@ -1523,6 +1519,30 @@ function bluesky_add_media(stdClass $embed, array $item, int $fetch_uid, int $le return $item; } +function bluesky_add_starterpack(array $item, stdClass $record) +{ + Logger::debug('Received starterpack', ['uri-id' => $item['uri-id'], 'guid' => $item['guid'], 'uri' => $record->uri]); + if (!preg_match('#^at://(.+)/app.bsky.graph.starterpack/(.+)#', $record->uri, $matches)) { + return; + } + + $media = [ + 'uri-id' => $item['uri-id'], + 'type' => Post\Media::HTML, + 'url' => 'https://bsky.app/starter-pack/' . $matches[1] . '/' . $matches[2], + 'name' => $record->record->name, + 'description' => $record->record->description, + ]; + + Post\Media::insert($media); + + $fields = [ + 'name' => $record->record->name, + 'description' => $record->record->description, + ]; + Post\Media::update($fields, ['uri-id' => $media['uri-id'], 'url' => $media['url']]); +} + function bluesky_get_uri(stdClass $post): string { if (empty($post->cid)) { From f52bb75c97125045e6e5b2f9d1d743639120eb99 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 20 Nov 2024 21:39:09 +0000 Subject: [PATCH 221/388] Blockbot: Drupal added --- blockbot/blockbot.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blockbot/blockbot.php b/blockbot/blockbot.php index adf0a7c27..022f188d4 100644 --- a/blockbot/blockbot.php +++ b/blockbot/blockbot.php @@ -461,7 +461,7 @@ function blockbot_is_social_media(array $parts): bool $agents = [ 'facebookexternalhit', 'twitterbot', 'mastodon', 'facebookexternalua', - 'friendica', 'diasporafederation', 'buzzrelay', 'activityrelay', + 'friendica', 'diasporafederation', 'buzzrelay', 'activityrelay', 'drupal', 'aoderelay', 'ap-relay', 'peertube', 'misskey', 'pleroma', 'foundkey', 'akkoma', 'lemmy', 'calckey', 'mobilizon', 'zot', 'camo-rs', 'gotosocial', 'pixelfed', 'pixelfedbot', 'app.wafrn.net', 'go-camo', 'http://a.gup.pe', 'iceshrimp', From 2ea40dc897c90d65c7be085fbd66fb5cc8d70c96 Mon Sep 17 00:00:00 2001 From: Artur Weigandt Date: Sat, 23 Nov 2024 22:28:59 +0100 Subject: [PATCH 222/388] Remove unused App paramter in securemail addon --- securemail/securemail.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/securemail/securemail.php b/securemail/securemail.php index 5390ebd14..611255872 100644 --- a/securemail/securemail.php +++ b/securemail/securemail.php @@ -82,7 +82,7 @@ function securemail_settings_post(array &$b) DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'securemail', 'enable', $enable); if (!empty($_POST['securemail-test'])) { - $res = DI::emailer()->send(new SecureTestEmail(DI::app(), DI::config(), DI::pConfig(), DI::baseUrl())); + $res = DI::emailer()->send(new SecureTestEmail(DI::config(), DI::pConfig(), DI::baseUrl())); // revert to saved value DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'securemail', 'enable', $enable); From ecf0edb520c50edca5512f0c450761c5d9d56121 Mon Sep 17 00:00:00 2001 From: Artur Weigandt Date: Sat, 23 Nov 2024 09:32:43 +0100 Subject: [PATCH 223/388] Remove unused parameter webdav_storage addon --- webdav_storage/webdav_storage.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/webdav_storage/webdav_storage.php b/webdav_storage/webdav_storage.php index adcbea29c..fd2eb0d97 100644 --- a/webdav_storage/webdav_storage.php +++ b/webdav_storage/webdav_storage.php @@ -8,11 +8,10 @@ use Friendica\Addon\webdav_storage\src\WebDav; use Friendica\Addon\webdav_storage\src\WebDavConfig; -use Friendica\App; use Friendica\Core\Hook; use Friendica\DI; -function webdav_storage_install($a) +function webdav_storage_install() { Hook::register('storage_instance' , __FILE__, 'webdav_storage_instance'); Hook::register('storage_config' , __FILE__, 'webdav_storage_config'); From bf679262b0b238378a75ed0c7f7436cfe999ac7d Mon Sep 17 00:00:00 2001 From: Artur Weigandt Date: Sat, 23 Nov 2024 22:42:52 +0100 Subject: [PATCH 224/388] Remove unused parameter in saml addon --- saml/saml.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/saml/saml.php b/saml/saml.php index 56dd0f5d2..9f065355c 100755 --- a/saml/saml.php +++ b/saml/saml.php @@ -161,7 +161,7 @@ function saml_sso_reply() } if (!empty($user['uid'])) { - DI::auth()->setForUser(DI::app(), $user); + DI::auth()->setForUser($user); } if (isset($_POST['RelayState']) && Utils::getSelfURL() != $_POST['RelayState']) { From 348c44c972e54090f329511e992c7ea5618dd862 Mon Sep 17 00:00:00 2001 From: Art4 Date: Sun, 24 Nov 2024 15:36:37 +0000 Subject: [PATCH 225/388] inline slim routes and middlewares into advancedcontentfilter addon --- .../advancedcontentfilter.php | 25 +++++++++++-- advancedcontentfilter/src/middlewares.php | 32 ----------------- advancedcontentfilter/src/routes.php | 36 ------------------- 3 files changed, 23 insertions(+), 70 deletions(-) delete mode 100644 advancedcontentfilter/src/middlewares.php delete mode 100644 advancedcontentfilter/src/routes.php diff --git a/advancedcontentfilter/advancedcontentfilter.php b/advancedcontentfilter/advancedcontentfilter.php index 418b253ed..84eb468cb 100644 --- a/advancedcontentfilter/advancedcontentfilter.php +++ b/advancedcontentfilter/advancedcontentfilter.php @@ -192,9 +192,30 @@ function advancedcontentfilter_init() if (DI::args()->getArgc() > 1 && DI::args()->getArgv()[1] == 'api') { $slim = \Slim\Factory\AppFactory::create(); - require __DIR__ . '/src/middlewares.php'; + /** + * The routing middleware should be added before the ErrorMiddleware + * Otherwise exceptions thrown from it will not be handled + */ + $slim->addRoutingMiddleware(); + + $slim->addErrorMiddleware(true, true, true, DI::logger()); + + // register routes + $slim->group('/advancedcontentfilter/api', function (\Slim\Routing\RouteCollectorProxy $app) { + $app->group('/rules', function (\Slim\Routing\RouteCollectorProxy $app) { + $app->get('', 'advancedcontentfilter_get_rules'); + $app->post('', 'advancedcontentfilter_post_rules'); + + $app->get('/{id}', 'advancedcontentfilter_get_rules_id'); + $app->put('/{id}', 'advancedcontentfilter_put_rules_id'); + $app->delete('/{id}', 'advancedcontentfilter_delete_rules_id'); + }); + + $app->group('/variables', function (\Slim\Routing\RouteCollectorProxy $app) { + $app->get('/{guid}', 'advancedcontentfilter_get_variables_guid'); + }); + }); - require __DIR__ . '/src/routes.php'; $slim->run(); exit; diff --git a/advancedcontentfilter/src/middlewares.php b/advancedcontentfilter/src/middlewares.php deleted file mode 100644 index 2b831473d..000000000 --- a/advancedcontentfilter/src/middlewares.php +++ /dev/null @@ -1,32 +0,0 @@ -. - * - */ - -use Friendica\DI; - -/** @var $slim \Slim\App */ - -/** - * The routing middleware should be added before the ErrorMiddleware - * Otherwise exceptions thrown from it will not be handled - */ -$slim->addRoutingMiddleware(); - -$errorMiddleware = $slim->addErrorMiddleware(true, true, true, DI::logger()); diff --git a/advancedcontentfilter/src/routes.php b/advancedcontentfilter/src/routes.php deleted file mode 100644 index a46f1b4b5..000000000 --- a/advancedcontentfilter/src/routes.php +++ /dev/null @@ -1,36 +0,0 @@ -. - * - */ - -/* @var $slim Slim\App */ -$slim->group('/advancedcontentfilter/api', function (\Slim\Routing\RouteCollectorProxy $app) { - $app->group('/rules', function (\Slim\Routing\RouteCollectorProxy $app) { - $app->get('', 'advancedcontentfilter_get_rules'); - $app->post('', 'advancedcontentfilter_post_rules'); - - $app->get('/{id}', 'advancedcontentfilter_get_rules_id'); - $app->put('/{id}', 'advancedcontentfilter_put_rules_id'); - $app->delete('/{id}', 'advancedcontentfilter_delete_rules_id'); - }); - - $app->group('/variables', function (\Slim\Routing\RouteCollectorProxy $app) { - $app->get('/{guid}', 'advancedcontentfilter_get_variables_guid'); - }); -}); From e9d3afb483eff053d0e53d2f55d9d59cd6d7f29e Mon Sep 17 00:00:00 2001 From: Art4 Date: Sun, 24 Nov 2024 19:51:37 +0000 Subject: [PATCH 226/388] Fix errors in tictac addon --- tictac/tictac.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tictac/tictac.php b/tictac/tictac.php index 0f9f4fb63..dc9f0348a 100644 --- a/tictac/tictac.php +++ b/tictac/tictac.php @@ -70,6 +70,7 @@ class tictac { private $dimen; private $first_move = true; private $handicap = 0; + private $mefirst; private $yours; private $mine; private $winning_play; @@ -161,10 +162,10 @@ class tictac { ]; - function __construct($dimen,$handicap,$mefirst,$yours,$mine) { + function __construct($dimen, $handicap, $mefirst, $yours, $mine) { $this->dimen = 3; - $this->handicap = (($handicap) ? 1 : 0); - $this->mefirst = (($mefirst) ? 1 : 0); + $this->handicap = $handicap ? 1 : 0; + $this->mefirst = $mefirst ? 1 : 0; $this->yours = str_replace('XXX','',$yours); $this->mine = $mine; $this->you = $this->parse_moves('you'); @@ -175,6 +176,7 @@ class tictac { } function play() { + $o = ''; if($this->first_move) { if(rand(0,1) == 1) { From 6df91dd37bd96bac74a2e347640b0a81684c3028 Mon Sep 17 00:00:00 2001 From: Art4 Date: Sun, 24 Nov 2024 19:55:54 +0000 Subject: [PATCH 227/388] Fix errors in statusnet addon --- statusnet/library/codebirdsn.php | 7 +++---- tictac/tictac.php | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/statusnet/library/codebirdsn.php b/statusnet/library/codebirdsn.php index 020c69c48..325bcb072 100644 --- a/statusnet/library/codebirdsn.php +++ b/statusnet/library/codebirdsn.php @@ -762,13 +762,13 @@ class CodebirdSN * @param string $method The API method to call * @param array $params The parameters to send along * - * @return void + * @return string */ protected function _buildMultipart($method, $params) { // well, files will only work in multipart methods if (! $this->_detectMultipart($method)) { - return; + return ''; } // only check specific parameters @@ -783,7 +783,7 @@ class CodebirdSN ); // method might have files? if (! in_array($method, array_keys($possible_files))) { - return; + return ''; } $possible_files = explode(' ', $possible_files[$method]); @@ -794,7 +794,6 @@ class CodebirdSN // is it an array? if (is_array($value)) { throw new \Exception('Using URL-encoded parameters is not supported for uploading media.'); - continue; } // check for filenames diff --git a/tictac/tictac.php b/tictac/tictac.php index dc9f0348a..101038355 100644 --- a/tictac/tictac.php +++ b/tictac/tictac.php @@ -631,7 +631,7 @@ function winning_move() { function draw_board() { if(! strlen($this->yours)) $this->yours = 'XXX'; - $o .= "

handicap}/{$this->mefirst}/{$this->dimen}/{$this->yours}/{$this->mine}\" method=\"post\" />"; + $o = "handicap}/{$this->mefirst}/{$this->dimen}/{$this->yours}/{$this->mine}\" method=\"post\" />"; for($x = 0; $x < $this->dimen; $x ++) { $o .= ''; for($y = 0; $y < $this->dimen; $y ++) { From 422e4fd48f80487bf751acc3b19ebe6b5b1d8fc2 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 24 Nov 2024 09:11:25 +0000 Subject: [PATCH 228/388] Bluesky: Fetch quoted post for "uid=0" --- bluesky/bluesky.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index a78480b61..74d4fee80 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -1036,7 +1036,7 @@ function bluesky_complete_post(stdClass $post, int $uid, int $post_reason, int $ } if ($complete) { - $uri = bluesky_fetch_missing_post($post->uri, $uid, $uid, $post_reason, $causer, 0, $last_poll, '', true); + $uri = bluesky_fetch_missing_post(bluesky_get_uri($post), $uid, $uid, $post_reason, $causer, 0, $last_poll, '', true); $uri_id = bluesky_fetch_uri_id($uri, $uid); } else { $uri_id = bluesky_process_post($post, $uid, $uid, $post_reason, $causer, 0, $last_poll); @@ -1060,7 +1060,6 @@ function bluesky_process_reason(stdClass $reason, string $uri, int $uid) 'wall' => false, 'uri' => $reason->by->did . '/app.bsky.feed.repost/' . $reason->indexedAt, 'private' => Item::UNLISTED, - 'verb' => Activity::POST, 'contact-id' => $contact['id'], 'author-name' => $contact['name'], 'author-link' => $contact['url'], @@ -1485,7 +1484,12 @@ function bluesky_add_media(stdClass $embed, array $item, int $fetch_uid, int $le break; } } - $uri = bluesky_fetch_missing_post($uri, $item['uid'], $fetch_uid, Item::PR_FETCHED, $item['contact-id'], $level, $last_poll); + $fetched_uri = bluesky_fetch_post($uri, $item['uid']); + if (!$fetched_uri) { + $uri = bluesky_fetch_missing_post($uri, 0, $fetch_uid, Item::PR_FETCHED, $item['contact-id'], $level, $last_poll); + } else { + $uri = $fetched_uri; + } if ($uri) { $shared = Post::selectFirst(['uri-id'], ['uri' => $uri, 'uid' => [$item['uid'], 0]]); $uri_id = $shared['uri-id'] ?? 0; From d7d6a43655734a1ebeb0d70481452447baf5a80e Mon Sep 17 00:00:00 2001 From: Art4 Date: Tue, 26 Nov 2024 07:55:01 +0000 Subject: [PATCH 229/388] Add checks for CLD2Detector ans CLD2Encoding classes --- cld/cld.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/cld/cld.php b/cld/cld.php index 5ca4c932b..83361e2bb 100644 --- a/cld/cld.php +++ b/cld/cld.php @@ -22,6 +22,16 @@ function cld_detect_languages(array &$data) return; } + if (!class_exists('CLD2Detector')) { + Logger::warning('CLD2Detector class does not exist.'); + return; + } + + if (!class_exists('CLD2Encoding')) { + Logger::warning('CLD2Encoding class does not exist.'); + return; + } + $cld2 = new \CLD2Detector(); $cld2->setEncodingHint(CLD2Encoding::UTF8); // optional, hints about text encoding From fc0dda0cd9b607dc8d87f73644108f922f6bb1e1 Mon Sep 17 00:00:00 2001 From: Art4 Date: Tue, 26 Nov 2024 08:23:27 +0000 Subject: [PATCH 230/388] refactor convert addon, replace each() calls with foreach loop --- convert/convert.php | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/convert/convert.php b/convert/convert.php index 57ce6ea83..2c97e2aa6 100644 --- a/convert/convert.php +++ b/convert/convert.php @@ -6,7 +6,6 @@ * Author: Mike Macgirvin */ -use Friendica\App; use Friendica\Core\Hook; function convert_install() { @@ -26,7 +25,7 @@ function convert_content() { // @TODO Let's one day rewrite this to a modern composer package include 'UnitConvertor.php'; - class TP_Converter extends UnitConvertor + $conv = new class('en') extends UnitConvertor { public function __construct(string $lang = 'en') { @@ -43,7 +42,7 @@ function convert_content() { private function findBaseUnit($from, $to) { - while (list($skey, $sval) = each($this->bases)) { + foreach ($this->bases as $skey => $sval) { if ($skey == $from || $to == $skey || in_array($to, $sval) || in_array($from, $sval)) { return $skey; } @@ -63,7 +62,7 @@ function convert_content() { $cells[] = $cell; // We now have the base unit and value now lets produce the table; - while (list($key, $val) = each($this->bases[$base_unit])) { + foreach ($this->bases[$base_unit] as $val) { $cell ['value'] = $this->convert($value, $from_unit, $val, $precision) . ' ' . $val; $cell ['class'] = ($val == $from_unit || $val == $to_unit) ? 'framedred' : ''; $cells[] = $cell; @@ -86,9 +85,7 @@ function convert_content() { return $string; } - } - - $conv = new TP_Converter('en'); + }; $conversions = [ 'Temperature' => ['base' => 'Celsius', @@ -176,10 +173,10 @@ function convert_content() { ] ]; - while (list($key, $val) = each($conversions)) { + foreach ($conversions as $key => $val) { $conv->addConversion($val['base'], $val['conv']); $list[$key][] = $val['base']; - while (list($ukey, $uval) = each($val['conv'])) { + foreach ($val['conv'] as $ukey => $uval) { $list[$key][] = $ukey; } } @@ -202,10 +199,9 @@ function convert_content() { $o .= ''; $o .= ''; $o .= '
- {{foreach $th_users as $k=>$th}} - {{if $k < 2 || $order_users == $th.1 || ($k==5 && !in_array($order_users,[$th_users.2.1, $th_users.3.1, $th_users.4.1])) }} + {{if $k < 2 || $order_users == $th.1 || ($k==4 && !in_array($order_users,[$th_users.2.1, $th_users.3.1, $th_users.5.1])) }} {{/if}} - {{if $order_users == $th_users.4.1}} - - {{/if}} - - {{if !in_array($order_users,[$th_users.2.1, $th_users.3.1, $th_users.4.1]) }} + {{if $order_users == $th_users.5.1}} From 46b38367209b8c5c6f084454d5a9ea9eb322a8d9 Mon Sep 17 00:00:00 2001 From: Matthew Exon Date: Sat, 11 Jan 2025 19:39:20 +0100 Subject: [PATCH 309/388] Ratioed: remove create user button --- ratioed/templates/ratioed.tpl | 3 --- 1 file changed, 3 deletions(-) diff --git a/ratioed/templates/ratioed.tpl b/ratioed/templates/ratioed.tpl index d634993ec..c64cb1dc0 100644 --- a/ratioed/templates/ratioed.tpl +++ b/ratioed/templates/ratioed.tpl @@ -6,9 +6,6 @@ {{$title}} - {{$page}} ({{$count}}) -

- {{$h_newuser}} -

+
@@ -323,7 +322,7 @@ $o .= <<< EOT - + @@ -345,13 +344,13 @@ $o .= <<< EOT - +
diff --git a/catavatar/catavatar.php b/catavatar/catavatar.php index 2116ac44b..2bdf0cca8 100644 --- a/catavatar/catavatar.php +++ b/catavatar/catavatar.php @@ -6,11 +6,9 @@ * Author: Fabio */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\Core\Logger; use Friendica\Core\Renderer; -use Friendica\Core\Worker; use Friendica\Database\DBA; use Friendica\DI; use Friendica\Model\Contact; diff --git a/cookienotice/cookienotice.php b/cookienotice/cookienotice.php index 2bd6f9b1b..bc9d24166 100644 --- a/cookienotice/cookienotice.php +++ b/cookienotice/cookienotice.php @@ -7,7 +7,6 @@ * Author: Peter Liebetrau */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\Core\Renderer; use Friendica\DI; diff --git a/diaspora/diaspora.php b/diaspora/diaspora.php index 979204baf..d6c98e342 100644 --- a/diaspora/diaspora.php +++ b/diaspora/diaspora.php @@ -9,7 +9,6 @@ require_once 'addon/diaspora/Diaspora_Connection.php'; -use Friendica\App; use Friendica\Content\Text\BBCode; use Friendica\Core\Hook; use Friendica\Core\Logger; diff --git a/discourse/discourse.php b/discourse/discourse.php index 298b3f3ee..e97a4fd80 100644 --- a/discourse/discourse.php +++ b/discourse/discourse.php @@ -8,7 +8,6 @@ * */ -use Friendica\App; use Friendica\Content\Text\Markdown; use Friendica\Core\Hook; use Friendica\Core\Logger; diff --git a/dwpost/dwpost.php b/dwpost/dwpost.php index 1ecd9764b..7ce30086e 100644 --- a/dwpost/dwpost.php +++ b/dwpost/dwpost.php @@ -8,7 +8,6 @@ * Author: Cat Gray */ -use Friendica\App; use Friendica\Content\Text\BBCode; use Friendica\Core\Hook; use Friendica\Core\Logger; diff --git a/fancybox/fancybox.php b/fancybox/fancybox.php index 73bbdab92..8608bcd7b 100644 --- a/fancybox/fancybox.php +++ b/fancybox/fancybox.php @@ -7,7 +7,6 @@ * Status: Unsupported */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\DI; diff --git a/fromapp/fromapp.php b/fromapp/fromapp.php index 0d5a5b16b..8bd276060 100644 --- a/fromapp/fromapp.php +++ b/fromapp/fromapp.php @@ -7,7 +7,6 @@ * */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\Core\Logger; use Friendica\Core\Renderer; @@ -76,6 +75,6 @@ function fromapp_post_hook(&$item) $apps = explode(',', $app); $item['app'] = trim($apps[mt_rand(0, count($apps)-1)]); - + return; } diff --git a/geocoordinates/geocoordinates.php b/geocoordinates/geocoordinates.php index 5cb90efde..eb56f093a 100644 --- a/geocoordinates/geocoordinates.php +++ b/geocoordinates/geocoordinates.php @@ -6,7 +6,6 @@ * Author: Michael Vogel */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\Core\Logger; use Friendica\Core\Renderer; diff --git a/geonames/geonames.php b/geonames/geonames.php index dcbd65f80..668eb0e77 100644 --- a/geonames/geonames.php +++ b/geonames/geonames.php @@ -6,7 +6,6 @@ * Author: Mike Macgirvin */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\Core\Logger; use Friendica\Core\Renderer; diff --git a/gnot/gnot.php b/gnot/gnot.php index 15fb4da00..5d0919cbd 100644 --- a/gnot/gnot.php +++ b/gnot/gnot.php @@ -4,11 +4,10 @@ * Description: Thread email comment notifications on Gmail and anonymise them * Version: 1.0 * Author: Mike Macgirvin - * + * * */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\Core\Logger; use Friendica\Core\Renderer; @@ -38,7 +37,7 @@ function gnot_settings_post($post) { } /** - * Called from the Addon Setting form. + * Called from the Addon Setting form. * Add our own settings info to the page. */ function gnot_settings(array &$data) diff --git a/googlemaps/googlemaps.php b/googlemaps/googlemaps.php index 356ce68ca..b83a9cf99 100644 --- a/googlemaps/googlemaps.php +++ b/googlemaps/googlemaps.php @@ -7,7 +7,6 @@ * */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\Core\Logger; diff --git a/gravatar/gravatar.php b/gravatar/gravatar.php index 83a8fbb93..ca5eaaf08 100644 --- a/gravatar/gravatar.php +++ b/gravatar/gravatar.php @@ -6,15 +6,12 @@ * Author: Klaus Weidenbach */ -use Friendica\App; use Friendica\BaseModule; use Friendica\Core\Hook; use Friendica\Core\Logger; use Friendica\Core\Renderer; -use Friendica\Database\DBA; use Friendica\DI; use Friendica\Core\Config\Util\ConfigFileManager; -use Friendica\Util\Strings; /** * Installs the addon hook diff --git a/group_text/group_text.php b/group_text/group_text.php index 02e9fd0a5..e5067fb54 100644 --- a/group_text/group_text.php +++ b/group_text/group_text.php @@ -8,9 +8,7 @@ * Note: Please use Circle Text instead */ -use Friendica\App; use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\DI; diff --git a/highlightjs/highlightjs.php b/highlightjs/highlightjs.php index 097d34c7e..c1c2aac86 100644 --- a/highlightjs/highlightjs.php +++ b/highlightjs/highlightjs.php @@ -6,7 +6,6 @@ * Author: Hypolite Petovan */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\DI; diff --git a/ifttt/ifttt.php b/ifttt/ifttt.php index 6d4f402c5..51fa8db81 100644 --- a/ifttt/ifttt.php +++ b/ifttt/ifttt.php @@ -6,7 +6,6 @@ * Version: 0.1 * Author: Michael Vogel */ -use Friendica\App; use Friendica\Content\PageInfo; use Friendica\Core\Hook; use Friendica\Core\Logger; diff --git a/ijpost/ijpost.php b/ijpost/ijpost.php index f22dfff29..37c3cd45e 100644 --- a/ijpost/ijpost.php +++ b/ijpost/ijpost.php @@ -8,7 +8,6 @@ * Author: Cat Gray */ -use Friendica\App; use Friendica\Content\Text\BBCode; use Friendica\Core\Hook; use Friendica\Core\Logger; diff --git a/impressum/impressum.php b/impressum/impressum.php index 754cb8286..19ade933a 100644 --- a/impressum/impressum.php +++ b/impressum/impressum.php @@ -7,7 +7,6 @@ * License: 3-clause BSD license */ -use Friendica\App; use Friendica\Content\Text\BBCode; use Friendica\Core\Hook; use Friendica\Core\Logger; diff --git a/infiniteimprobabilitydrive/infiniteimprobabilitydrive.php b/infiniteimprobabilitydrive/infiniteimprobabilitydrive.php index aff7aec0b..9eb6ab36c 100644 --- a/infiniteimprobabilitydrive/infiniteimprobabilitydrive.php +++ b/infiniteimprobabilitydrive/infiniteimprobabilitydrive.php @@ -6,7 +6,6 @@ * Author: Thomas Willingham */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\DI; diff --git a/irc/irc.php b/irc/irc.php index d44358511..db808a995 100644 --- a/irc/irc.php +++ b/irc/irc.php @@ -7,7 +7,6 @@ * Author: Tobias Diekershoff */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\Core\Renderer; use Friendica\DI; diff --git a/krynn/krynn.php b/krynn/krynn.php index f7e77c269..fa9db1331 100644 --- a/krynn/krynn.php +++ b/krynn/krynn.php @@ -10,7 +10,6 @@ *"My body was my sacrifice... for my magic. This damage is permanent." - Raistlin Majere */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\Core\Logger; use Friendica\Core\Renderer; diff --git a/ldapauth/ldapauth.php b/ldapauth/ldapauth.php index 38e2d6a1e..14686e997 100644 --- a/ldapauth/ldapauth.php +++ b/ldapauth/ldapauth.php @@ -29,7 +29,6 @@ * The configuration options for this module are described in the config/ldapauth.config.php file */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\Core\Logger; use Friendica\Database\DBA; diff --git a/libertree/libertree.php b/libertree/libertree.php index 1d997123a..c138e5977 100644 --- a/libertree/libertree.php +++ b/libertree/libertree.php @@ -6,7 +6,6 @@ * Author: Tony Baldwin */ -use Friendica\App; use Friendica\Content\Text\BBCode; use Friendica\Core\Hook; use Friendica\Core\Logger; diff --git a/libravatar/libravatar.php b/libravatar/libravatar.php index 54594b889..b0b2c214c 100644 --- a/libravatar/libravatar.php +++ b/libravatar/libravatar.php @@ -6,7 +6,6 @@ * Author: Klaus Weidenbach */ -use Friendica\App; use Friendica\Core\Addon; use Friendica\Core\Hook; use Friendica\Core\Logger; diff --git a/markdown/markdown.php b/markdown/markdown.php index 6f4592445..0822ac836 100644 --- a/markdown/markdown.php +++ b/markdown/markdown.php @@ -5,7 +5,6 @@ * Version: 0.1 * Author: Michael Vogel */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\Content\Text\Markdown; use Friendica\Core\Renderer; diff --git a/mathjax/mathjax.php b/mathjax/mathjax.php index d0046cf7a..e96aaddf8 100644 --- a/mathjax/mathjax.php +++ b/mathjax/mathjax.php @@ -8,7 +8,6 @@ * License: 3-clause BSD license */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\Core\Renderer; use Friendica\DI; diff --git a/morechoice/morechoice.php b/morechoice/morechoice.php index fe726d279..fbb88ce19 100644 --- a/morechoice/morechoice.php +++ b/morechoice/morechoice.php @@ -8,7 +8,6 @@ * Status: Deprecated */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\DI; diff --git a/morepokes/morepokes.php b/morepokes/morepokes.php index abe59a6e6..2ac09a73f 100644 --- a/morepokes/morepokes.php +++ b/morepokes/morepokes.php @@ -7,7 +7,6 @@ * */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\DI; diff --git a/newmemberwidget/newmemberwidget.php b/newmemberwidget/newmemberwidget.php index 01977d0c3..d3b68807a 100644 --- a/newmemberwidget/newmemberwidget.php +++ b/newmemberwidget/newmemberwidget.php @@ -6,7 +6,6 @@ * Author: Tobias Diekershoff ***/ -use Friendica\App; use Friendica\Content\Text\BBCode; use Friendica\Core\Hook; use Friendica\Core\Logger; diff --git a/nitter/nitter.php b/nitter/nitter.php index 946b18c0c..adbfd6b06 100644 --- a/nitter/nitter.php +++ b/nitter/nitter.php @@ -25,7 +25,6 @@ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\Core\Renderer; use Friendica\DI; diff --git a/nominatim/nominatim.php b/nominatim/nominatim.php index 6ad4a8a3f..a3d14af5e 100644 --- a/nominatim/nominatim.php +++ b/nominatim/nominatim.php @@ -6,7 +6,6 @@ * Author: Michael Vogel */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\Core\Logger; use Friendica\Core\Renderer; diff --git a/notifyall/notifyall.php b/notifyall/notifyall.php index 966a91843..d37bac568 100644 --- a/notifyall/notifyall.php +++ b/notifyall/notifyall.php @@ -9,9 +9,7 @@ */ use Friendica\Addon\notifyall\NotifyAllEmail; -use Friendica\App; use Friendica\Database\DBA; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\DI; diff --git a/numfriends/numfriends.php b/numfriends/numfriends.php index 538a4a3ec..66c9b74a1 100644 --- a/numfriends/numfriends.php +++ b/numfriends/numfriends.php @@ -6,7 +6,6 @@ * Author: Mike Macgirvin */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\Core\Logger; use Friendica\Core\Renderer; @@ -39,7 +38,7 @@ function numfriends_settings_post($post) { /** * - * Called from the Addon Setting form. + * Called from the Addon Setting form. * Add our own settings info to the page. * */ @@ -50,7 +49,7 @@ function numfriends_settings(array &$data) } $numfriends = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'system', 'display_friend_count', 24); - + $t = Renderer::getMarkupTemplate('settings.tpl', 'addon/numfriends/'); $html = Renderer::replaceMacros($t, [ '$numfriends' => ['numfriends', DI::l10n()->t('How many contacts to display on profile sidebar'), $numfriends], diff --git a/openstreetmap/openstreetmap.php b/openstreetmap/openstreetmap.php index ae22aff04..c520514c0 100644 --- a/openstreetmap/openstreetmap.php +++ b/openstreetmap/openstreetmap.php @@ -9,7 +9,6 @@ * */ -use Friendica\App; use Friendica\Core\Cache\Enum\Duration; use Friendica\Core\Hook; use Friendica\Core\Logger; diff --git a/opmlexport/opmlexport.php b/opmlexport/opmlexport.php index fdfacc3e3..3df712752 100644 --- a/opmlexport/opmlexport.php +++ b/opmlexport/opmlexport.php @@ -8,12 +8,8 @@ */ use Friendica\DI; -use Friendica\App; use Friendica\Core\Hook; use Friendica\Core\Logger; -use Friendica\Network\HTTPException; -use Friendica\Database\DBA; -use Friendica\Core\Renderer; use Friendica\Core\Protocol; use Friendica\Model\Contact; use Friendica\Model\User; diff --git a/pageheader/pageheader.php b/pageheader/pageheader.php index 057bb863c..d729acc18 100644 --- a/pageheader/pageheader.php +++ b/pageheader/pageheader.php @@ -5,10 +5,9 @@ * Version: 1.1 * Author: Keith Fernie * Hauke Altmann - * + * */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\Core\Renderer; use Friendica\DI; diff --git a/phpmailer/phpmailer.php b/phpmailer/phpmailer.php index 4c12709d0..5e137b94e 100644 --- a/phpmailer/phpmailer.php +++ b/phpmailer/phpmailer.php @@ -7,7 +7,6 @@ * Maintainer: Hypolite Petovan */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\DI; use Friendica\Object\EMail\IEmail; diff --git a/piwik/piwik.php b/piwik/piwik.php index fd6d5fc9b..b7b49bd4a 100644 --- a/piwik/piwik.php +++ b/piwik/piwik.php @@ -35,7 +35,6 @@ * setting. */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\Core\Logger; use Friendica\Core\Renderer; @@ -76,7 +75,7 @@ function piwik_analytics(string &$b) * Add the Piwik tracking code for the site. * If async is set to true use asynchronous tracking */ - + $scriptAsyncValue = $async ? 'true' : 'false'; $scriptPhpEndpoint = $shortendpoint ? 'js/' : 'piwik.php'; $scriptJsEndpoint = $shortendpoint ? 'js/' : 'piwik.js'; diff --git a/planets/planets.php b/planets/planets.php index 8a206fb51..d96e33a6f 100644 --- a/planets/planets.php +++ b/planets/planets.php @@ -7,7 +7,6 @@ * Author: Tony Baldwin */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\Core\Logger; use Friendica\Core\Renderer; diff --git a/public_server/public_server.php b/public_server/public_server.php index 7591c7d0d..5834f42a2 100644 --- a/public_server/public_server.php +++ b/public_server/public_server.php @@ -6,7 +6,6 @@ * Author: Keith Fernie */ -use Friendica\App; use Friendica\BaseModule; use Friendica\Core\Hook; use Friendica\Core\Logger; diff --git a/qcomment/qcomment.php b/qcomment/qcomment.php index 1b8bfcbfd..f7126531b 100644 --- a/qcomment/qcomment.php +++ b/qcomment/qcomment.php @@ -18,7 +18,6 @@ * */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\Core\Renderer; use Friendica\DI; diff --git a/randplace/randplace.php b/randplace/randplace.php index 34f48c6c2..5cb075970 100644 --- a/randplace/randplace.php +++ b/randplace/randplace.php @@ -19,7 +19,6 @@ * */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\Core\Logger; use Friendica\Core\Renderer; diff --git a/rendertime/rendertime.php b/rendertime/rendertime.php index 731cf0037..1cce5b1b5 100644 --- a/rendertime/rendertime.php +++ b/rendertime/rendertime.php @@ -7,7 +7,6 @@ * */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\Core\Renderer; use Friendica\DI; diff --git a/s3_storage/s3_storage.php b/s3_storage/s3_storage.php index 361577be5..c08c3172e 100644 --- a/s3_storage/s3_storage.php +++ b/s3_storage/s3_storage.php @@ -8,7 +8,6 @@ use Friendica\Addon\s3_storage\src\S3Client; use Friendica\Addon\s3_storage\src\S3Config; -use Friendica\App; use Friendica\Core\Hook; use Friendica\DI; diff --git a/securemail/SecureTestEmail.php b/securemail/SecureTestEmail.php index c614104f4..325100918 100644 --- a/securemail/SecureTestEmail.php +++ b/securemail/SecureTestEmail.php @@ -21,7 +21,6 @@ namespace Friendica\Addon\securemail; -use Friendica\App; use Friendica\App\BaseURL; use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Core\PConfig\Capability\IManagePersonalConfigValues; diff --git a/securemail/securemail.php b/securemail/securemail.php index 611255872..b56c0cbcd 100644 --- a/securemail/securemail.php +++ b/securemail/securemail.php @@ -7,7 +7,6 @@ */ use Friendica\Addon\securemail\SecureTestEmail; -use Friendica\App; use Friendica\Core\Hook; use Friendica\Core\Logger; use Friendica\Core\Renderer; @@ -32,8 +31,6 @@ function securemail_install() * @link https://github.com/friendica/friendica/blob/develop/doc/Addons.md#addon_settings 'addon_settings' hook * * @param array $data - * - * @see App */ function securemail_settings(array &$data) { @@ -67,8 +64,6 @@ function securemail_settings(array &$data) * @link https://github.com/friendica/friendica/blob/develop/doc/Addons.md#addon_settings_post 'addon_settings_post' hook * * @param array $b hook data - * - * @see App */ function securemail_settings_post(array &$b) { @@ -102,8 +97,6 @@ function securemail_settings_post(array &$b) * @link https://github.com/friendica/friendica/blob/develop/doc/Addons.md#emailer_send_prepare 'emailer_send_prepare' hook * * @param IEmail $email Email - * - * @see App */ function securemail_emailer_send_prepare(IEmail &$email) { diff --git a/showmore_dyn/showmore_dyn.php b/showmore_dyn/showmore_dyn.php index 7cb64bcca..4c2e62f5a 100644 --- a/showmore_dyn/showmore_dyn.php +++ b/showmore_dyn/showmore_dyn.php @@ -7,12 +7,8 @@ * */ -use Friendica\App; use Friendica\Core\Hook; -use Friendica\Core\L10n; -use Friendica\Core\Logger; use Friendica\Core\Renderer; -use Friendica\Database\DBA; use Friendica\DI; function showmore_dyn_install() diff --git a/smiley_pack/lang/smiley_pack_es/smiley_pack_es.php b/smiley_pack/lang/smiley_pack_es/smiley_pack_es.php index 38b208da1..0f41101df 100644 --- a/smiley_pack/lang/smiley_pack_es/smiley_pack_es.php +++ b/smiley_pack/lang/smiley_pack_es/smiley_pack_es.php @@ -3,11 +3,10 @@ * Name: Smiley Pack (Español) * Description: Pack of smileys that make master too AOLish. * Version: 1.02 - * Author: Thomas Willingham (based on Mike Macgirvin's Adult Smile template) + * Author: Thomas Willingham (based on Mike Macgirvin's Adult Smile template) * All smileys from sites offering them as Public Domain */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\DI; @@ -19,7 +18,7 @@ function smiley_pack_smilies_es(array &$b) { #Smileys are split into various directories by the intended range of emotions. This is in case we get too big and need to modularise things. We can then cut and paste the right lines, move the right directory, and just change the name of the addon to happy_smilies or whatever. -#Be careful with invocation strings. If you have a smiley called foo, and another called foobar, typing :foobar will call foo. Avoid this with clever naming, using ~ instead of : +#Be careful with invocation strings. If you have a smiley called foo, and another called foobar, typing :foobar will call foo. Avoid this with clever naming, using ~ instead of : #when all else fails. @@ -49,7 +48,7 @@ function smiley_pack_smilies_es(array &$b) { $b['texts'][] = ':vaca'; $b['icons'][] = '' . ':vaca' . ''; - + $b['texts'][] = ':cangrejo'; $b['icons'][] = '' . ':cangrejo' . ''; @@ -70,7 +69,7 @@ function smiley_pack_smilies_es(array &$b) { $b['texts'][] = ':caballo'; $b['icons'][] = '' . ':caballo' . ''; - + $b['texts'][] = ':loro'; $b['icons'][] = '' . ':loro' . ''; @@ -107,7 +106,7 @@ function smiley_pack_smilies_es(array &$b) { $b['texts'][] = ':cuna'; $b['icons'][] = '' . ':cuna' . ''; - + $b['texts'][] = ':embarazada'; $b['icons'][] = '' . ':embarazada' . ''; @@ -116,10 +115,10 @@ function smiley_pack_smilies_es(array &$b) { $b['icons'][] = '' . ':cigüeña' . ''; -#Confused Smileys +#Confused Smileys $b['texts'][] = ':confundido'; $b['icons'][] = '' . ':confundido' . ''; - + $b['texts'][] = ':encogehombros'; $b['icons'][] = '' . ':encogehombros' . ''; @@ -154,13 +153,13 @@ function smiley_pack_smilies_es(array &$b) { $b['texts'][] = ':diabólico'; $b['icons'][] = '' . ':diabólico' . ''; - + $b['texts'][] = ':adbalancín'; $b['icons'][] = '' . ':adbalancín' . ''; $b['texts'][] = ':vuelvedemonio'; $b['icons'][] = '' . ':vuelvedemonio' . ''; - + $b['texts'][] = ':santo'; $b['icons'][] = '' . ':santo' . ''; @@ -242,7 +241,7 @@ function smiley_pack_smilies_es(array &$b) { $b['texts'][] = ':billar'; $b['icons'][] = '' . ':billar' . ''; - + $b['texts'][] = ':tenis'; $b['icons'][] = '' . ':tenis' . ''; diff --git a/smiley_pack/lang/smiley_pack_fr/smiley_pack_fr.php b/smiley_pack/lang/smiley_pack_fr/smiley_pack_fr.php index 63cf613e0..c5474e3c1 100644 --- a/smiley_pack/lang/smiley_pack_fr/smiley_pack_fr.php +++ b/smiley_pack/lang/smiley_pack_fr/smiley_pack_fr.php @@ -9,7 +9,6 @@ * */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\DI; @@ -23,7 +22,7 @@ function smiley_pack_fr_smilies(array &$b) #Smileys are split into various directories by the intended range of emotions. This is in case we get too big and need to modularise things. We can then cut and paste the right lines, move the right directory, and just change the name of the addon to happy_smilies or whatever. -#Be careful with invocation strings. If you have a smiley called foo, and another called foobar, typing :foobar will call foo. Avoid this with clever naming, using ~ instead of : +#Be careful with invocation strings. If you have a smiley called foo, and another called foobar, typing :foobar will call foo. Avoid this with clever naming, using ~ instead of : #when all else fails. @@ -56,7 +55,7 @@ function smiley_pack_fr_smilies(array &$b) $b['texts'][] = ':vache'; $b['icons'][] = '' . ':vache' . ''; - + $b['texts'][] = ':crabe'; $b['icons'][] = '' . ':crabe' . ''; @@ -74,7 +73,7 @@ function smiley_pack_fr_smilies(array &$b) $b['texts'][] = ':cheval'; $b['icons'][] = '' . ':cheval' . ''; - + $b['texts'][] = ':perroquet'; $b['icons'][] = '' . ':perroquet' . ''; @@ -108,7 +107,7 @@ function smiley_pack_fr_smilies(array &$b) $b['texts'][] = ':litbébé'; $b['icons'][] = '' . ':litbébé' . ''; - + $b['texts'][] = ':enceinte'; $b['icons'][] = '' . ':enceinte' . ''; @@ -117,10 +116,10 @@ function smiley_pack_fr_smilies(array &$b) $b['icons'][] = '' . ':cigogne' . ''; -#Confused Smileys +#Confused Smileys $b['texts'][] = ':paumé'; $b['icons'][] = '' . ':paumé' . ''; - + $b['texts'][] = ':hausseépaules'; $b['icons'][] = '' . ':hausseépaules' . ''; @@ -152,13 +151,13 @@ function smiley_pack_fr_smilies(array &$b) $b['texts'][] = ':démoniaque'; $b['icons'][] = '' . ':démoniaque' . ''; - + $b['texts'][] = ':bascule'; $b['icons'][] = '' . ':bascule' . ''; $b['texts'][] = ':possédé'; $b['icons'][] = '' . ':possédé' . ''; - + $b['texts'][] = ':tombe'; $b['icons'][] = '' . ':tombe' . ''; @@ -225,7 +224,7 @@ function smiley_pack_fr_smilies(array &$b) $b['texts'][] = ':billard'; $b['icons'][] = '' . ':billard' . ''; - + $b['texts'][] = ':équitation'; $b['icons'][] = '' . ':équitation' . ''; diff --git a/smileybutton/smileybutton.php b/smileybutton/smileybutton.php index 1df717b72..ae0e783b5 100644 --- a/smileybutton/smileybutton.php +++ b/smileybutton/smileybutton.php @@ -7,7 +7,6 @@ * Maintainer: Hypolite Petovan */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\DI; diff --git a/smilies_adult/smilies_adult.php b/smilies_adult/smilies_adult.php index e8af21e16..4a80168de 100644 --- a/smilies_adult/smilies_adult.php +++ b/smilies_adult/smilies_adult.php @@ -4,12 +4,11 @@ * Description: Smily icons that could or should not be included in core * Version: 1.0 * Author: Mike Macgirvin - * + * * This is a template for how to extend the "smily" code. - * + * */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\DI; diff --git a/startpage/startpage.php b/startpage/startpage.php index e4d80c0c2..558af473e 100644 --- a/startpage/startpage.php +++ b/startpage/startpage.php @@ -7,7 +7,6 @@ * */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\Core\Renderer; use Friendica\DI; diff --git a/statusnet/statusnet.php b/statusnet/statusnet.php index 48f9c2542..bd115115e 100644 --- a/statusnet/statusnet.php +++ b/statusnet/statusnet.php @@ -38,7 +38,6 @@ define('STATUSNET_DEFAULT_POLL_INTERVAL', 5); // given in minutes require_once __DIR__ . DIRECTORY_SEPARATOR . 'library' . DIRECTORY_SEPARATOR . 'statusnetoauth.php'; use CodebirdSN\CodebirdSN; -use Friendica\App; use Friendica\Content\Text\Plaintext; use Friendica\Core\Hook; use Friendica\Core\Logger; diff --git a/testdrive/testdrive.php b/testdrive/testdrive.php index 556452845..40f22e0a7 100644 --- a/testdrive/testdrive.php +++ b/testdrive/testdrive.php @@ -6,7 +6,6 @@ * Author: Mike Macgirvin */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\Core\Search; use Friendica\Database\DBA; diff --git a/unicode_smilies/unicode_smilies.php b/unicode_smilies/unicode_smilies.php index 22ee3439c..b39c6f100 100644 --- a/unicode_smilies/unicode_smilies.php +++ b/unicode_smilies/unicode_smilies.php @@ -7,7 +7,6 @@ * Author: Matthias Ebers */ -use Friendica\App; use Friendica\Content\Smilies; use Friendica\Core\Hook; @@ -691,7 +690,7 @@ function unicode_smilies_smilies(array &$b) Smilies::add($b, ':custard:', '🍮'); Smilies::add($b, ':honey pot:', '🍯'); -// drink +// drink Smilies::add($b, ':baby bottle:', '🍼'); Smilies::add($b, ':glass of milk:', '🥛'); Smilies::add($b, ':hot beverage:', '☕'); @@ -1123,7 +1122,7 @@ function unicode_smilies_smilies(array &$b) Smilies::add($b, ':control knobs:', '🎛'); Smilies::add($b, ':microphone:', '🎤'); Smilies::add($b, ':headphone:', '🎧'); - Smilies::add($b, ':radio:', '📻'); + Smilies::add($b, ':radio:', '📻'); // musical-instrument Smilies::add($b, ':saxophone:', '🎷'); @@ -1529,7 +1528,7 @@ function unicode_smilies_smilies(array &$b) Smilies::add($b, ':O button (blood type):', '🅾'); Smilies::add($b, ':OK button:', '🆗'); Smilies::add($b, ':P button:', '🅿'); - Smilies::add($b, ':SOS button:', '🆘'); + Smilies::add($b, ':SOS button:', '🆘'); Smilies::add($b, ':UP! button:', '🆙'); Smilies::add($b, ':VS button:', '🆚'); Smilies::add($b, ':Japanese “here” button:', '🈁'); diff --git a/viewsrc/viewsrc.php b/viewsrc/viewsrc.php index c4d21ccbd..bd07b5417 100644 --- a/viewsrc/viewsrc.php +++ b/viewsrc/viewsrc.php @@ -7,7 +7,6 @@ * */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\DI; diff --git a/webrtc/webrtc.php b/webrtc/webrtc.php index e142b374b..e5d4ce6e5 100644 --- a/webrtc/webrtc.php +++ b/webrtc/webrtc.php @@ -7,7 +7,6 @@ * Author: Tobias Diekershoff */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\Core\Renderer; use Friendica\DI; From 84659fc1ad339b0f7cee0b8d11ede9ea9aafba07 Mon Sep 17 00:00:00 2001 From: Art4 Date: Wed, 11 Dec 2024 21:47:10 +0000 Subject: [PATCH 276/388] Replace DI::app() with DI::appHelper() --- advancedcontentfilter/advancedcontentfilter.php | 2 +- bluesky/bluesky.php | 2 +- fancybox/fancybox.php | 2 +- geonames/geonames.php | 2 +- gravatar/gravatar.php | 2 +- highlightjs/highlightjs.php | 2 +- impressum/impressum.php | 2 +- ldapauth/ldapauth.php | 2 +- libravatar/libravatar.php | 2 +- openstreetmap/openstreetmap.php | 2 +- phpmailer/phpmailer.php | 2 +- piwik/piwik.php | 2 +- pnut/pnut.php | 2 +- public_server/public_server.php | 2 +- pumpio/pumpio.php | 2 +- smileybutton/smileybutton.php | 6 +++--- testdrive/testdrive.php | 2 +- tumblr/tumblr.php | 2 +- twitter/twitter.php | 2 +- 19 files changed, 21 insertions(+), 21 deletions(-) diff --git a/advancedcontentfilter/advancedcontentfilter.php b/advancedcontentfilter/advancedcontentfilter.php index 329156f1c..c03034cd2 100644 --- a/advancedcontentfilter/advancedcontentfilter.php +++ b/advancedcontentfilter/advancedcontentfilter.php @@ -271,7 +271,7 @@ function advancedcontentfilter_content() 'rule_expression' => DI::l10n()->t('Rule Expression'), 'cancel' => DI::l10n()->t('Cancel'), ], - '$current_theme' => DI::app()->getCurrentTheme(), + '$current_theme' => DI::appHelper()->getCurrentTheme(), '$rules' => DBA::toArray(DBA::select('advancedcontentfilter_rules', [], ['uid' => DI::userSession()->getLocalUserId()])), '$form_security_token' => BaseModule::getFormSecurityToken() ]); diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index 91e524fea..aa4bc3402 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -98,7 +98,7 @@ function bluesky_install() function bluesky_load_config(ConfigFileManager $loader) { - DI::app()->getConfigCache()->load($loader->loadAddonConfig('bluesky'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); + DI::appHelper()->getConfigCache()->load($loader->loadAddonConfig('bluesky'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); } function bluesky_check_item_notification(array &$notification_data) diff --git a/fancybox/fancybox.php b/fancybox/fancybox.php index 8608bcd7b..b1a1ff359 100644 --- a/fancybox/fancybox.php +++ b/fancybox/fancybox.php @@ -39,7 +39,7 @@ function fancybox_render(array &$b){ function ($text) use ($gallery) { // This processes images inlined in posts // Frio / Vier hooks für lightbox are un-hooked in fancybox-config.js. So this works for them, too! - //if (!in_array(DI::app()->getCurrentTheme(),['vier','frio'])) + //if (!in_array(DI::appHelper()->getCurrentTheme(),['vier','frio'])) $text = preg_replace( '#]*href="([^"]*)"[^>]*>(]*src="[^"]*"[^>]*>)#', '$2', diff --git a/geonames/geonames.php b/geonames/geonames.php index 668eb0e77..d14b1e8fe 100644 --- a/geonames/geonames.php +++ b/geonames/geonames.php @@ -34,7 +34,7 @@ function geonames_install() function geonames_load_config(ConfigFileManager $loader) { - DI::app()->getConfigCache()->load($loader->loadAddonConfig('geonames'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); + DI::appHelper()->getConfigCache()->load($loader->loadAddonConfig('geonames'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); } function geonames_post_hook(array &$item) diff --git a/gravatar/gravatar.php b/gravatar/gravatar.php index ca5eaaf08..6007c433e 100644 --- a/gravatar/gravatar.php +++ b/gravatar/gravatar.php @@ -25,7 +25,7 @@ function gravatar_install() { function gravatar_load_config(ConfigFileManager $loader) { - DI::app()->getConfigCache()->load($loader->loadAddonConfig('gravatar'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); + DI::appHelper()->getConfigCache()->load($loader->loadAddonConfig('gravatar'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); } /** diff --git a/highlightjs/highlightjs.php b/highlightjs/highlightjs.php index c1c2aac86..762f4117a 100644 --- a/highlightjs/highlightjs.php +++ b/highlightjs/highlightjs.php @@ -17,7 +17,7 @@ function highlightjs_install() function highlightjs_head(string &$str) { - if (DI::app()->getCurrentTheme() == 'frio') { + if (DI::appHelper()->getCurrentTheme() == 'frio') { $style = 'bootstrap'; } else { $style = 'default'; diff --git a/impressum/impressum.php b/impressum/impressum.php index 19ade933a..f61d7182f 100644 --- a/impressum/impressum.php +++ b/impressum/impressum.php @@ -55,7 +55,7 @@ function impressum_footer(string &$body) function impressum_load_config(ConfigFileManager $loader) { - DI::app()->getConfigCache()->load($loader->loadAddonConfig('impressum'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); + DI::appHelper()->getConfigCache()->load($loader->loadAddonConfig('impressum'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); } function impressum_show(string &$body) diff --git a/ldapauth/ldapauth.php b/ldapauth/ldapauth.php index 14686e997..f834b4d54 100644 --- a/ldapauth/ldapauth.php +++ b/ldapauth/ldapauth.php @@ -44,7 +44,7 @@ function ldapauth_install() function ldapauth_load_config(ConfigFileManager $loader) { - DI::app()->getConfigCache()->load($loader->loadAddonConfig('ldapauth'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); + DI::appHelper()->getConfigCache()->load($loader->loadAddonConfig('ldapauth'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); } function ldapauth_hook_authenticate(array &$b) diff --git a/libravatar/libravatar.php b/libravatar/libravatar.php index b0b2c214c..4cd72c83e 100644 --- a/libravatar/libravatar.php +++ b/libravatar/libravatar.php @@ -25,7 +25,7 @@ function libravatar_install() function libravatar_load_config(ConfigFileManager $loader) { - DI::app()->getConfigCache()->load($loader->loadAddonConfig('libravatar'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); + DI::appHelper()->getConfigCache()->load($loader->loadAddonConfig('libravatar'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); } /** diff --git a/openstreetmap/openstreetmap.php b/openstreetmap/openstreetmap.php index c520514c0..fc5ebbbeb 100644 --- a/openstreetmap/openstreetmap.php +++ b/openstreetmap/openstreetmap.php @@ -36,7 +36,7 @@ function openstreetmap_install() function openstreetmap_load_config(ConfigFileManager $loader) { - DI::app()->getConfigCache()->load($loader->loadAddonConfig('openstreetmap'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); + DI::appHelper()->getConfigCache()->load($loader->loadAddonConfig('openstreetmap'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); } function openstreetmap_alterheader(&$navHtml) diff --git a/phpmailer/phpmailer.php b/phpmailer/phpmailer.php index 5e137b94e..f4bb7753e 100644 --- a/phpmailer/phpmailer.php +++ b/phpmailer/phpmailer.php @@ -24,7 +24,7 @@ function phpmailer_install() function phpmailer_load_config(ConfigFileManager $loader) { - DI::app()->getConfigCache()->load($loader->loadAddonConfig('phpmailer'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); + DI::appHelper()->getConfigCache()->load($loader->loadAddonConfig('phpmailer'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); } /** diff --git a/piwik/piwik.php b/piwik/piwik.php index b7b49bd4a..fc459a875 100644 --- a/piwik/piwik.php +++ b/piwik/piwik.php @@ -50,7 +50,7 @@ function piwik_install() { function piwik_load_config(ConfigFileManager $loader) { - DI::app()->getConfigCache()->load($loader->loadAddonConfig('piwik'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); + DI::appHelper()->getConfigCache()->load($loader->loadAddonConfig('piwik'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); } function piwik_analytics(string &$b) diff --git a/pnut/pnut.php b/pnut/pnut.php index 32f60f6d5..f298997b4 100644 --- a/pnut/pnut.php +++ b/pnut/pnut.php @@ -90,7 +90,7 @@ function pnut_connect() function pnut_load_config(ConfigFileManager $loader) { - DI::app()->getConfigCache()->load($loader->loadAddonConfig('pnut'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); + DI::appHelper()->getConfigCache()->load($loader->loadAddonConfig('pnut'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); } function pnut_addon_admin(string &$o) diff --git a/public_server/public_server.php b/public_server/public_server.php index 5834f42a2..eb7af1e75 100644 --- a/public_server/public_server.php +++ b/public_server/public_server.php @@ -28,7 +28,7 @@ function public_server_install() function public_server_load_config(ConfigFileManager $loader) { - DI::app()->getConfigCache()->load($loader->loadAddonConfig('public_server'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); + DI::appHelper()->getConfigCache()->load($loader->loadAddonConfig('public_server'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); } function public_server_register_account($b) diff --git a/pumpio/pumpio.php b/pumpio/pumpio.php index d7c2ac326..ffe5f187a 100644 --- a/pumpio/pumpio.php +++ b/pumpio/pumpio.php @@ -319,7 +319,7 @@ function pumpio_settings_post(array &$b) function pumpio_load_config(ConfigFileManager $loader) { - DI::app()->getConfigCache()->load($loader->loadAddonConfig('pumpio'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); + DI::appHelper()->getConfigCache()->load($loader->loadAddonConfig('pumpio'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); } function pumpio_hook_fork(array &$b) diff --git a/smileybutton/smileybutton.php b/smileybutton/smileybutton.php index ae0e783b5..4d0a8d421 100644 --- a/smileybutton/smileybutton.php +++ b/smileybutton/smileybutton.php @@ -19,7 +19,7 @@ function smileybutton_install() function smileybutton_jot_tool(string &$body) { // Disable if theme is quattro - if (DI::app()->getCurrentTheme() == 'quattro') { + if (DI::appHelper()->getCurrentTheme() == 'quattro') { return; } @@ -96,7 +96,7 @@ function smileybutton_jot_tool(string &$body) $s .= '
'; //Add css to header - $css_file = __DIR__ . '/view/' . DI::app()->getCurrentTheme() . '.css'; + $css_file = __DIR__ . '/view/' . DI::appHelper()->getCurrentTheme() . '.css'; if (!file_exists($css_file)) { $css_file = __DIR__ . '/view/default.css'; } @@ -104,7 +104,7 @@ function smileybutton_jot_tool(string &$body) DI::page()->registerStylesheet($css_file); //Get the correct image for the theme - $image = 'addon/smileybutton/view/' . DI::app()->getCurrentTheme() . '.png'; + $image = 'addon/smileybutton/view/' . DI::appHelper()->getCurrentTheme() . '.png'; if (!file_exists($image)) { $image = 'addon/smileybutton/view/default.png'; } diff --git a/testdrive/testdrive.php b/testdrive/testdrive.php index 40f22e0a7..90fb59188 100644 --- a/testdrive/testdrive.php +++ b/testdrive/testdrive.php @@ -26,7 +26,7 @@ function testdrive_install() function testdrive_load_config(ConfigFileManager $loader) { - DI::app()->getConfigCache()->load($loader->loadAddonConfig('testdrive'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); + DI::appHelper()->getConfigCache()->load($loader->loadAddonConfig('testdrive'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); } function testdrive_globaldir_update(array &$b) diff --git a/tumblr/tumblr.php b/tumblr/tumblr.php index 1e9f5c7fa..580d73e66 100644 --- a/tumblr/tumblr.php +++ b/tumblr/tumblr.php @@ -65,7 +65,7 @@ function tumblr_install() function tumblr_load_config(ConfigFileManager $loader) { - DI::app()->getConfigCache()->load($loader->loadAddonConfig('tumblr'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); + DI::appHelper()->getConfigCache()->load($loader->loadAddonConfig('tumblr'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); } function tumblr_check_item_notification(array &$notification_data) diff --git a/twitter/twitter.php b/twitter/twitter.php index 10f8a2fb3..ea4ae3569 100644 --- a/twitter/twitter.php +++ b/twitter/twitter.php @@ -67,7 +67,7 @@ function twitter_install() function twitter_load_config(ConfigFileManager $loader) { - DI::app()->getConfigCache()->load($loader->loadAddonConfig('twitter'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); + DI::appHelper()->getConfigCache()->load($loader->loadAddonConfig('twitter'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC); } function twitter_jot_nets(array &$jotnets_fields) From 31198294c787497d0c5cb4bcf081e5a15db084e5 Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 29 Nov 2024 22:36:05 +0000 Subject: [PATCH 277/388] Fix error in bluesky addon --- bluesky/bluesky.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index 38934febb..8e2c1ca08 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -1563,7 +1563,7 @@ function bluesky_get_uri_class(string $uri): ?stdClass } $elements = explode(':', $uri); - if (empty($elements) || ($elements[0] != 'at')) { + if ($elements[0] !== 'at') { $post = Post::selectFirstPost(['extid'], ['uri' => $uri]); return bluesky_get_uri_class($post['extid'] ?? ''); } From cf8a7870f3765db549ec961cf28f7fc7b8e466ad Mon Sep 17 00:00:00 2001 From: Art4 Date: Sat, 30 Nov 2024 19:27:45 +0000 Subject: [PATCH 278/388] Fix errors in bluesky addon --- bluesky/bluesky.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index 8e2c1ca08..91e524fea 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -683,6 +683,8 @@ function bluesky_create_activity(array $item, stdClass $parent = null) return; } + $post = []; + if ($item['verb'] == Activity::LIKE) { $record = [ 'subject' => $parent, From 1860e732aee24ee9b1f6677e7b8f5c503f226db6 Mon Sep 17 00:00:00 2001 From: Art4 Date: Sat, 30 Nov 2024 19:28:38 +0000 Subject: [PATCH 279/388] Fix errors in convert addon --- convert/convert.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/convert/convert.php b/convert/convert.php index 2c97e2aa6..2545974c1 100644 --- a/convert/convert.php +++ b/convert/convert.php @@ -181,7 +181,7 @@ function convert_content() { } } - $o .= '

Unit Conversions

'; + $o = '

Unit Conversions

'; if (isset($_POST['from_unit']) && isset($_POST['value'])) { $o .= ($conv->getTable(intval($_POST['value']), $_POST['from_unit'], $_POST['to_unit'], 5)) . '

'; From 81f232d57e8991ca342751d0db2d2680ec7bc7c8 Mon Sep 17 00:00:00 2001 From: Art4 Date: Sat, 30 Nov 2024 19:30:39 +0000 Subject: [PATCH 280/388] Fix errors in js_upload addon --- .../file-uploader/tests/action-acceptance.php | 16 ++++++++-------- .../tests/action-handler-queue-test.php | 8 ++++---- .../file-uploader/tests/action-handler-test.php | 8 ++++---- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/js_upload/file-uploader/tests/action-acceptance.php b/js_upload/file-uploader/tests/action-acceptance.php index fc9583f21..172b88579 100644 --- a/js_upload/file-uploader/tests/action-acceptance.php +++ b/js_upload/file-uploader/tests/action-acceptance.php @@ -2,12 +2,12 @@ usleep(100000); -$fileName; -$fileSize; +$fileName = ''; +$fileSize = 0;; if (isset($_GET['qqfile'])){ $fileName = $_GET['qqfile']; - + // xhr request $headers = apache_request_headers(); $fileSize = (int)$headers['Content-Length']; @@ -34,13 +34,13 @@ if ($fileSize > 9 * 1024){ die ('{error: "server-error file size is bigger than 9kB"}'); } -if (count($_GET)){ +if (count($_GET)){ array_merge($_GET, array('fileName'=>$fileName)); - + $response = array_merge($_GET, array('success'=>true, 'fileName'=>$fileName)); - - // to pass data through iframe you will need to encode all html tags - echo htmlspecialchars(json_encode($response), ENT_NOQUOTES); + + // to pass data through iframe you will need to encode all html tags + echo htmlspecialchars(json_encode($response), ENT_NOQUOTES); } else { die ('{error: "server-error query params not passed"}'); } diff --git a/js_upload/file-uploader/tests/action-handler-queue-test.php b/js_upload/file-uploader/tests/action-handler-queue-test.php index ff13576dd..78760d646 100644 --- a/js_upload/file-uploader/tests/action-handler-queue-test.php +++ b/js_upload/file-uploader/tests/action-handler-queue-test.php @@ -2,11 +2,11 @@ sleep(4); -$fileName; +$fileName = ''; if (isset($_GET['qqfile'])){ $fileName = $_GET['qqfile']; - + // xhr request $headers = apache_request_headers(); if ((int)$headers['Content-Length'] == 0){ @@ -14,7 +14,7 @@ if (isset($_GET['qqfile'])){ } } elseif (isset($_FILES['qqfile'])){ $fileName = basename($_FILES['qqfile']['name']); - + // form request if ($_FILES['qqfile']['size'] == 0){ die ('{error: "file size is zero"}'); @@ -25,7 +25,7 @@ if (isset($_GET['qqfile'])){ if (count($_GET)){ $_GET['success'] = true; - echo json_encode(array_merge($_GET)); + echo json_encode(array_merge($_GET)); } else { die ('{error: "query params not passed"}'); } diff --git a/js_upload/file-uploader/tests/action-handler-test.php b/js_upload/file-uploader/tests/action-handler-test.php index 24466b122..9fa72023d 100644 --- a/js_upload/file-uploader/tests/action-handler-test.php +++ b/js_upload/file-uploader/tests/action-handler-test.php @@ -2,11 +2,11 @@ usleep(300); -$fileName; +$fileName = ''; if (isset($_GET['qqfile'])){ $fileName = $_GET['qqfile']; - + // xhr request $headers = apache_request_headers(); if ((int)$headers['Content-Length'] == 0){ @@ -14,7 +14,7 @@ if (isset($_GET['qqfile'])){ } } elseif (isset($_FILES['qqfile'])){ $fileName = basename($_FILES['qqfile']['name']); - + // form request if ($_FILES['qqfile']['size'] == 0){ die ('{error: "file size is zero"}'); @@ -25,7 +25,7 @@ if (isset($_GET['qqfile'])){ if (count($_GET)){ //return query params - echo json_encode(array_merge($_GET, array('fileName'=>$fileName))); + echo json_encode(array_merge($_GET, array('fileName'=>$fileName))); } else { die ('{error: "query params not passed"}'); } From 3cf53a334d3d04df83b35423f31a916eea0ab492 Mon Sep 17 00:00:00 2001 From: Art4 Date: Sat, 30 Nov 2024 19:32:07 +0000 Subject: [PATCH 281/388] Fix errors in keycloakpassword addon --- keycloakpassword/keycloakpassword.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/keycloakpassword/keycloakpassword.php b/keycloakpassword/keycloakpassword.php index bfff4ea47..e9809f86a 100644 --- a/keycloakpassword/keycloakpassword.php +++ b/keycloakpassword/keycloakpassword.php @@ -6,7 +6,6 @@ * Author: Ryan */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\Core\Logger; use Friendica\Core\Renderer; @@ -92,7 +91,7 @@ function keycloakpassword_authenticate(array &$b) $client_id, $secret, $endpoint . '/logout', - [ 'refresh_token' => res['refresh_token'] ] + [ 'refresh_token' => $res['refresh_token'] ] ); } } From a53d5ae29b1ec11d4063d636ec6c27074855576b Mon Sep 17 00:00:00 2001 From: Art4 Date: Sat, 30 Nov 2024 19:35:19 +0000 Subject: [PATCH 282/388] Fix errors in langfilter addon --- langfilter/langfilter.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/langfilter/langfilter.php b/langfilter/langfilter.php index e5efa8fbc..2bf986f09 100644 --- a/langfilter/langfilter.php +++ b/langfilter/langfilter.php @@ -7,7 +7,6 @@ * License: MIT */ -use Friendica\App; use Friendica\Content\Text\BBCode; use Friendica\Core\Hook; use Friendica\Core\Renderer; @@ -148,6 +147,8 @@ function langfilter_prepare_body_content_filter(&$hook_data) $iso639 = new Matriphe\ISO639\ISO639; + $confidence = null; + // Extract the language of the post if (!empty($hook_data['item']['language'])) { $languages = json_decode($hook_data['item']['language'], true); From ee1a917612fb1c014eecce9d37b7dbcfa166aaa9 Mon Sep 17 00:00:00 2001 From: Art4 Date: Sat, 30 Nov 2024 19:37:58 +0000 Subject: [PATCH 283/388] Fix errors in leistungsschutzrecht addon --- leistungsschutzrecht/leistungsschutzrecht.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/leistungsschutzrecht/leistungsschutzrecht.php b/leistungsschutzrecht/leistungsschutzrecht.php index f6c653995..ec8091acb 100644 --- a/leistungsschutzrecht/leistungsschutzrecht.php +++ b/leistungsschutzrecht/leistungsschutzrecht.php @@ -6,7 +6,6 @@ * Author: Michael Vogel */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\Core\Logger; use Friendica\DI; @@ -149,7 +148,7 @@ function leistungsschutzrecht_is_member_site(string $url): bool $cleanedurlpart = explode('%', $urldata['host']); $hostname = explode('.', $cleanedurlpart[0]); - if (empty($hostname)) { + if ($hostname === false || $hostname === '') { return false; } From d08a280ba6d51ea1671b62a65ee72f221f83106c Mon Sep 17 00:00:00 2001 From: Art4 Date: Sat, 30 Nov 2024 19:41:11 +0000 Subject: [PATCH 284/388] Fix errors in libravatar addon --- libravatar/Services/Libravatar.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libravatar/Services/Libravatar.php b/libravatar/Services/Libravatar.php index 70fcfe39f..e51ef0700 100644 --- a/libravatar/Services/Libravatar.php +++ b/libravatar/Services/Libravatar.php @@ -401,9 +401,8 @@ class Services_Libravatar */ protected function srvGet($domain, $https = false) { - // Are we going secure? Set up a fallback too. - if (isset($https) && $https === true) { + if ($https === true) { $subdomain = '_avatars-sec._tcp.'; $fallback = 'seccdn.'; } else { @@ -426,6 +425,7 @@ class Services_Libravatar $top = $srv[0]; $sum = 0; + $pri = []; // Try to adhere to RFC2782's weighting algorithm, page 3 // "arrange all SRV RRs (that have not been ordered yet) in any order, From 984e7c5e5d133ab4305c766a924d2517a03bbd2c Mon Sep 17 00:00:00 2001 From: Art4 Date: Sat, 30 Nov 2024 19:42:40 +0000 Subject: [PATCH 285/388] Fix errors in ljpost addon --- ljpost/ljpost.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ljpost/ljpost.php b/ljpost/ljpost.php index 7acc65898..b416c6059 100644 --- a/ljpost/ljpost.php +++ b/ljpost/ljpost.php @@ -8,7 +8,6 @@ * Author: Cat Gray */ -use Friendica\App; use Friendica\Content\Text\BBCode; use Friendica\Core\Hook; use Friendica\Core\Logger; @@ -203,10 +202,12 @@ EOT; Logger::debug('ljpost: data: ' . $xml); + $x = ''; + if ($lj_blog !== 'test') { $x = DI::httpClient()->post($lj_blog, $xml, ['Content-Type' => 'text/xml'])->getBodyString(); } - Logger::info('posted to livejournal: ' . ($x) ? $x : ''); + Logger::info('posted to livejournal: ' . $x); } } From 6b1b043dd8fc48511f9288249cd18322b8a709b4 Mon Sep 17 00:00:00 2001 From: Art4 Date: Sat, 30 Nov 2024 19:48:49 +0000 Subject: [PATCH 286/388] fix errors in mailstream addon --- mailstream/phpmailer/class.phpmailer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mailstream/phpmailer/class.phpmailer.php b/mailstream/phpmailer/class.phpmailer.php index ff3d81e34..dcf023615 100644 --- a/mailstream/phpmailer/class.phpmailer.php +++ b/mailstream/phpmailer/class.phpmailer.php @@ -3287,7 +3287,7 @@ class PHPMailer $result = 'localhost.localdomain'; if (!empty($this->Hostname)) { $result = $this->Hostname; - } elseif (isset($_SERVER) and array_key_exists('SERVER_NAME', $_SERVER) and !empty($_SERVER['SERVER_NAME'])) { + } elseif (array_key_exists('SERVER_NAME', $_SERVER) and !empty($_SERVER['SERVER_NAME'])) { $result = $_SERVER['SERVER_NAME']; } elseif (function_exists('gethostname') && gethostname() !== false) { $result = gethostname(); From c0971779c6091f0d3621c38df30d77f4f1b7e021 Mon Sep 17 00:00:00 2001 From: Art4 Date: Sat, 30 Nov 2024 19:50:06 +0000 Subject: [PATCH 287/388] Fix errors in nsfw addon --- nsfw/nsfw.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nsfw/nsfw.php b/nsfw/nsfw.php index 4a54d899e..674fc2012 100644 --- a/nsfw/nsfw.php +++ b/nsfw/nsfw.php @@ -8,7 +8,6 @@ * */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\Core\Renderer; use Friendica\DI; @@ -119,7 +118,9 @@ function nsfw_prepare_body_content_filter(&$hook_data) $word_list = ['nsfw']; } - $found = false; + $found = false; + $tag_search = false; + if (count($word_list)) { $body = $hook_data['item']['title'] . "\n" . nsfw_extract_photos($hook_data['item']['body']); @@ -129,7 +130,6 @@ function nsfw_prepare_body_content_filter(&$hook_data) continue; } - $tag_search = false; switch ($word[0]) { case '/'; // Regular expression $found = @preg_match($word, $body); From 7fa2dfc608d9ac30253ac257c020dfda3061ec8b Mon Sep 17 00:00:00 2001 From: Art4 Date: Sat, 30 Nov 2024 19:51:18 +0000 Subject: [PATCH 288/388] Fix errors in pnut addon --- pnut/lib/phpnut.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pnut/lib/phpnut.php b/pnut/lib/phpnut.php index 5794d795a..89d5e5f89 100644 --- a/pnut/lib/phpnut.php +++ b/pnut/lib/phpnut.php @@ -1339,6 +1339,8 @@ class phpnut */ protected function updateUserImage(string $image, string $which='avatar') { + $mimeType = ''; + $test = @getimagesize($image); if ($test && array_key_exists('mime', $test)) { $mimeType = $test['mime']; From bda683c56b1800d1c2b3847e44074d554ac34c4b Mon Sep 17 00:00:00 2001 From: Art4 Date: Sat, 30 Nov 2024 20:12:23 +0000 Subject: [PATCH 289/388] fix errors in pumpio addon --- pumpio/pumpio.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pumpio/pumpio.php b/pumpio/pumpio.php index 5e053d7c3..d7c2ac326 100644 --- a/pumpio/pumpio.php +++ b/pumpio/pumpio.php @@ -6,7 +6,6 @@ * Author: Michael Vogel */ -use Friendica\App; use Friendica\Content\Text\BBCode; use Friendica\Content\Text\HTML; use Friendica\Core\Addon; @@ -582,6 +581,8 @@ function pumpio_action(int $uid, string $uri, string $action, string $content = $uri = $orig_post['uri']; } + $objectType = ''; + if (($orig_post['object-type'] != '') && (strstr($orig_post['object-type'], ActivityNamespace::ACTIVITY_SCHEMA))) { $objectType = str_replace(ActivityNamespace::ACTIVITY_SCHEMA, '', $orig_post['object-type']); } elseif (strstr($uri, '/api/comment/')) { @@ -827,6 +828,7 @@ function pumpio_dounlike(int $uid, array $self, $post, string $own_id) } $contactid = 0; + $contact = []; if (Strings::compareLink($post->actor->url, $own_id)) { $contactid = $self['id']; @@ -1430,6 +1432,8 @@ function pumpio_fetchallcomments($uid, $id) Logger::notice('pumpio_fetchallcomments: fetching comment for user ' . $uid . ', URL ' . $url); + $item = new \stdClass(); + if (pumpio_reachable($url)) { $success = $client->CallAPI($url, 'GET', [], ['FailOnAccessError' => true], $item); } else { From 5b623c83686b1ac4ac72d15f2072cb380b872ee2 Mon Sep 17 00:00:00 2001 From: Art4 Date: Sat, 30 Nov 2024 20:13:41 +0000 Subject: [PATCH 290/388] fix errors in ratioed addon --- ratioed/RatioedPanel.php | 1 + 1 file changed, 1 insertion(+) diff --git a/ratioed/RatioedPanel.php b/ratioed/RatioedPanel.php index e25c7f341..bd9b44dcd 100644 --- a/ratioed/RatioedPanel.php +++ b/ratioed/RatioedPanel.php @@ -26,6 +26,7 @@ class RatioedPanel extends Active $action = $this->parameters['action'] ?? ''; $uid = $this->parameters['uid'] ?? 0; + $user = []; if ($uid) { $user = User::getById($uid, ['username', 'blocked']); From 8e778593ca014916297ad234587f5cbfb426f4f2 Mon Sep 17 00:00:00 2001 From: Art4 Date: Sat, 30 Nov 2024 20:27:57 +0000 Subject: [PATCH 291/388] fix errors in statusnet addon --- statusnet/library/codebirdsn.php | 13 +++++++------ statusnet/statusnet.php | 2 ++ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/statusnet/library/codebirdsn.php b/statusnet/library/codebirdsn.php index 325bcb072..91e256be0 100644 --- a/statusnet/library/codebirdsn.php +++ b/statusnet/library/codebirdsn.php @@ -31,11 +31,10 @@ use Friendica\Core\System; /** * Define constants */ -$constants = explode(' ', 'OBJECT ARRAY JSON'); -foreach ($constants as $i => $id) { - $id = 'CODEBIRD_RETURNFORMAT_' . $id; - defined($id) or define($id, $i); -} +defined('CODEBIRD_RETURNFORMAT_ARRAY') or define('CODEBIRD_RETURNFORMAT_ARRAY', 0); +defined('CODEBIRD_RETURNFORMAT_JSON') or define('CODEBIRD_RETURNFORMAT_JSON', 1); +defined('CODEBIRD_RETURNFORMAT_OBJECT') or define('CODEBIRD_RETURNFORMAT_OBJECT', 2); + $constants = array( 'CURLE_SSL_CERTPROBLEM' => 58, 'CURLE_SSL_CACERT' => 60, @@ -788,6 +787,8 @@ class CodebirdSN $possible_files = explode(' ', $possible_files[$method]); + $data = ''; + $multipart_border = '--------------------' . $this->_nonce(); $multipart_request = ''; foreach ($params as $key => $value) { @@ -917,7 +918,7 @@ class CodebirdSN $authorization = 'Authorization: Bearer ' . self::$_oauth_bearer_token; } $request_headers = array(); - if (isset($authorization)) { + if ($authorization !== '') { $request_headers[] = $authorization; $request_headers[] = 'Expect:'; } diff --git a/statusnet/statusnet.php b/statusnet/statusnet.php index 4bc32050f..48f9c2542 100644 --- a/statusnet/statusnet.php +++ b/statusnet/statusnet.php @@ -366,6 +366,8 @@ function statusnet_post_hook(array &$b) $otoken = DI::pConfig()->get($b['uid'], 'statusnet', 'oauthtoken'); $osecret = DI::pConfig()->get($b['uid'], 'statusnet', 'oauthsecret'); + $iscomment = null; + if ($ckey && $csecret && $otoken && $osecret) { $dent = new StatusNetOAuth($api, $ckey, $csecret, $otoken, $osecret); $max_char = $dent->get_maxlength(); // max. length for a dent From 2f89827deaa09de0cf8bf2a803645441f424cd9a Mon Sep 17 00:00:00 2001 From: Art4 Date: Sat, 30 Nov 2024 20:36:07 +0000 Subject: [PATCH 292/388] fix errors in tictac addon --- tictac/tictac.php | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/tictac/tictac.php b/tictac/tictac.php index 101038355..082b58c16 100644 --- a/tictac/tictac.php +++ b/tictac/tictac.php @@ -7,7 +7,6 @@ * Status: unsupported */ -use Friendica\App; use Friendica\Core\Hook; use Friendica\DI; @@ -30,7 +29,12 @@ function tictac_module() {} function tictac_content() { - $o = ''; + $o = ''; + $dimen = 3; + $handicap = 0; + $mefirst = 0; + $yours = ''; + $mine = ''; if($_POST['move']) { $handicap = DI::args()->get(1); @@ -45,9 +49,6 @@ function tictac_content() { $handicap = DI::args()->get(1); $dimen = 3; } - else { - $dimen = 3; - } $o .= '

' . DI::l10n()->t('3D Tic-Tac-Toe') . '


'; @@ -163,7 +164,7 @@ class tictac { ]; function __construct($dimen, $handicap, $mefirst, $yours, $mine) { - $this->dimen = 3; + $this->dimen = $dimen; $this->handicap = $handicap ? 1 : 0; $this->mefirst = $mefirst ? 1 : 0; $this->yours = str_replace('XXX','',$yours); @@ -228,6 +229,8 @@ class tictac { } function parse_moves($player) { + $str = ''; + if($player == 'me') $str = $this->mine; if($player == 'you') From a71db771d9473852786cc7435e9b1178b842880f Mon Sep 17 00:00:00 2001 From: Art4 Date: Sat, 30 Nov 2024 20:36:58 +0000 Subject: [PATCH 293/388] Fix errors in wppost addon --- wppost/wppost.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/wppost/wppost.php b/wppost/wppost.php index dba738de4..f2ee5d210 100644 --- a/wppost/wppost.php +++ b/wppost/wppost.php @@ -259,9 +259,11 @@ EOT; Logger::debug('wppost: data: ' . $xml); + $x = ''; + if ($wp_blog !== 'test') { $x = DI::httpClient()->post($wp_blog, $xml)->getBodyString(); } - Logger::info('posted to wordpress: ' . (($x) ? $x : '')); + Logger::info('posted to wordpress: ' . $x); } } From 729b6e52107dd1f3ce870b2fa45b7a8e1f60cc4d Mon Sep 17 00:00:00 2001 From: Artur Weigandt Date: Thu, 5 Dec 2024 18:23:51 +0100 Subject: [PATCH 294/388] Update mailstream/phpmailer/class.phpmailer.php Co-authored-by: Hypolite Petovan --- mailstream/phpmailer/class.phpmailer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mailstream/phpmailer/class.phpmailer.php b/mailstream/phpmailer/class.phpmailer.php index dcf023615..1d9df9afc 100644 --- a/mailstream/phpmailer/class.phpmailer.php +++ b/mailstream/phpmailer/class.phpmailer.php @@ -3287,7 +3287,7 @@ class PHPMailer $result = 'localhost.localdomain'; if (!empty($this->Hostname)) { $result = $this->Hostname; - } elseif (array_key_exists('SERVER_NAME', $_SERVER) and !empty($_SERVER['SERVER_NAME'])) { + } elseif (!empty($_SERVER['SERVER_NAME'])) { $result = $_SERVER['SERVER_NAME']; } elseif (function_exists('gethostname') && gethostname() !== false) { $result = gethostname(); From 3719d1eee5d67424e9bb144a47fe06ba5e87d2a0 Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 6 Dec 2024 06:46:36 +0000 Subject: [PATCH 295/388] Set extid via guid, nit via id --- bluesky/bluesky.php | 4 ++-- tumblr/tumblr.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index dfd7fe060..26ecb9679 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -715,7 +715,7 @@ function bluesky_create_activity(array $item, stdClass $parent = null) } Logger::debug('Activity done', ['return' => $activity]); $uri = bluesky_get_uri($activity); - Item::update(['extid' => $uri], ['id' => $item['id']]); + Item::update(['extid' => $uri], ['guid' => $item['guid']]); Logger::debug('Set extid', ['id' => $item['id'], 'extid' => $activity]); } @@ -806,7 +806,7 @@ function bluesky_create_post(array $item, stdClass $root = null, stdClass $paren } if (($key == 0) && ($item['gravity'] != Item::GRAVITY_PARENT)) { $uri = bluesky_get_uri($parent); - Item::update(['extid' => $uri], ['id' => $item['id']]); + Item::update(['extid' => $uri], ['guid' => $item['guid']]); Logger::debug('Set extid', ['id' => $item['id'], 'extid' => $uri]); } } diff --git a/tumblr/tumblr.php b/tumblr/tumblr.php index 1e9f5c7fa..ecd6f8628 100644 --- a/tumblr/tumblr.php +++ b/tumblr/tumblr.php @@ -564,7 +564,7 @@ function tumblr_send(array &$b) if ($result->meta->status < 400) { Logger::info('Successfully performed activity', ['verb' => $b['verb'], 'deleted' => $b['deleted'], 'meta' => $result->meta, 'response' => $result->response]); if (!$b['deleted'] && !empty($result->response->id_string)) { - Item::update(['extid' => 'tumblr::' . $result->response->id_string], ['id' => $b['id']]); + Item::update(['extid' => 'tumblr::' . $result->response->id_string], ['guid' => $b['guid']]); } } else { Logger::notice('Error while performing activity', ['verb' => $b['verb'], 'deleted' => $b['deleted'], 'meta' => $result->meta, 'response' => $result->response, 'errors' => $result->errors, 'params' => $params]); From f29908464b87916948ce3e6763c01195290b624f Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 12 Dec 2024 20:20:44 +0000 Subject: [PATCH 296/388] Bluesky: Fix token problems --- bluesky/bluesky.php | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index 26ecb9679..6451f3fae 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -416,7 +416,7 @@ function bluesky_get_status(string $handle = null, string $did = null, string $p switch ($status) { case BLUEKSY_STATUS_TOKEN_OK: - return DI::l10n()->t("You are authenticated to Bluesky. For security reasons the password isn't stored."); + return DI::l10n()->t("You are authenticated to Bluesky."); case BLUEKSY_STATUS_SUCCESS: return DI::l10n()->t('The communication with the personal data server service (PDS) is established.'); case BLUEKSY_STATUS_API_FAIL; @@ -447,6 +447,7 @@ function bluesky_settings_post(array &$b) DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'post', intval($_POST['bluesky'])); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'post_by_default', intval($_POST['bluesky_bydefault'])); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'handle', $handle); + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'password', $_POST['bluesky_password']); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'import', intval($_POST['bluesky_import'])); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'import_feeds', intval($_POST['bluesky_import_feeds'])); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'complete_threads', intval($_POST['bluesky_complete_threads'])); @@ -466,6 +467,7 @@ function bluesky_settings_post(array &$b) } else { DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'bluesky', 'did'); DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'bluesky', 'pds'); + DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'bluesky', 'password'); DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'bluesky', 'access_token'); DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'bluesky', 'refresh_token'); DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'bluesky', 'token_created'); @@ -2108,6 +2110,11 @@ function bluesky_refresh_token(int $uid): string $data = bluesky_post($uid, '/xrpc/com.atproto.server.refreshSession', '', ['Authorization' => ['Bearer ' . $token]]); if (empty($data) || empty($data->accessJwt)) { + Logger::debug('Refresh failed', ['return' => $data]); + $password = DI::pConfig()->get($uid, 'bluesky', 'password'); + if (!empty($password)) { + return bluesky_create_token($uid, $password); + } DI::pConfig()->set($uid, 'bluesky', 'status', BLUEKSY_STATUS_TOKEN_FAIL); return ''; } @@ -2174,7 +2181,11 @@ function bluesky_post(int $uid, string $url, string $params, array $headers): ?s $data->code = $curlResult->getReturnCode(); } - DI::pConfig()->set($uid, 'bluesky', 'status', BLUEKSY_STATUS_SUCCESS); + if (!empty($data->code) && ($data->code >= 200) && ($data->code < 400)) { + DI::pConfig()->set($uid, 'bluesky', 'status', BLUEKSY_STATUS_SUCCESS); + } else { + DI::pConfig()->set($uid, 'bluesky', 'status', BLUEKSY_STATUS_API_FAIL); + } return $data; } @@ -2197,7 +2208,9 @@ function bluesky_xrpc_get(int $uid, string $url, array $parameters = []): ?stdCl } $data = bluesky_get($pds . '/xrpc/' . $url, HttpClientAccept::JSON, [HttpClientOptions::HEADERS => $headers]); - DI::pConfig()->set($uid, 'bluesky', 'status', is_null($data) ? BLUEKSY_STATUS_API_FAIL : BLUEKSY_STATUS_SUCCESS); + if ($uid != 0) { + DI::pConfig()->set($uid, 'bluesky', 'status', is_null($data) ? BLUEKSY_STATUS_API_FAIL : BLUEKSY_STATUS_SUCCESS); + } return $data; } From 52b18c7d9a7df1dcd6adb1f1d4d25fa0653c76cc Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 14 Dec 2024 19:03:15 +0000 Subject: [PATCH 297/388] Bluesky: Functionality moved to the core --- bluesky/bluesky.php | 1267 ++++--------------------------------------- 1 file changed, 91 insertions(+), 1176 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index 6451f3fae..c9c7dc67e 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -26,7 +26,6 @@ */ use Friendica\Content\Text\BBCode; -use Friendica\Content\Text\HTML; use Friendica\Content\Text\Plaintext; use Friendica\Core\Cache\Enum\Duration; use Friendica\Core\Config\Util\ConfigFileManager; @@ -39,42 +38,20 @@ use Friendica\Database\DBA; use Friendica\DI; use Friendica\Model\Contact; use Friendica\Model\Conversation; -use Friendica\Model\GServer; use Friendica\Model\Item; -use Friendica\Model\ItemURI; use Friendica\Model\Photo; use Friendica\Model\Post; -use Friendica\Model\Tag; use Friendica\Model\User; -use Friendica\Network\HTTPClient\Client\HttpClientAccept; -use Friendica\Network\HTTPClient\Client\HttpClientOptions; -use Friendica\Network\HTTPClient\Client\HttpClientRequest; use Friendica\Object\Image; use Friendica\Protocol\Activity; +use Friendica\Protocol\ATProtocol; use Friendica\Protocol\Relay; use Friendica\Util\DateTimeFormat; -use Friendica\Util\Network; use Friendica\Util\Strings; const BLUESKY_DEFAULT_POLL_INTERVAL = 10; // given in minutes const BLUESKY_IMAGE_SIZE = [1000000, 500000, 100000, 50000]; -const BLUEKSY_STATUS_UNKNOWN = 0; -const BLUEKSY_STATUS_TOKEN_OK = 1; -const BLUEKSY_STATUS_SUCCESS = 2; -const BLUEKSY_STATUS_API_FAIL = 10; -const BLUEKSY_STATUS_DID_FAIL = 11; -const BLUEKSY_STATUS_PDS_FAIL = 12; -const BLUEKSY_STATUS_TOKEN_FAIL = 13; - -/* - * (Currently) hard wired paths for Bluesky services - */ -const BLUESKY_APPVIEW_API = 'https://public.api.bsky.app'; // Path to the public Bluesky AppView API. -const BLUESKY_DIRECTORY = 'https://plc.directory'; // Path to the directory server service to fetch the PDS of a given DID -const BLUESKY_WEB = 'https://bsky.app'; // Path to the web interface with the user profile and posts -const BLUESKY_HOSTNAME = 'bsky.social'; // Host name to be added to the handle if incomplete - function bluesky_install() { Hook::register('load_config', __FILE__, 'bluesky_load_config'); @@ -86,13 +63,11 @@ function bluesky_install() Hook::register('connector_settings_post', __FILE__, 'bluesky_settings_post'); Hook::register('cron', __FILE__, 'bluesky_cron'); Hook::register('support_follow', __FILE__, 'bluesky_support_follow'); - Hook::register('support_probe', __FILE__, 'bluesky_support_probe'); Hook::register('follow', __FILE__, 'bluesky_follow'); Hook::register('unfollow', __FILE__, 'bluesky_unfollow'); Hook::register('block', __FILE__, 'bluesky_block'); Hook::register('unblock', __FILE__, 'bluesky_unblock'); Hook::register('check_item_notification', __FILE__, 'bluesky_check_item_notification'); - Hook::register('probe_detect', __FILE__, 'bluesky_probe_detect'); Hook::register('item_by_link', __FILE__, 'bluesky_item_by_link'); } @@ -107,7 +82,7 @@ function bluesky_check_item_notification(array &$notification_data) return; } - $did = bluesky_get_user_did($notification_data['uid']); + $did = DI::atProtocol()->getUserDid($notification_data['uid']); if (empty($did)) { return; } @@ -115,61 +90,6 @@ function bluesky_check_item_notification(array &$notification_data) $notification_data['profiles'][] = $did; } -function bluesky_probe_detect(array &$hookData) -{ - // Don't overwrite an existing result - if (isset($hookData['result'])) { - return; - } - - // Avoid a lookup for the wrong network - if (!in_array($hookData['network'], ['', Protocol::BLUESKY])) { - return; - } - - $pconfig = DBA::selectFirst('pconfig', ['uid'], ["`cat` = ? AND `k` = ? AND `v` != ?", 'bluesky', 'access_token', '']); - if (empty($pconfig['uid'])) { - return; - } - - if (parse_url($hookData['uri'], PHP_URL_SCHEME) == 'did') { - $did = $hookData['uri']; - } elseif (parse_url($hookData['uri'], PHP_URL_PATH) == $hookData['uri'] && strpos($hookData['uri'], '@') === false) { - $did = bluesky_get_did($hookData['uri'], $pconfig['uid']); - if (empty($did)) { - return; - } - } elseif (Network::isValidHttpUrl($hookData['uri'])) { - $did = bluesky_get_did_by_profile($hookData['uri'], $pconfig['uid']); - if (empty($did)) { - return; - } - } else { - return; - } - - $token = bluesky_get_token($pconfig['uid']); - if (empty($token)) { - return; - } - - $data = bluesky_xrpc_get($pconfig['uid'], 'app.bsky.actor.getProfile', ['actor' => $did]); - if (empty($data) || empty($data->did)) { - return; - } - - $hookData['result'] = bluesky_get_contact_fields($data, 0, $pconfig['uid'], true); - - // Preparing probe data. This differs slightly from the contact array - $hookData['result']['photo'] = $data->avatar ?? ''; - $hookData['result']['batch'] = ''; - $hookData['result']['notify'] = ''; - $hookData['result']['poll'] = ''; - $hookData['result']['poco'] = ''; - $hookData['result']['priority'] = 0; - $hookData['result']['guid'] = ''; -} - function bluesky_item_by_link(array &$hookData) { // Don't overwrite an existing result @@ -177,16 +97,17 @@ function bluesky_item_by_link(array &$hookData) return; } - $token = bluesky_get_token($hookData['uid']); + $token = DI::atProtocol()->getUserToken($hookData['uid']); if (empty($token)) { return; } - if (!preg_match('#^' . BLUESKY_WEB . '/profile/(.+)/post/(.+)#', $hookData['uri'], $matches)) { + // @todo also support the URI format (at://did/app.bsky.feed.post/cid) + if (!preg_match('#^' . ATProtocol::WEB . '/profile/(.+)/post/(.+)#', $hookData['uri'], $matches)) { return; } - $did = bluesky_get_did($matches[1], $hookData['uid']); + $did = DI::atProtocol()->getDid($matches[1]); if (empty($did)) { return; } @@ -195,7 +116,7 @@ function bluesky_item_by_link(array &$hookData) $uri = 'at://' . $did . '/app.bsky.feed.post/' . $matches[2]; - $uri = bluesky_fetch_missing_post($uri, $hookData['uid'], $hookData['uid'], Item::PR_FETCHED, 0, 0, 0); + $uri = DI::atpProcessor()->fetchMissingPost($uri, $hookData['uid'], Item::PR_FETCHED, 0, 0); Logger::debug('Got post', ['did' => $did, 'cid' => $matches[2], 'result' => $uri]); if (!empty($uri)) { $item = Post::selectFirst(['id'], ['uri' => $uri, 'uid' => $hookData['uid']]); @@ -212,16 +133,9 @@ function bluesky_support_follow(array &$data) } } -function bluesky_support_probe(array &$data) -{ - if ($data['protocol'] == Protocol::BLUESKY) { - $data['result'] = true; - } -} - function bluesky_follow(array &$hook_data) { - $token = bluesky_get_token($hook_data['uid']); + $token = DI::atProtocol()->getUserToken($hook_data['uid']); if (empty($token)) { return; } @@ -240,11 +154,11 @@ function bluesky_follow(array &$hook_data) $post = [ 'collection' => 'app.bsky.graph.follow', - 'repo' => bluesky_get_user_did($hook_data['uid']), + 'repo' => DI::atProtocol()->getUserDid($hook_data['uid']), 'record' => $record ]; - $activity = bluesky_xrpc_post($hook_data['uid'], 'com.atproto.repo.createRecord', $post); + $activity = DI::atProtocol()->XRPCPost($hook_data['uid'], 'com.atproto.repo.createRecord', $post); if (!empty($activity->uri)) { $hook_data['contact'] = $contact; Logger::debug('Successfully start following', ['url' => $contact['url'], 'uri' => $activity->uri]); @@ -253,7 +167,7 @@ function bluesky_follow(array &$hook_data) function bluesky_unfollow(array &$hook_data) { - $token = bluesky_get_token($hook_data['uid']); + $token = DI::atProtocol()->getUserToken($hook_data['uid']); if (empty($token)) { return; } @@ -262,7 +176,7 @@ function bluesky_unfollow(array &$hook_data) return; } - $data = bluesky_xrpc_get($hook_data['uid'], 'app.bsky.actor.getProfile', ['actor' => $hook_data['contact']['url']]); + $data = DI::atProtocol()->XRPCGet('app.bsky.actor.getProfile', ['actor' => $hook_data['contact']['url']], $hook_data['uid']); if (empty($data->viewer) || empty($data->viewer->following)) { return; } @@ -274,7 +188,7 @@ function bluesky_unfollow(array &$hook_data) function bluesky_block(array &$hook_data) { - $token = bluesky_get_token($hook_data['uid']); + $token = DI::atProtocol()->getUserToken($hook_data['uid']); if (empty($token)) { return; } @@ -291,11 +205,11 @@ function bluesky_block(array &$hook_data) $post = [ 'collection' => 'app.bsky.graph.block', - 'repo' => bluesky_get_user_did($hook_data['uid']), + 'repo' => DI::atProtocol()->getUserDid($hook_data['uid']), 'record' => $record ]; - $activity = bluesky_xrpc_post($hook_data['uid'], 'com.atproto.repo.createRecord', $post); + $activity = DI::atProtocol()->XRPCPost($hook_data['uid'], 'com.atproto.repo.createRecord', $post); if (!empty($activity->uri)) { $ucid = Contact::getUserContactId($hook_data['contact']['id'], $hook_data['uid']); if ($ucid) { @@ -307,7 +221,7 @@ function bluesky_block(array &$hook_data) function bluesky_unblock(array &$hook_data) { - $token = bluesky_get_token($hook_data['uid']); + $token = DI::atProtocol()->getUserToken($hook_data['uid']); if (empty($token)) { return; } @@ -316,7 +230,7 @@ function bluesky_unblock(array &$hook_data) return; } - $data = bluesky_xrpc_get($hook_data['uid'], 'app.bsky.actor.getProfile', ['actor' => $hook_data['contact']['url']]); + $data = DI::atProtocol()->XRPCGet('app.bsky.actor.getProfile', ['actor' => $hook_data['contact']['url']], $hook_data['uid']); if (empty($data->viewer) || empty($data->viewer->blocking)) { return; } @@ -351,7 +265,7 @@ function bluesky_settings(array &$data) $def_enabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'post_by_default') ?? false; $pds = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'pds'); $handle = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'handle'); - $did = bluesky_get_user_did(DI::userSession()->getLocalUserId()); + $did = DI::atProtocol()->getUserDid(DI::userSession()->getLocalUserId()); $token = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'access_token'); $import = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'import') ?? false; $import_feeds = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'import_feeds') ?? false; @@ -399,33 +313,33 @@ function bluesky_get_status(string $handle = null, string $did = null, string $p return DI::l10n()->t('You are not authenticated. Please enter your handle and the app password.'); } - $status = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'status') ?? BLUEKSY_STATUS_UNKNOWN; + $status = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'status') ?? ATProtocol::STATUS_UNKNOWN; // Fallback mechanism for connection that had been established before the introduction of the status - if ($status == BLUEKSY_STATUS_UNKNOWN) { + if ($status == ATProtocol::STATUS_UNKNOWN) { if (empty($did)) { - $status = BLUEKSY_STATUS_DID_FAIL; + $status = ATProtocol::STATUS_DID_FAIL; } elseif (empty($pds)) { - $status = BLUEKSY_STATUS_PDS_FAIL; + $status = ATProtocol::STATUS_PDS_FAIL; } elseif (!empty($token)) { - $status = BLUEKSY_STATUS_TOKEN_OK; + $status = ATProtocol::STATUS_TOKEN_OK; } else { - $status = BLUEKSY_STATUS_TOKEN_FAIL; + $status = ATProtocol::STATUS_TOKEN_FAIL; } } switch ($status) { - case BLUEKSY_STATUS_TOKEN_OK: + case ATProtocol::STATUS_TOKEN_OK: return DI::l10n()->t("You are authenticated to Bluesky."); - case BLUEKSY_STATUS_SUCCESS: + case ATProtocol::STATUS_SUCCESS: return DI::l10n()->t('The communication with the personal data server service (PDS) is established.'); - case BLUEKSY_STATUS_API_FAIL; + case ATProtocol::STATUS_API_FAIL; return DI::l10n()->t('Communication issues with the personal data server service (PDS).'); - case BLUEKSY_STATUS_DID_FAIL: + case ATProtocol::STATUS_DID_FAIL: return DI::l10n()->t('The DID for the provided handle could not be detected. Please check if you entered the correct handle.'); - case BLUEKSY_STATUS_PDS_FAIL: + case ATProtocol::STATUS_PDS_FAIL: return DI::l10n()->t('The personal data server service (PDS) could not be detected.'); - case BLUEKSY_STATUS_TOKEN_FAIL: + case ATProtocol::STATUS_TOKEN_FAIL: return DI::l10n()->t('The authentication with the provided handle and password failed. Please check if you entered the correct password.'); default: return ''; @@ -454,11 +368,11 @@ function bluesky_settings_post(array &$b) DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'friendica_handle', intval($_POST['bluesky_friendica_handle'] ?? false)); if (!empty($handle)) { - $did = bluesky_get_user_did(DI::userSession()->getLocalUserId(), empty($old_did) || $old_handle != $handle); + $did = DI::atProtocol()->getUserDid(DI::userSession()->getLocalUserId(), empty($old_did) || $old_handle != $handle); if (!empty($did) && (empty($old_pds) || $old_handle != $handle)) { - $pds = bluesky_get_pds($did); + $pds = DI::atProtocol()->getPdsOfDid($did); if (empty($pds)) { - DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'status', BLUEKSY_STATUS_PDS_FAIL); + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'status', ATProtocol::STATUS_PDS_FAIL); } DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'pds', $pds); } else { @@ -475,7 +389,7 @@ function bluesky_settings_post(array &$b) } if (!empty($did) && !empty($pds) && !empty($_POST['bluesky_password'])) { - bluesky_create_token(DI::userSession()->getLocalUserId(), $_POST['bluesky_password']); + DI::atProtocol()->createUserToken(DI::userSession()->getLocalUserId(), $_POST['bluesky_password']); } } @@ -524,7 +438,7 @@ function bluesky_cron() $pconfigs = DBA::selectToArray('pconfig', [], ["`cat` = ? AND `k` IN (?, ?) AND `v`", 'bluesky', 'import', 'import_feeds']); foreach ($pconfigs as $pconfig) { - if (empty(bluesky_get_user_did($pconfig['uid']))) { + if (empty(DI::atProtocol()->getUserDid($pconfig['uid']))) { Logger::debug('User has got no valid DID', ['uid' => $pconfig['uid']]); continue; } @@ -538,7 +452,13 @@ function bluesky_cron() // Refresh the token now, so that it doesn't need to be refreshed in parallel by the following workers Logger::debug('Refresh the token', ['uid' => $pconfig['uid']]); - bluesky_get_token($pconfig['uid']); + DI::atProtocol()->getUserToken($pconfig['uid']); + + $last_sync = DI::pConfig()->get($pconfig['uid'], 'bluesky', 'last_contact_sync'); + if ($last_sync < (time() - 86400)) { + DI::atpActor()->syncContacts($pconfig['uid']); + DI::pConfig()->set($pconfig['uid'], 'bluesky', 'last_contact_sync', time()); + } Worker::add(['priority' => Worker::PRIORITY_MEDIUM, 'force_priority' => true], 'addon/bluesky/bluesky_notifications.php', $pconfig['uid']); if (DI::pConfig()->get($pconfig['uid'], 'bluesky', 'import')) { @@ -640,7 +560,7 @@ function bluesky_send(array &$b) Logger::debug('Got comment', ['item' => $b]); if ($b['deleted']) { - $uri = bluesky_get_uri_class($b['uri']); + $uri = DI::atpProcessor()->getUriClass($b['uri']); if (empty($uri)) { Logger::debug('Not a bluesky post', ['uri' => $b['uri']]); return; @@ -649,8 +569,8 @@ function bluesky_send(array &$b) return; } - $root = bluesky_get_uri_class($b['parent-uri']); - $parent = bluesky_get_uri_class($b['thr-parent']); + $root = DI::atpProcessor()->getUriClass($b['parent-uri']); + $parent = DI::atpProcessor()->getUriClass($b['thr-parent']); if (empty($root) || empty($parent)) { Logger::debug('No bluesky post', ['parent' => $b['parent'], 'thr-parent' => $b['thr-parent']]); @@ -675,12 +595,12 @@ function bluesky_send(array &$b) function bluesky_create_activity(array $item, stdClass $parent = null) { $uid = $item['uid']; - $token = bluesky_get_token($uid); + $token = DI::atProtocol()->getUserToken($uid); if (empty($token)) { return; } - $did = bluesky_get_user_did($uid); + $did = DI::atProtocol()->getUserDid($uid); if (empty($did)) { return; } @@ -711,12 +631,12 @@ function bluesky_create_activity(array $item, stdClass $parent = null) ]; } - $activity = bluesky_xrpc_post($uid, 'com.atproto.repo.createRecord', $post); + $activity = DI::atProtocol()->XRPCPost($uid, 'com.atproto.repo.createRecord', $post); if (empty($activity->uri)) { return; } Logger::debug('Activity done', ['return' => $activity]); - $uri = bluesky_get_uri($activity); + $uri = DI::atpProcessor()->getUri($activity); Item::update(['extid' => $uri], ['guid' => $item['guid']]); Logger::debug('Set extid', ['id' => $item['id'], 'extid' => $activity]); } @@ -724,7 +644,7 @@ function bluesky_create_activity(array $item, stdClass $parent = null) function bluesky_create_post(array $item, stdClass $root = null, stdClass $parent = null) { $uid = $item['uid']; - $token = bluesky_get_token($uid); + $token = DI::atProtocol()->getUserToken($uid); if (empty($token)) { return; } @@ -791,11 +711,11 @@ function bluesky_create_post(array $item, stdClass $root = null, stdClass $paren $post = [ 'collection' => 'app.bsky.feed.post', - 'repo' => bluesky_get_user_did($uid), + 'repo' => DI::atProtocol()->getUserDid($uid), 'record' => $record ]; - $parent = bluesky_xrpc_post($uid, 'com.atproto.repo.createRecord', $post); + $parent = DI::atProtocol()->XRPCPost($uid, 'com.atproto.repo.createRecord', $post); if (empty($parent->uri)) { if ($part == 0) { Worker::defer(); @@ -807,7 +727,7 @@ function bluesky_create_post(array $item, stdClass $root = null, stdClass $paren $root = $parent; } if (($key == 0) && ($item['gravity'] != Item::GRAVITY_PARENT)) { - $uri = bluesky_get_uri($parent); + $uri = DI::atpProcessor()->getUri($parent); Item::update(['extid' => $uri], ['guid' => $item['guid']]); Logger::debug('Set extid', ['id' => $item['id'], 'extid' => $uri]); } @@ -973,7 +893,7 @@ function bluesky_upload_blob(int $uid, array $photo): ?stdClass Logger::info('Uploading', ['uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size]); - $data = bluesky_post($uid, '/xrpc/com.atproto.repo.uploadBlob', $content, ['Content-type' => $photo['type'], 'Authorization' => ['Bearer ' . bluesky_get_token($uid)]]); + $data = DI::atProtocol()->post($uid, '/xrpc/com.atproto.repo.uploadBlob', $content, ['Content-type' => $photo['type'], 'Authorization' => ['Bearer ' . DI::atProtocol()->getUserToken($uid)]]); if (empty($data) || empty($data->blob)) { Logger::info('Uploading failed', ['uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size]); return null; @@ -986,18 +906,18 @@ function bluesky_upload_blob(int $uid, array $photo): ?stdClass function bluesky_delete_post(string $uri, int $uid) { - $parts = bluesky_get_uri_parts($uri); + $parts = DI::atpProcessor()->getUriParts($uri); if (empty($parts)) { Logger::debug('No uri delected', ['uri' => $uri]); return; } - bluesky_xrpc_post($uid, 'com.atproto.repo.deleteRecord', $parts); + DI::atProtocol()->XRPCPost($uid, 'com.atproto.repo.deleteRecord', $parts); Logger::debug('Deleted', ['parts' => $parts]); } function bluesky_fetch_timeline(int $uid) { - $data = bluesky_xrpc_get($uid, 'app.bsky.feed.getTimeline'); + $data = DI::atProtocol()->XRPCGet('app.bsky.feed.getTimeline', [], $uid); if (empty($data)) { return; } @@ -1006,42 +926,39 @@ function bluesky_fetch_timeline(int $uid) return; } - $last_post = DBA::selectFirst('post-thread-user', ['received'], ['network' => Protocol::BLUESKY, 'uid' => $uid], ['order' => ['received' => true]]); - $last_poll = !empty($last_post['received']) ? strtotime($last_post['received']) : 0; - foreach (array_reverse($data->feed) as $entry) { - $causer = bluesky_get_contact($entry->post->author, 0, $uid); + $causer = DI::atpActor()->getContactByDID($entry->post->author->did, $uid, 0, true); if (!empty($entry->reply)) { if (!empty($entry->reply->root)) { - bluesky_complete_post($entry->reply->root, $uid, Item::PR_COMMENT, $causer['id'], $last_poll, Conversation::PARCEL_CONNECTOR); + bluesky_complete_post($entry->reply->root, $uid, Item::PR_COMMENT, $causer['id'], Conversation::PARCEL_CONNECTOR); } if (!empty($entry->reply->parent)) { - bluesky_complete_post($entry->reply->parent, $uid, Item::PR_COMMENT, $causer['id'], $last_poll, Conversation::PARCEL_CONNECTOR); + bluesky_complete_post($entry->reply->parent, $uid, Item::PR_COMMENT, $causer['id'], Conversation::PARCEL_CONNECTOR); } } - bluesky_process_post($entry->post, $uid, $uid, Item::PR_NONE, 0, 0, $last_poll, Conversation::PARCEL_CONNECTOR); + DI::atpProcessor()->processPost($entry->post, $uid, Item::PR_NONE, 0, 0, Conversation::PARCEL_CONNECTOR); if (!empty($entry->reason)) { - bluesky_process_reason($entry->reason, bluesky_get_uri($entry->post), $uid); + bluesky_process_reason($entry->reason, DI::atpProcessor()->getUri($entry->post), $uid); } } } -function bluesky_complete_post(stdClass $post, int $uid, int $post_reason, int $causer, int $last_poll, int $protocol): int +function bluesky_complete_post(stdClass $post, int $uid, int $post_reason, int $causer, int $protocol): int { $complete = DI::pConfig()->get($uid, 'bluesky', 'complete_threads'); - $existing_uri = bluesky_fetch_post(bluesky_get_uri($post), $uid); + $existing_uri = DI::atpProcessor()->getPostUri(DI::atpProcessor()->getUri($post), $uid); if (!empty($existing_uri)) { $comments = Post::countPosts(['thr-parent' => $existing_uri, 'gravity' => Item::GRAVITY_COMMENT]); if (($post->replyCount <= $comments) || !$complete) { - return bluesky_fetch_uri_id($existing_uri, $uid); + return DI::atpProcessor()->fetchUriId($existing_uri, $uid); } } if ($complete) { - $uri = bluesky_fetch_missing_post(bluesky_get_uri($post), $uid, $uid, $post_reason, $causer, 0, $last_poll, '', true); - $uri_id = bluesky_fetch_uri_id($uri, $uid); + $uri = DI::atpProcessor()->fetchMissingPost(DI::atpProcessor()->getUri($post), $uid, $post_reason, $causer, 0, '', true); + $uri_id = DI::atpProcessor()->fetchUriId($uri, $uid); } else { - $uri_id = bluesky_process_post($post, $uid, $uid, $post_reason, $causer, 0, $last_poll, $protocol); + $uri_id = DI::atpProcessor()->processPost($post, $uid, $post_reason, $causer, 0, $protocol); } return $uri_id; } @@ -1053,7 +970,7 @@ function bluesky_process_reason(stdClass $reason, string $uri, int $uid) return; } - $contact = bluesky_get_contact($reason->by, $uid, $uid); + $contact = DI::atpActor()->getContactByDID($reason->by->did, $uid, 0); $item = [ 'network' => Protocol::BLUESKY, @@ -1089,16 +1006,13 @@ function bluesky_process_reason(stdClass $reason, string $uri, int $uid) function bluesky_fetch_notifications(int $uid) { - $data = bluesky_xrpc_get($uid, 'app.bsky.notification.listNotifications'); + $data = DI::atProtocol()->XRPCGet('app.bsky.notification.listNotifications', [], $uid); if (empty($data->notifications)) { return; } - $last_post = DBA::selectFirst('post-thread-user', ['received'], ['network' => Protocol::BLUESKY, 'uid' => $uid], ['order' => ['received' => true]]); - $last_poll = !empty($last_post['received']) ? strtotime($last_post['received']) : 0; - foreach ($data->notifications as $notification) { - $uri = bluesky_get_uri($notification); + $uri = DI::atpProcessor()->getUri($notification); if (Post::exists(['uri' => $uri, 'uid' => $uid]) || Post::exists(['extid' => $uri, 'uid' => $uid])) { Logger::debug('Notification already processed', ['uid' => $uid, 'reason' => $notification->reason, 'uri' => $uri, 'indexedAt' => $notification->indexedAt]); continue; @@ -1106,11 +1020,11 @@ function bluesky_fetch_notifications(int $uid) Logger::debug('Process notification', ['uid' => $uid, 'reason' => $notification->reason, 'uri' => $uri, 'indexedAt' => $notification->indexedAt]); switch ($notification->reason) { case 'like': - $item = bluesky_get_header($notification, $uri, $uid, $uid, $last_poll, Conversation::PARCEL_CONNECTOR); + $item = DI::atpProcessor()->getHeaderFromPost($notification, $uri, $uid, Conversation::PARCEL_CONNECTOR); $item['gravity'] = Item::GRAVITY_ACTIVITY; $item['body'] = $item['verb'] = Activity::LIKE; - $item['thr-parent'] = bluesky_get_uri($notification->record->subject); - $item['thr-parent'] = bluesky_fetch_missing_post($item['thr-parent'], $uid, $uid, Item::PR_FETCHED, $item['contact-id'], 0, $last_poll); + $item['thr-parent'] = DI::atpProcessor()->getUri($notification->record->subject); + $item['thr-parent'] = DI::atpProcessor()->fetchMissingPost($item['thr-parent'], $uid, Item::PR_FETCHED, $item['contact-id'], 0); if (!empty($item['thr-parent'])) { $data = Item::insert($item); Logger::debug('Got like', ['uid' => $uid, 'result' => $data, 'uri' => $uri]); @@ -1120,11 +1034,11 @@ function bluesky_fetch_notifications(int $uid) break; case 'repost': - $item = bluesky_get_header($notification, $uri, $uid, $uid, $last_poll, Conversation::PARCEL_CONNECTOR); + $item = DI::atpProcessor()->getHeaderFromPost($notification, $uri, $uid, Conversation::PARCEL_CONNECTOR); $item['gravity'] = Item::GRAVITY_ACTIVITY; $item['body'] = $item['verb'] = Activity::ANNOUNCE; - $item['thr-parent'] = bluesky_get_uri($notification->record->subject); - $item['thr-parent'] = bluesky_fetch_missing_post($item['thr-parent'], $uid, $uid, Item::PR_FETCHED, $item['contact-id'], 0, $last_poll); + $item['thr-parent'] = DI::atpProcessor()->getUri($notification->record->subject); + $item['thr-parent'] = DI::atpProcessor()->fetchMissingPost($item['thr-parent'], $uid, Item::PR_FETCHED, $item['contact-id'], 0); if (!empty($item['thr-parent'])) { $data = Item::insert($item); Logger::debug('Got repost', ['uid' => $uid, 'result' => $data, 'uri' => $uri]); @@ -1134,25 +1048,25 @@ function bluesky_fetch_notifications(int $uid) break; case 'follow': - $contact = bluesky_get_contact($notification->author, $uid, $uid); + $contact = DI::atpActor()->getContactByDID($notification->author->did, $uid, $uid); Logger::debug('New follower', ['uid' => $uid, 'nick' => $contact['nick'], 'uri' => $uri]); break; case 'mention': - $contact = bluesky_get_contact($notification->author, 0, $uid); - $result = bluesky_fetch_missing_post($uri, $uid, $uid, Item::PR_TO, $contact['id'], 0, $last_poll); + $contact = DI::atpActor()->getContactByDID($notification->author->did, $uid, 0); + $result = DI::atpProcessor()->fetchMissingPost($uri, $uid, Item::PR_TO, $contact['id'], 0); Logger::debug('Got mention', ['uid' => $uid, 'nick' => $contact['nick'], 'result' => $result, 'uri' => $uri]); break; case 'reply': - $contact = bluesky_get_contact($notification->author, 0, $uid); - $result = bluesky_fetch_missing_post($uri, $uid, $uid, Item::PR_COMMENT, $contact['id'], 0, $last_poll); + $contact = DI::atpActor()->getContactByDID($notification->author->did, $uid, 0); + $result = DI::atpProcessor()->fetchMissingPost($uri, $uid, Item::PR_COMMENT, $contact['id'], 0); Logger::debug('Got reply', ['uid' => $uid, 'nick' => $contact['nick'], 'result' => $result, 'uri' => $uri]); break; case 'quote': - $contact = bluesky_get_contact($notification->author, 0, $uid); - $result = bluesky_fetch_missing_post($uri, $uid, $uid, Item::PR_PUSHED, $contact['id'], 0, $last_poll); + $contact = DI::atpActor()->getContactByDID($notification->author->did, $uid, 0); + $result = DI::atpProcessor()->fetchMissingPost($uri, $uid, Item::PR_PUSHED, $contact['id'], 0); Logger::debug('Got quote', ['uid' => $uid, 'nick' => $contact['nick'], 'result' => $result, 'uri' => $uri]); break; @@ -1165,7 +1079,7 @@ function bluesky_fetch_notifications(int $uid) function bluesky_fetch_feed(int $uid, string $feed) { - $data = bluesky_xrpc_get($uid, 'app.bsky.feed.getFeed', ['feed' => $feed]); + $data = DI::atProtocol()->XRPCGet('app.bsky.feed.getFeed', ['feed' => $feed], $uid); if (empty($data)) { return; } @@ -1174,10 +1088,7 @@ function bluesky_fetch_feed(int $uid, string $feed) return; } - $last_post = DBA::selectFirst('post-thread-user', ['received'], ['network' => Protocol::BLUESKY, 'uid' => $uid], ['order' => ['received' => true]]); - $last_poll = !empty($last_post['received']) ? strtotime($last_post['received']) : 0; - - $feeddata = bluesky_xrpc_get($uid, 'app.bsky.feed.getFeedGenerator', ['feed' => $feed]); + $feeddata = DI::atProtocol()->XRPCGet('app.bsky.feed.getFeedGenerator', ['feed' => $feed], $uid); if (!empty($feeddata) && !empty($feeddata->view)) { $feedurl = $feeddata->view->uri; $feedname = $feeddata->view->displayName; @@ -1187,15 +1098,15 @@ function bluesky_fetch_feed(int $uid, string $feed) } foreach (array_reverse($data->feed) as $entry) { - $contact = bluesky_get_contact($entry->post->author, 0, $uid); + $contact = DI::atpActor()->getContactByDID($entry->post->author->did, $uid, 0); $languages = $entry->post->record->langs ?? []; if (!Relay::isWantedLanguage($entry->post->record->text, 0, $contact['id'] ?? 0, $languages)) { Logger::debug('Unwanted language detected', ['languages' => $languages, 'text' => $entry->post->record->text]); continue; } - $causer = bluesky_get_contact($entry->post->author, 0, $uid); - $uri_id = bluesky_complete_post($entry->post, $uid, Item::PR_TAG, $causer['id'], $last_poll, Conversation::PARCEL_CONNECTOR); + $causer = DI::atpActor()->getContactByDID($entry->post->author->did, $uid, 0); + $uri_id = bluesky_complete_post($entry->post, $uid, Item::PR_TAG, $causer['id'], Conversation::PARCEL_CONNECTOR); if (!empty($uri_id)) { $stored = Post\Category::storeFileByURIId($uri_id, $uid, Post\Category::SUBCRIPTION, $feedname, $feedurl); Logger::debug('Stored tag subscription for user', ['uri-id' => $uri_id, 'uid' => $uid, 'name' => $feedname, 'url' => $feedurl, 'stored' => $stored]); @@ -1203,641 +1114,11 @@ function bluesky_fetch_feed(int $uid, string $feed) Logger::notice('Post not found', ['entry' => $entry]); } if (!empty($entry->reason)) { - bluesky_process_reason($entry->reason, bluesky_get_uri($entry->post), $uid); + bluesky_process_reason($entry->reason, DI::atpProcessor()->getUri($entry->post), $uid); } } } -function bluesky_process_post(stdClass $post, int $uid, int $fetch_uid, int $post_reason, int $causer, int $level, int $last_poll, int $protocol): int -{ - $uri = bluesky_get_uri($post); - - if ($uri_id = bluesky_fetch_uri_id($uri, $uid)) { - return $uri_id; - } - - if (empty($post->record)) { - Logger::debug('Invalid post', ['uri' => $uri]); - return 0; - } - - Logger::debug('Importing post', ['uid' => $uid, 'indexedAt' => $post->indexedAt, 'uri' => $post->uri, 'cid' => $post->cid, 'root' => $post->record->reply->root ?? '']); - - $item = bluesky_get_header($post, $uri, $uid, $fetch_uid, $last_poll, $protocol); - $item = bluesky_get_content($item, $post->record, $uri, $uid, $fetch_uid, $level, $last_poll); - if (empty($item)) { - return 0; - } - - if (!empty($post->embed)) { - $item = bluesky_add_media($post->embed, $item, $uid, $level, $last_poll); - } - - $item['restrictions'] = bluesky_get_restrictions_for_user($post, $item, $post_reason); - - if (empty($item['post-reason'])) { - $item['post-reason'] = $post_reason; - } - - if ($causer != 0) { - $item['causer-id'] = $causer; - } - - Item::insert($item); - return bluesky_fetch_uri_id($uri, $uid); -} - -function bluesky_get_header(stdClass $post, string $uri, int $uid, int $fetch_uid, int $last_poll, int $protocol): array -{ - $parts = bluesky_get_uri_parts($uri); - if (empty($post->author) || empty($post->cid) || empty($parts->rkey)) { - return []; - } - $contact = bluesky_get_contact($post->author, $uid, $fetch_uid); - $item = [ - 'network' => Protocol::BLUESKY, - 'protocol' => $protocol, - 'uid' => $uid, - 'wall' => false, - 'uri' => $uri, - 'guid' => $post->cid, - 'received' => DateTimeFormat::utc($post->indexedAt, DateTimeFormat::MYSQL), - 'private' => Item::UNLISTED, - 'verb' => Activity::POST, - 'contact-id' => $contact['id'], - 'author-name' => $contact['name'], - 'author-link' => $contact['url'], - 'author-avatar' => $contact['avatar'], - 'plink' => $contact['alias'] . '/post/' . $parts->rkey, - 'source' => json_encode($post), - ]; - - if (($last_poll != 0) && strtotime($item['received']) < $last_poll) { - unset($item['received']); - } - - $account = Contact::selectFirstAccountUser(['pid'], ['id' => $contact['id']]); - - $item['author-id'] = $account['pid']; - $item['uri-id'] = ItemURI::getIdByURI($uri); - $item['owner-id'] = $item['author-id']; - $item['owner-name'] = $item['author-name']; - $item['owner-link'] = $item['author-link']; - $item['owner-avatar'] = $item['author-avatar']; - - if (in_array($contact['rel'], [Contact::SHARING, Contact::FRIEND])) { - $item['post-reason'] = Item::PR_FOLLOWER; - } - - if (!empty($post->labels)) { - foreach ($post->labels as $label) { - // Only flag posts as sensitive based on labels that had been provided by the author. - // When "ver" is set to "1" it was flagged by some automated process. - if (empty($label->ver)) { - $item['sensitive'] = true; - $item['content-warning'] = $label->val ?? ''; - Logger::debug('Sensitive content', ['uri-id' => $item['uri-id'], 'label' => $label]); - } - } - } - - return $item; -} - -function bluesky_get_restrictions_for_user(stdClass $post, array $item, int $post_reason): ?int -{ - if (!empty($post->viewer->replyDisabled)) { - return Item::CANT_REPLY; - } - - if (empty($post->threadgate)) { - return null; - } - - if (!isset($post->threadgate->record->allow)) { - return null; - } - - if ($item['uid'] == 0) { - return Item::CANT_REPLY; - } - - $restrict = true; - $type = '$type'; - foreach ($post->threadgate->record->allow as $allow) { - switch ($allow->$type) { - case 'app.bsky.feed.threadgate#followingRule': - // Only followers can reply. - if (Contact::isFollower($item['author-id'], $item['uid'])) { - $restrict = false; - } - break; - case 'app.bsky.feed.threadgate#mentionRule': - // Only mentioned accounts can reply. - if ($post_reason == Item::PR_TO) { - $restrict = false; - } - break; - case 'app.bsky.feed.threadgate#listRule'; - // Only accounts in the provided list can reply. We don't support this at the moment. - break; - } - } - - return $restrict ? Item::CANT_REPLY : null; -} - -function bluesky_get_content(array $item, stdClass $record, string $uri, int $uid, int $fetch_uid, int $level, int $last_poll): array -{ - if (empty($item)) { - return []; - } - - if (!empty($record->reply)) { - $item['parent-uri'] = bluesky_get_uri($record->reply->root); - if ($item['parent-uri'] != $uri) { - $item['parent-uri'] = bluesky_fetch_missing_post($item['parent-uri'], $uid, $fetch_uid, Item::PR_FETCHED, $item['contact-id'], $level, $last_poll); - if (empty($item['parent-uri'])) { - return []; - } - } - - $item['thr-parent'] = bluesky_get_uri($record->reply->parent); - if (!in_array($item['thr-parent'], [$uri, $item['parent-uri']])) { - $item['thr-parent'] = bluesky_fetch_missing_post($item['thr-parent'], $uid, $fetch_uid, Item::PR_FETCHED, $item['contact-id'], $level, $last_poll, $item['parent-uri']); - if (empty($item['thr-parent'])) { - return []; - } - } - } - - $item['body'] = bluesky_get_text($record, $item['uri-id']); - $item['created'] = DateTimeFormat::utc($record->createdAt, DateTimeFormat::MYSQL); - $item['transmitted-languages'] = $record->langs ?? []; - - return $item; -} - -function bluesky_get_text(stdClass $record, int $uri_id): string -{ - $text = $record->text ?? ''; - - if (empty($record->facets)) { - return $text; - } - - $facets = []; - foreach ($record->facets as $facet) { - $facets[$facet->index->byteStart] = $facet; - } - krsort($facets); - - foreach ($facets as $facet) { - $prefix = substr($text, 0, $facet->index->byteStart); - $linktext = substr($text, $facet->index->byteStart, $facet->index->byteEnd - $facet->index->byteStart); - $suffix = substr($text, $facet->index->byteEnd); - - $url = ''; - $type = '$type'; - foreach ($facet->features as $feature) { - - switch ($feature->$type) { - case 'app.bsky.richtext.facet#link': - $url = $feature->uri; - break; - - case 'app.bsky.richtext.facet#mention': - $contact = Contact::getByURL($feature->did, null, ['id']); - if (!empty($contact['id'])) { - $url = DI::baseUrl() . '/contact/' . $contact['id']; - if (substr($linktext, 0, 1) == '@') { - $prefix .= '@'; - $linktext = substr($linktext, 1); - } - } - break; - - case 'app.bsky.richtext.facet#tag'; - Tag::store($uri_id, Tag::HASHTAG, $feature->tag); - $url = DI::baseUrl() . '/search?tag=' . urlencode($feature->tag); - $linktext = '#' . $feature->tag; - break; - - default: - Logger::notice('Unhandled feature type', ['type' => $feature->$type, 'feature' => $feature, 'record' => $record]); - break; - } - } - if (!empty($url)) { - $text = $prefix . '[url=' . $url . ']' . $linktext . '[/url]' . $suffix; - } - } - return $text; -} - -function bluesky_add_media(stdClass $embed, array $item, int $fetch_uid, int $level, int $last_poll): array -{ - $type = '$type'; - switch ($embed->$type) { - case 'app.bsky.embed.images#view': - foreach ($embed->images as $image) { - $media = [ - 'uri-id' => $item['uri-id'], - 'type' => Post\Media::IMAGE, - 'url' => $image->fullsize, - 'preview' => $image->thumb, - 'description' => $image->alt, - ]; - Post\Media::insert($media); - } - break; - - case 'app.bsky.embed.video#view': - $media = [ - 'uri-id' => $item['uri-id'], - 'type' => Post\Media::HLS, - 'url' => $embed->playlist, - 'preview' => $embed->thumbnail, - 'description' => $embed->alt ?? '', - 'height' => $embed->aspectRatio->height ?? null, - 'width' => $embed->aspectRatio->width ?? null, - ]; - Post\Media::insert($media); - break; - - case 'app.bsky.embed.external#view': - $media = [ - 'uri-id' => $item['uri-id'], - 'type' => Post\Media::HTML, - 'url' => $embed->external->uri, - 'name' => $embed->external->title, - 'description' => $embed->external->description, - ]; - Post\Media::insert($media); - break; - - case 'app.bsky.embed.record#view': - $original_uri = $uri = bluesky_get_uri($embed->record); - $type = '$type'; - if (!empty($embed->record->record->$type)) { - $embed_type = $embed->record->record->$type; - if ($embed_type == 'app.bsky.graph.starterpack') { - bluesky_add_starterpack($item, $embed->record); - break; - } - } - $fetched_uri = bluesky_fetch_post($uri, $item['uid']); - if (!$fetched_uri) { - $uri = bluesky_fetch_missing_post($uri, 0, $fetch_uid, Item::PR_FETCHED, $item['contact-id'], $level, $last_poll); - } else { - $uri = $fetched_uri; - } - if ($uri) { - $shared = Post::selectFirst(['uri-id'], ['uri' => $uri, 'uid' => [$item['uid'], 0]]); - $uri_id = $shared['uri-id'] ?? 0; - } - if (!empty($uri_id)) { - $item['quote-uri-id'] = $uri_id; - } else { - Logger::debug('Quoted post could not be fetched', ['original-uri' => $original_uri, 'uri' => $uri]); - } - break; - - case 'app.bsky.embed.recordWithMedia#view': - bluesky_add_media($embed->media, $item, $fetch_uid, $level, $last_poll); - $original_uri = $uri = bluesky_get_uri($embed->record->record); - $uri = bluesky_fetch_missing_post($uri, $item['uid'], $fetch_uid, Item::PR_FETCHED, $item['contact-id'], $level, $last_poll); - if ($uri) { - $shared = Post::selectFirst(['uri-id'], ['uri' => $uri, 'uid' => [$item['uid'], 0]]); - $uri_id = $shared['uri-id'] ?? 0; - } - if (!empty($uri_id)) { - $item['quote-uri-id'] = $uri_id; - } else { - Logger::debug('Quoted post could not be fetched', ['original-uri' => $original_uri, 'uri' => $uri]); - } - break; - - default: - Logger::notice('Unhandled embed type', ['uri-id' => $item['uri-id'], 'type' => $embed->$type, 'embed' => $embed]); - break; - } - return $item; -} - -function bluesky_add_starterpack(array $item, stdClass $record) -{ - Logger::debug('Received starterpack', ['uri-id' => $item['uri-id'], 'guid' => $item['guid'], 'uri' => $record->uri]); - if (!preg_match('#^at://(.+)/app.bsky.graph.starterpack/(.+)#', $record->uri, $matches)) { - return; - } - - $media = [ - 'uri-id' => $item['uri-id'], - 'type' => Post\Media::HTML, - 'url' => 'https://bsky.app/starter-pack/' . $matches[1] . '/' . $matches[2], - 'name' => $record->record->name, - 'description' => $record->record->description, - ]; - - Post\Media::insert($media); - - $fields = [ - 'name' => $record->record->name, - 'description' => $record->record->description, - ]; - Post\Media::update($fields, ['uri-id' => $media['uri-id'], 'url' => $media['url']]); -} - -function bluesky_get_uri(stdClass $post): string -{ - if (empty($post->cid)) { - Logger::info('Invalid URI', ['post' => $post]); - return ''; - } - return $post->uri . ':' . $post->cid; -} - -function bluesky_get_uri_class(string $uri): ?stdClass -{ - if (empty($uri)) { - return null; - } - - $elements = explode(':', $uri); - if (empty($elements) || ($elements[0] != 'at')) { - $post = Post::selectFirstPost(['extid'], ['uri' => $uri]); - return bluesky_get_uri_class($post['extid'] ?? ''); - } - - $class = new stdClass; - - $class->cid = array_pop($elements); - $class->uri = implode(':', $elements); - - if ((substr_count($class->uri, '/') == 2) && (substr_count($class->cid, '/') == 2)) { - $class->uri .= ':' . $class->cid; - $class->cid = ''; - } - - return $class; -} - -function bluesky_get_uri_parts(string $uri): ?stdClass -{ - $class = bluesky_get_uri_class($uri); - if (empty($class)) { - return null; - } - - $parts = explode('/', substr($class->uri, 5)); - - $class = new stdClass; - - $class->repo = $parts[0]; - $class->collection = $parts[1]; - $class->rkey = $parts[2]; - - return $class; -} - -function bluesky_fetch_missing_post(string $uri, int $uid, int $fetch_uid, int $post_reason, int $causer, int $level, int $last_poll, string $fallback = '', bool $always_fetch = false, int $Protocol = Conversation::PARCEL_CONNECTOR): string -{ - $fetched_uri = bluesky_fetch_post($uri, $uid); - if (!$always_fetch && !empty($fetched_uri)) { - return $fetched_uri; - } - - if (++$level > 100) { - Logger::info('Recursion level too deep', ['level' => $level, 'uid' => $uid, 'uri' => $uri, 'fallback' => $fallback]); - // When the level is too deep we will fallback to the parent uri. - // Allthough the threading won't be correct, we at least had stored all posts and won't try again - return $fallback; - } - - $class = bluesky_get_uri_class($uri); - if (empty($class)) { - return $fallback; - } - - $fetch_uri = $class->uri; - - Logger::debug('Fetch missing post', ['level' => $level, 'uid' => $uid, 'uri' => $uri]); - $data = bluesky_xrpc_get($fetch_uid, 'app.bsky.feed.getPostThread', ['uri' => $fetch_uri]); - if (empty($data) || empty($data->thread)) { - Logger::info('Thread was not fetched', ['level' => $level, 'uid' => $uid, 'uri' => $uri, 'fallback' => $fallback]); - return $fallback; - } - - Logger::debug('Reply count', ['level' => $level, 'uid' => $uid, 'uri' => $uri]); - - if ($causer != 0) { - $causer = Contact::getPublicContactId($causer, $uid); - } - - if (!empty($data->thread->parent)) { - $parents = bluesky_fetch_parents($data->thread->parent, $uid); - - foreach ($parents as $parent) { - $uri_id = bluesky_process_post($parent, $uid, $fetch_uid, Item::PR_FETCHED, $causer, $level, $last_poll, $Protocol); - Logger::debug('Parent created', ['uri-id' => $uri_id]); - } - } - - return bluesky_process_thread($data->thread, $uid, $fetch_uid, $post_reason, $causer, $level, $last_poll, $Protocol); -} - -function bluesky_fetch_parents(stdClass $parent, int $uid, array $parents = []): array -{ - if (!empty($parent->parent)) { - $parents = bluesky_fetch_parents($parent->parent, $uid, $parents); - } - - if (!empty($parent->post) && empty(bluesky_fetch_post(bluesky_get_uri($parent->post), $uid))) { - $parents[] = $parent->post; - } - - return $parents; -} - -function bluesky_fetch_post(string $uri, int $uid): string -{ - if (Post::exists(['uri' => $uri, 'uid' => [$uid, 0]])) { - Logger::debug('Post exists', ['uri' => $uri]); - return $uri; - } - - $reply = Post::selectFirst(['uri'], ['extid' => $uri, 'uid' => [$uid, 0]]); - if (!empty($reply['uri'])) { - Logger::debug('Post with extid exists', ['uri' => $uri]); - return $reply['uri']; - } - return ''; -} - -function bluesky_fetch_uri_id(string $uri, int $uid): string -{ - $reply = Post::selectFirst(['uri-id'], ['uri' => $uri, 'uid' => [$uid, 0]]); - if (!empty($reply['uri-id'])) { - Logger::debug('Post with extid exists', ['uri' => $uri]); - return $reply['uri-id']; - } - $reply = Post::selectFirst(['uri-id'], ['extid' => $uri, 'uid' => [$uid, 0]]); - if (!empty($reply['uri-id'])) { - Logger::debug('Post with extid exists', ['uri' => $uri]); - return $reply['uri-id']; - } - return 0; -} - -function bluesky_process_thread(stdClass $thread, int $uid, int $fetch_uid, int $post_reason, int $causer, int $level, int $last_poll, int $protocol): string -{ - if (empty($thread->post)) { - Logger::info('Invalid post', ['post' => $thread]); - return ''; - } - $uri = bluesky_get_uri($thread->post); - - $fetched_uri = bluesky_fetch_post($uri, $uid); - if (empty($fetched_uri)) { - $uri_id = bluesky_process_post($thread->post, $uid, $fetch_uid, $post_reason, $causer, $level, $last_poll, $protocol); - if ($uri_id) { - Logger::debug('Post has been processed and stored', ['uri-id' => $uri_id, 'uri' => $uri]); - return $uri; - } else { - Logger::info('Post has not not been stored', ['uri' => $uri]); - return ''; - } - } else { - Logger::debug('Post exists', ['uri' => $uri]); - $uri = $fetched_uri; - } - - foreach ($thread->replies ?? [] as $reply) { - $reply_uri = bluesky_process_thread($reply, $uid, $fetch_uid, Item::PR_FETCHED, $causer, $level, $last_poll, $protocol); - Logger::debug('Reply has been processed', ['uri' => $uri, 'reply' => $reply_uri]); - } - - return $uri; -} - -function bluesky_get_contact(stdClass $author, int $uid, int $fetch_uid): array -{ - $condition = ['network' => Protocol::BLUESKY, 'uid' => 0, 'nurl' => $author->did]; - $contact = Contact::selectFirst(['id', 'updated'], $condition); - - $update = empty($contact) || $contact['updated'] < DateTimeFormat::utc('now -24 hours'); - - $public_fields = $fields = bluesky_get_contact_fields($author, $uid, $fetch_uid, $update); - - $public_fields['uid'] = 0; - $public_fields['rel'] = Contact::NOTHING; - - if (empty($contact)) { - $cid = Contact::insert($public_fields); - } else { - $cid = $contact['id']; - Logger::debug('Update contact', ['fields' => $public_fields, 'id' => $cid]); - Contact::update($public_fields, ['id' => $cid], true); - } - - if ($uid != 0) { - $condition = ['network' => Protocol::BLUESKY, 'uid' => $uid, 'nurl' => $author->did]; - - $contact = Contact::selectFirst(['id', 'rel', 'uid'], $condition); - if (!isset($fields['rel']) && isset($contact['rel'])) { - $fields['rel'] = $contact['rel']; - } elseif (!isset($fields['rel'])) { - $fields['rel'] = Contact::NOTHING; - } - } - - if (($uid != 0) && ($fields['rel'] != Contact::NOTHING)) { - if (empty($contact)) { - $cid = Contact::insert($fields); - } else { - $cid = $contact['id']; - Logger::debug('Update contact', ['fields' => $fields, 'id' => $cid]); - Contact::update($fields, ['id' => $cid], true); - } - Logger::debug('Get user contact', ['id' => $cid, 'uid' => $uid, 'update' => $update]); - } else { - Logger::debug('Get public contact', ['id' => $cid, 'uid' => $uid, 'update' => $update]); - } - if (!empty($author->avatar)) { - Contact::updateAvatar($cid, $author->avatar); - } - - return Contact::getById($cid); -} - -function bluesky_get_contact_fields(stdClass $author, int $uid, int $fetch_uid, bool $update): array -{ - $nick = $author->handle ?? $author->did; - $name = $author->displayName ?? $nick; - $fields = [ - 'uid' => $uid, - 'network' => Protocol::BLUESKY, - 'priority' => 1, - 'writable' => true, - 'blocked' => false, - 'readonly' => false, - 'pending' => false, - 'url' => $author->did, - 'nurl' => $author->did, - 'alias' => BLUESKY_WEB . '/profile/' . $nick, - 'name' => $name ?: $nick, - 'nick' => $nick, - 'addr' => $nick, - ]; - - if (!$update) { - Logger::debug('Got contact fields', ['uid' => $uid, 'url' => $fields['url'], 'fields' => $fields]); - return $fields; - } - - $data = bluesky_get(BLUESKY_DIRECTORY . '/' . $author->did); - if (!empty($data)) { - $fields['baseurl'] = bluesky_get_pds('', $data); - if (!empty($fields['baseurl'])) { - GServer::check($fields['baseurl'], Protocol::BLUESKY); - $fields['gsid'] = GServer::getID($fields['baseurl'], true); - } - $fields['pubkey'] = bluesky_get_public_key('', $data); - } - - $data = bluesky_xrpc_get($fetch_uid, 'app.bsky.actor.getProfile', ['actor' => $author->did]); - if (empty($data)) { - Logger::debug('Error fetching contact fields', ['uid' => $uid, 'url' => $fields['url']]); - return $fields; - } - - $fields['updated'] = DateTimeFormat::utcNow(DateTimeFormat::MYSQL); - - if (!empty($data->description)) { - $fields['about'] = HTML::toBBCode($data->description); - } - - if (!empty($data->banner)) { - $fields['header'] = $data->banner; - } - - if (!empty($data->viewer)) { - if (!empty($data->viewer->following) && !empty($data->viewer->followedBy)) { - $fields['rel'] = Contact::FRIEND; - } elseif (!empty($data->viewer->following) && empty($data->viewer->followedBy)) { - $fields['rel'] = Contact::SHARING; - } elseif (empty($data->viewer->following) && !empty($data->viewer->followedBy)) { - $fields['rel'] = Contact::FOLLOWER; - } else { - $fields['rel'] = Contact::NOTHING; - } - } - - Logger::debug('Got updated contact fields', ['uid' => $uid, 'url' => $fields['url']]); - return $fields; -} - function bluesky_get_feeds(int $uid): array { $type = '$type'; @@ -1861,7 +1142,7 @@ function bluesky_get_preferences(int $uid): ?stdClass return $data; } - $data = bluesky_xrpc_get($uid, 'app.bsky.actor.getPreferences'); + $data = DI::atProtocol()->XRPCGet('app.bsky.actor.getPreferences', [], $uid); if (empty($data)) { return null; } @@ -1869,369 +1150,3 @@ function bluesky_get_preferences(int $uid): ?stdClass DI::cache()->set($cachekey, $data, Duration::HOUR); return $data; } - -function bluesky_get_did_by_profile(string $url, int $uid): string -{ - if (preg_match('#^' . BLUESKY_WEB . '/profile/(.+)#', $url, $matches)) { - $did = bluesky_get_did($matches[1], $uid); - if (!empty($did)) { - return $did; - } - } - try { - $curlResult = DI::httpClient()->get($url, HttpClientAccept::HTML, [HttpClientOptions::REQUEST => HttpClientRequest::CONTACTINFO]); - } catch (\Throwable $th) { - return ''; - } - if (!$curlResult->isSuccess()) { - return ''; - } - $profile = $curlResult->getBodyString(); - if (empty($profile)) { - return ''; - } - - $doc = new DOMDocument(); - try { - @$doc->loadHTML($profile); - } catch (\Throwable $th) { - return ''; - } - $xpath = new DOMXPath($doc); - $list = $xpath->query('//p[@id]'); - foreach ($list as $node) { - foreach ($node->attributes as $attribute) { - if ($attribute->name == 'id') { - $ids[$attribute->value] = $node->textContent; - } - } - } - - if (empty($ids['bsky_handle']) || empty($ids['bsky_did'])) { - return ''; - } - - if (!bluesky_valid_did($ids['bsky_did'], $ids['bsky_handle'])) { - Logger::notice('Invalid DID', ['handle' => $ids['bsky_handle'], 'did' => $ids['bsky_did']]); - return ''; - } - - return $ids['bsky_did']; -} - -function bluesky_get_did_by_wellknown(string $handle): string -{ - $curlResult = DI::httpClient()->get('http://' . $handle . '/.well-known/atproto-did'); - if ($curlResult->isSuccess() && substr($curlResult->getBodyString(), 0, 4) == 'did:') { - $did = $curlResult->getBodyString(); - if (!bluesky_valid_did($did, $handle)) { - Logger::notice('Invalid DID', ['handle' => $handle, 'did' => $did]); - return ''; - } - return $did; - } - return ''; -} - -function bluesky_get_did_by_dns(string $handle): string -{ - $records = @dns_get_record('_atproto.' . $handle . '.', DNS_TXT); - if (empty($records)) { - return ''; - } - foreach ($records as $record) { - if (!empty($record['txt']) && substr($record['txt'], 0, 4) == 'did=') { - $did = substr($record['txt'], 4); - if (!bluesky_valid_did($did, $handle)) { - Logger::notice('Invalid DID', ['handle' => $handle, 'did' => $did]); - return ''; - } - return $did; - } - } - return ''; -} - -function bluesky_get_did(string $handle, int $uid): string -{ - if ($handle == '') { - return ''; - } - - if (strpos($handle, '.') === false) { - $handle .= '.' . BLUESKY_HOSTNAME; - } - - // At first we use the user PDS. That should cover most cases. - $pds = DI::pConfig()->get($uid, 'bluesky', 'pds'); - if (!empty($pds)) { - $data = bluesky_get($pds . '/xrpc/com.atproto.identity.resolveHandle?handle=' . urlencode($handle)); - if (!empty($data) && !empty($data->did)) { - Logger::debug('Got DID by user PDS call', ['handle' => $handle, 'did' => $data->did]); - return $data->did; - } - } - - // Then we query the DNS, which is used for third party handles (DNS should be faster than wellknown) - $did = bluesky_get_did_by_dns($handle); - if ($did != '') { - Logger::debug('Got DID by DNS', ['handle' => $handle, 'did' => $did]); - return $did; - } - - // Then we query wellknown, which should mostly cover the rest. - $did = bluesky_get_did_by_wellknown($handle); - if ($did != '') { - Logger::debug('Got DID by wellknown', ['handle' => $handle, 'did' => $did]); - return $did; - } - - // And finally we use the AppView API. - $data = bluesky_get(BLUESKY_APPVIEW_API . '/xrpc/com.atproto.identity.resolveHandle?handle=' . urlencode($handle)); - if (!empty($data) && !empty($data->did)) { - Logger::debug('Got DID by system PDS call', ['handle' => $handle, 'did' => $data->did]); - return $data->did; - } - - Logger::notice('No DID detected', ['handle' => $handle]); - return ''; -} - -function bluesky_get_user_did(int $uid, bool $refresh = false): ?string -{ - if (!$refresh) { - $did = DI::pConfig()->get($uid, 'bluesky', 'did'); - if (!empty($did)) { - return $did; - } - } - - $handle = DI::pConfig()->get($uid, 'bluesky', 'handle'); - if (empty($handle)) { - return null; - } - - $did = bluesky_get_did($handle, $uid); - if (empty($did)) { - return null; - } - - Logger::debug('Got DID for user', ['uid' => $uid, 'handle' => $handle, 'did' => $did]); - DI::pConfig()->set($uid, 'bluesky', 'did', $did); - return $did; -} - -function bluesky_get_user_pds(int $uid): ?string -{ - if ($uid == 0) { - return BLUESKY_APPVIEW_API; - } - - $pds = DI::pConfig()->get($uid, 'bluesky', 'pds'); - if (!empty($pds)) { - return $pds; - } - - $did = bluesky_get_user_did($uid); - if (empty($did)) { - return null; - } - - $pds = bluesky_get_pds($did); - if (empty($pds)) { - return null; - } - - DI::pConfig()->set($uid, 'bluesky', 'pds', $pds); - return $pds; -} - -function bluesky_get_pds(string $did, stdClass $data = null): ?string -{ - if (empty($data)) { - $data = bluesky_get(BLUESKY_DIRECTORY . '/' . $did); - } - if (empty($data) || empty($data->service)) { - return null; - } - - foreach ($data->service as $service) { - if (($service->id == '#atproto_pds') && ($service->type == 'AtprotoPersonalDataServer') && !empty($service->serviceEndpoint)) { - return $service->serviceEndpoint; - } - } - - return null; -} - -function bluesky_get_public_key(string $did, stdClass $data = null): ?string -{ - if (empty($data)) { - $data = bluesky_get(BLUESKY_DIRECTORY . '/' . $did); - } - if (empty($data) || empty($data->verificationMethod)) { - return null; - } - foreach ($data->verificationMethod as $method) { - if (!empty($method->publicKeyMultibase)) { - return $method->publicKeyMultibase; - } - } - return null; -} - -function bluesky_valid_did(string $did, string $handle): bool -{ - $data = bluesky_get(BLUESKY_DIRECTORY . '/' . $did); - if (empty($data) || empty($data->alsoKnownAs)) { - return false; - } - - return in_array('at://' . $handle, $data->alsoKnownAs); -} - -function bluesky_get_token(int $uid): string -{ - $token = DI::pConfig()->get($uid, 'bluesky', 'access_token'); - $created = DI::pConfig()->get($uid, 'bluesky', 'token_created'); - if (empty($token)) { - return ''; - } - - if ($created + 300 < time()) { - return bluesky_refresh_token($uid); - } - return $token; -} - -function bluesky_refresh_token(int $uid): string -{ - $token = DI::pConfig()->get($uid, 'bluesky', 'refresh_token'); - - $data = bluesky_post($uid, '/xrpc/com.atproto.server.refreshSession', '', ['Authorization' => ['Bearer ' . $token]]); - if (empty($data) || empty($data->accessJwt)) { - Logger::debug('Refresh failed', ['return' => $data]); - $password = DI::pConfig()->get($uid, 'bluesky', 'password'); - if (!empty($password)) { - return bluesky_create_token($uid, $password); - } - DI::pConfig()->set($uid, 'bluesky', 'status', BLUEKSY_STATUS_TOKEN_FAIL); - return ''; - } - - Logger::debug('Refreshed token', ['return' => $data]); - DI::pConfig()->set($uid, 'bluesky', 'access_token', $data->accessJwt); - DI::pConfig()->set($uid, 'bluesky', 'refresh_token', $data->refreshJwt); - DI::pConfig()->set($uid, 'bluesky', 'token_created', time()); - return $data->accessJwt; -} - -function bluesky_create_token(int $uid, string $password): string -{ - $did = bluesky_get_user_did($uid); - if (empty($did)) { - return ''; - } - - $data = bluesky_post($uid, '/xrpc/com.atproto.server.createSession', json_encode(['identifier' => $did, 'password' => $password]), ['Content-type' => 'application/json']); - if (empty($data) || empty($data->accessJwt)) { - DI::pConfig()->set($uid, 'bluesky', 'status', BLUEKSY_STATUS_TOKEN_FAIL); - return ''; - } - - Logger::debug('Created token', ['return' => $data]); - DI::pConfig()->set($uid, 'bluesky', 'access_token', $data->accessJwt); - DI::pConfig()->set($uid, 'bluesky', 'refresh_token', $data->refreshJwt); - DI::pConfig()->set($uid, 'bluesky', 'token_created', time()); - DI::pConfig()->set($uid, 'bluesky', 'status', BLUEKSY_STATUS_TOKEN_OK); - return $data->accessJwt; -} - -function bluesky_xrpc_post(int $uid, string $url, $parameters): ?stdClass -{ - $data = bluesky_post($uid, '/xrpc/' . $url, json_encode($parameters), ['Content-type' => 'application/json', 'Authorization' => ['Bearer ' . bluesky_get_token($uid)]]); - if (!empty($data)) { - Item::incrementOutbound(Protocol::BLUESKY); - } - return $data; -} - -function bluesky_post(int $uid, string $url, string $params, array $headers): ?stdClass -{ - $pds = bluesky_get_user_pds($uid); - if (empty($pds)) { - return null; - } - - try { - $curlResult = DI::httpClient()->post($pds . $url, $params, $headers); - } catch (\Exception $e) { - Logger::notice('Exception on post', ['exception' => $e]); - DI::pConfig()->set($uid, 'bluesky', 'status', BLUEKSY_STATUS_API_FAIL); - return null; - } - - $data = json_decode($curlResult->getBodyString()); - if (!$curlResult->isSuccess()) { - Logger::notice('API Error', ['url' => $url, 'code' => $curlResult->getReturnCode(), 'error' => $data ?: $curlResult->getBodyString()]); - if (!$data) { - DI::pConfig()->set($uid, 'bluesky', 'status', BLUEKSY_STATUS_API_FAIL); - return null; - } - $data->code = $curlResult->getReturnCode(); - } - - if (!empty($data->code) && ($data->code >= 200) && ($data->code < 400)) { - DI::pConfig()->set($uid, 'bluesky', 'status', BLUEKSY_STATUS_SUCCESS); - } else { - DI::pConfig()->set($uid, 'bluesky', 'status', BLUEKSY_STATUS_API_FAIL); - } - return $data; -} - -function bluesky_xrpc_get(int $uid, string $url, array $parameters = []): ?stdClass -{ - if (!empty($parameters)) { - $url .= '?' . http_build_query($parameters); - } - - $pds = bluesky_get_user_pds($uid); - if (empty($pds)) { - return null; - } - - $headers = ['Authorization' => ['Bearer ' . bluesky_get_token($uid)]]; - - $languages = User::getWantedLanguages($uid); - if (!empty($languages)) { - $headers['Accept-Language'] = implode(',', $languages); - } - - $data = bluesky_get($pds . '/xrpc/' . $url, HttpClientAccept::JSON, [HttpClientOptions::HEADERS => $headers]); - if ($uid != 0) { - DI::pConfig()->set($uid, 'bluesky', 'status', is_null($data) ? BLUEKSY_STATUS_API_FAIL : BLUEKSY_STATUS_SUCCESS); - } - return $data; -} - -function bluesky_get(string $url, string $accept_content = HttpClientAccept::DEFAULT, array $opts = []): ?stdClass -{ - try { - $curlResult = DI::httpClient()->get($url, $accept_content, $opts); - } catch (\Exception $e) { - Logger::notice('Exception on get', ['url' => $url, 'exception' => $e]); - return null; - } - - $data = json_decode($curlResult->getBodyString()); - if (!$curlResult->isSuccess()) { - Logger::notice('API Error', ['url' => $url, 'code' => $curlResult->getReturnCode(), 'error' => $data ?: $curlResult->getBodyString()]); - if (!$data) { - return null; - } - $data->code = $curlResult->getReturnCode(); - } - - Item::incrementInbound(Protocol::BLUESKY); - return $data; -} From 01ec6ecb8ea98555d744949305a60e12e2fdb76c Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 17 Dec 2024 04:50:54 +0000 Subject: [PATCH 298/388] Bluesky: Handle problems when uploading pictures --- bluesky/bluesky.php | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index c9c7dc67e..d6b7624ba 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -313,7 +313,8 @@ function bluesky_get_status(string $handle = null, string $did = null, string $p return DI::l10n()->t('You are not authenticated. Please enter your handle and the app password.'); } - $status = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'status') ?? ATProtocol::STATUS_UNKNOWN; + $status = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'status') ?? ATProtocol::STATUS_UNKNOWN; + $message = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'status-message') ?? ''; // Fallback mechanism for connection that had been established before the introduction of the status if ($status == ATProtocol::STATUS_UNKNOWN) { @@ -330,11 +331,11 @@ function bluesky_get_status(string $handle = null, string $did = null, string $p switch ($status) { case ATProtocol::STATUS_TOKEN_OK: - return DI::l10n()->t("You are authenticated to Bluesky."); + return DI::l10n()->t("You are authenticated to Bluesky. For security reasons the password isn't stored."); case ATProtocol::STATUS_SUCCESS: return DI::l10n()->t('The communication with the personal data server service (PDS) is established.'); case ATProtocol::STATUS_API_FAIL; - return DI::l10n()->t('Communication issues with the personal data server service (PDS).'); + return DI::l10n()->t('Communication issues with the personal data server service (PDS): %s', $message); case ATProtocol::STATUS_DID_FAIL: return DI::l10n()->t('The DID for the provided handle could not be detected. Please check if you entered the correct handle.'); case ATProtocol::STATUS_PDS_FAIL: @@ -361,7 +362,6 @@ function bluesky_settings_post(array &$b) DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'post', intval($_POST['bluesky'])); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'post_by_default', intval($_POST['bluesky_bydefault'])); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'handle', $handle); - DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'password', $_POST['bluesky_password']); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'import', intval($_POST['bluesky_import'])); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'import_feeds', intval($_POST['bluesky_import_feeds'])); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'complete_threads', intval($_POST['bluesky_complete_threads'])); @@ -850,7 +850,14 @@ function bluesky_add_embed(int $uid, array $msg, array $record): array if (empty($blob)) { return []; } - $images[] = ['alt' => $image['description'] ?? '', 'image' => $blob]; + $images[] = [ + 'alt' => $image['description'] ?? '', + 'image' => $blob, + 'aspectRatio' => [ + 'width' => $photo['width'], + 'height' => $photo['height'], + ] + ]; } if (!empty($images)) { $record['embed'] = ['$type' => 'app.bsky.embed.images', 'images' => $images]; @@ -888,10 +895,15 @@ function bluesky_upload_blob(int $uid, array $photo): ?stdClass $picture = Photo::resizeToFileSize($picture, BLUESKY_IMAGE_SIZE[$retrial]); $new_height = $picture->getHeight(); $new_width = $picture->getWidth(); - $content = $picture->asString(); + $content = (string)$picture->asString(); $new_size = strlen($content); - Logger::info('Uploading', ['uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size]); + if (($size != 0) && ($new_size == 0) && ($retrial == 0)) { + Logger::warning('Size is empty after resize, uploading original file', ['uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size]); + $content = Photo::getImageForPhoto($photo); + } else { + Logger::info('Uploading', ['uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size]); + } $data = DI::atProtocol()->post($uid, '/xrpc/com.atproto.repo.uploadBlob', $content, ['Content-type' => $photo['type'], 'Authorization' => ['Bearer ' . DI::atProtocol()->getUserToken($uid)]]); if (empty($data) || empty($data->blob)) { @@ -955,7 +967,7 @@ function bluesky_complete_post(stdClass $post, int $uid, int $post_reason, int $ } if ($complete) { - $uri = DI::atpProcessor()->fetchMissingPost(DI::atpProcessor()->getUri($post), $uid, $post_reason, $causer, 0, '', true); + $uri = DI::atpProcessor()->fetchMissingPost(DI::atpProcessor()->getUri($post), $uid, $post_reason, $causer, 0, '', true, $protocol); $uri_id = DI::atpProcessor()->fetchUriId($uri, $uid); } else { $uri_id = DI::atpProcessor()->processPost($post, $uid, $post_reason, $causer, 0, $protocol); From 16e06f9b2b85dba28a109ec85aaccc75509f2209 Mon Sep 17 00:00:00 2001 From: loma-one Date: Sun, 17 Nov 2024 08:20:49 +0100 Subject: [PATCH 299/388] Small bug fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Close the Uni-Code Smilies link with a ’;’ --- unicode_smilies/unicode_smilies.php | 3099 +++++++++++++-------------- 1 file changed, 1548 insertions(+), 1551 deletions(-) diff --git a/unicode_smilies/unicode_smilies.php b/unicode_smilies/unicode_smilies.php index 22ee3439c..8d55c4be8 100644 --- a/unicode_smilies/unicode_smilies.php +++ b/unicode_smilies/unicode_smilies.php @@ -2,7 +2,7 @@ /* * Name: Unicode Smilies * Description: Smilies based on the unicode emojis - On Linux use https://github.com/eosrei/emojione-color-font to see them in color and http://www.unicode.org/emoji/charts/full-emoji-list.html - * Version: 1.1.2 + * Version: 1.1.3 * Author: Michael Vogel * Author: Matthias Ebers */ @@ -25,7 +25,7 @@ function unicode_smilies_smilies(array &$b) Smilies::add($b, ':-D', '😁'); Smilies::add($b, ':D', '😁'); Smilies::add($b, ';-)', '😉'); - // Smilies::add($b, ';)', '😉'); // Deactivated since this leads to disturbed html entities +// Smilies::add($b, ';)', '😉'); // Deactivated since this leads to disturbed html entities Smilies::add($b, ':-P', '😛'); Smilies::add($b, ':-p', '😛'); Smilies::add($b, ':P', '😛'); @@ -54,353 +54,350 @@ function unicode_smilies_smilies(array &$b) // Smilies::add($b, 'O_o', '&#x;'); // face-smiling - Smilies::add($b, ':grinning face:', '😀'); - Smilies::add($b, ':grinning face with big eyes:', '😃'); - Smilies::add($b, ':grinning face with smiling eyes:', '😄'); - Smilies::add($b, ':beaming face with smiling eyes:', '😁'); - Smilies::add($b, ':grinning squinting face:', '😆'); - Smilies::add($b, ':laughing:', '😆'); - Smilies::add($b, ':grinning face with sweat:', '😅'); - Smilies::add($b, ':rolling on the floor laughing:', '🤣'); + Smilies::add($b, ':grinning face:', '😀'); + Smilies::add($b, ':grinning face with big eyes:', '😃'); + Smilies::add($b, ':grinning face with smiling eyes:', '😄'); + Smilies::add($b, ':beaming face with smiling eyes:', '😁'); + Smilies::add($b, ':grinning squinting face:', '😆'); + Smilies::add($b, ':laughing:', '😆'); + Smilies::add($b, ':grinning face with sweat:', '😅'); + Smilies::add($b, ':rolling on the floor laughing:', '🤣'); Smilies::add($b, ':rofl:', '🤣'); - Smilies::add($b, ':face with tears of joy:', '😂'); + Smilies::add($b, ':face with tears of joy:', '😂'); Smilies::add($b, ':tearsofjoy:', '😂'); - Smilies::add($b, ':slightly smiling face:', '🙂'); - Smilies::add($b, ':upside-down face:', '🙃'); - Smilies::add($b, ':winking face:', '😉'); - Smilies::add($b, ':smiling face with smiling eyes:', '😊'); - Smilies::add($b, ':smiling face with halo:', '😇'); + Smilies::add($b, ':slightly smiling face:', '🙂'); + Smilies::add($b, ':upside-down face:', '🙃'); + Smilies::add($b, ':winking face:', '😉'); + Smilies::add($b, ':smiling face with smiling eyes:', '😊'); + Smilies::add($b, ':smiling face with halo:', '😇'); // face-affection - Smilies::add($b, ':smiling face with hearts:', '🥰'); - Smilies::add($b, ':smiling face with heart-eyes:', '😍'); - Smilies::add($b, ':star-struck:', '🤩'); - Smilies::add($b, ':face blowing a kiss:', '😘'); - Smilies::add($b, ':kissing face:', '😗'); - Smilies::add($b, ':smiling face:', '☺'); - Smilies::add($b, ':kissing face with closed eyes:', '😚'); - Smilies::add($b, ':kissing face with smiling eyes:', '😙'); + Smilies::add($b, ':smiling face with hearts:', '🥰'); + Smilies::add($b, ':smiling face with heart-eyes:', '😍'); + Smilies::add($b, ':star-struck:', '🤩'); + Smilies::add($b, ':face blowing a kiss:', '😘'); + Smilies::add($b, ':kissing face:', '😗'); + Smilies::add($b, ':smiling face:', '☺'); + Smilies::add($b, ':kissing face with closed eyes:', '😚'); + Smilies::add($b, ':kissing face with smiling eyes:', '😙'); // face-tongue - Smilies::add($b, ':face savoring food:', '😋'); - Smilies::add($b, ':face with tongue:', '😛'); - Smilies::add($b, ':winking face with tongue:', '😜'); - Smilies::add($b, ':zany face:', '🤪'); - Smilies::add($b, ':squinting face with tongue:', '😝'); - Smilies::add($b, ':money-mouth face:', '🤑'); + Smilies::add($b, ':face savoring food:', '😋'); + Smilies::add($b, ':face with tongue:', '😛'); + Smilies::add($b, ':winking face with tongue:', '😜'); + Smilies::add($b, ':zany face:', '🤪'); + Smilies::add($b, ':squinting face with tongue:', '😝'); + Smilies::add($b, ':money-mouth face:', '🤑'); // face-hand - Smilies::add($b, ':hugging face:', '🤗'); - Smilies::add($b, ':face with hand over mouth:', '🤭'); - Smilies::add($b, ':shushing face:', '🤫'); - Smilies::add($b, ':thinking face:', '🤔'); + Smilies::add($b, ':hugging face:', '🤗'); + Smilies::add($b, ':face with hand over mouth:', '🤭'); + Smilies::add($b, ':shushing face:', '🤫'); + Smilies::add($b, ':thinking face:', '🤔'); // face-neutral-skeptical - Smilies::add($b, ':zipper-mouth face:', '🤐'); - Smilies::add($b, ':face with raised eyebrow:', '🤨'); - Smilies::add($b, ':neutral face:', '😐'); - Smilies::add($b, ':expressionless face:', '😑'); - Smilies::add($b, ':face without mouth:', '😶'); - Smilies::add($b, ':smirking face:', '😏'); - Smilies::add($b, ':unamused face:', '😒'); - Smilies::add($b, ':face with rolling eyes:', '🙄'); - Smilies::add($b, ':grimacing face:', '😬'); - Smilies::add($b, ':lying face:', '🤥'); + Smilies::add($b, ':zipper-mouth face:', '🤐'); + Smilies::add($b, ':face with raised eyebrow:', '🤨'); + Smilies::add($b, ':neutral face:', '😐'); + Smilies::add($b, ':expressionless face:', '😑'); + Smilies::add($b, ':face without mouth:', '😶'); + Smilies::add($b, ':smirking face:', '😏'); + Smilies::add($b, ':unamused face:', '😒'); + Smilies::add($b, ':face with rolling eyes:', '🙄'); + Smilies::add($b, ':grimacing face:', '😬'); + Smilies::add($b, ':lying face:', '🤥'); // face-sleepy - Smilies::add($b, ':relieved face:', '😌'); - Smilies::add($b, ':pensive face:', '😔'); - Smilies::add($b, ':sleepy face:', '😪'); - Smilies::add($b, ':drooling face:', '🤤'); + Smilies::add($b, ':relieved face:', '😌'); + Smilies::add($b, ':pensive face:', '😔'); + Smilies::add($b, ':sleepy face:', '😪'); + Smilies::add($b, ':drooling face:', '🤤'); Smilies::add($b, ':drool:', '🤤'); - Smilies::add($b, ':sleeping face:', '😴'); + Smilies::add($b, ':sleeping face:', '😴'); // face-unwell - Smilies::add($b, ':face with medical mask:', '😷'); - Smilies::add($b, ':face with thermometer:', '🤒'); - Smilies::add($b, ':face with head-bandage:', '🤕'); - Smilies::add($b, ':nauseated face:', '🤢'); - Smilies::add($b, ':face vomiting:', '🤮'); + Smilies::add($b, ':face with medical mask:', '😷'); + Smilies::add($b, ':face with thermometer:', '🤒'); + Smilies::add($b, ':face with head-bandage:', '🤕'); + Smilies::add($b, ':nauseated face:', '🤢'); + Smilies::add($b, ':face vomiting:', '🤮'); Smilies::add($b, ':vomit:', '🤮'); - Smilies::add($b, ':sneezing face:', '🤧'); - Smilies::add($b, ':hot face:', '🥵'); - Smilies::add($b, ':cold face:', '🥶'); - Smilies::add($b, ':woozy face:', '🥴'); - Smilies::add($b, ':dizzy face:', '😵'); + Smilies::add($b, ':sneezing face:', '🤧'); + Smilies::add($b, ':hot face:', '🥵'); + Smilies::add($b, ':cold face:', '🥶'); + Smilies::add($b, ':woozy face:', '🥴'); + Smilies::add($b, ':dizzy face:', '😵'); Smilies::add($b, ':dead:', '😵'); - Smilies::add($b, ':exploding head:', '🤯'); + Smilies::add($b, ':exploding head:', '🤯'); // face-hat - Smilies::add($b, ':cowboy hat face:', '🤠'); - Smilies::add($b, ':partying face:', '🥳'); + Smilies::add($b, ':cowboy hat face:', '🤠'); + Smilies::add($b, ':partying face:', '🥳'); // face-glasses - Smilies::add($b, ':smiling face with sunglasses:', '😎'); - Smilies::add($b, ':nerd face:', '🤓'); - Smilies::add($b, ':face with monocle:', '🧐'); + Smilies::add($b, ':smiling face with sunglasses:', '😎'); + Smilies::add($b, ':nerd face:', '🤓'); + Smilies::add($b, ':face with monocle:', '🧐'); // face-concerned - Smilies::add($b, ':confused face:', '😕'); - Smilies::add($b, ':worried face:', '😟'); - Smilies::add($b, ':slightly frowning face:', '🙁'); - Smilies::add($b, ':frowning face:', '☹'); - Smilies::add($b, ':face with open mouth:', '😮'); - Smilies::add($b, ':hushed face:', '😯'); - Smilies::add($b, ':astonished face:', '😲'); - Smilies::add($b, ':flushed face:', '😳'); + Smilies::add($b, ':confused face:', '😕'); + Smilies::add($b, ':worried face:', '😟'); + Smilies::add($b, ':slightly frowning face:', '🙁'); + Smilies::add($b, ':frowning face:', '☹'); + Smilies::add($b, ':face with open mouth:', '😮'); + Smilies::add($b, ':hushed face:', '😯'); + Smilies::add($b, ':astonished face:', '😲'); + Smilies::add($b, ':flushed face:', '😳'); Smilies::add($b, ':dazed:', '😳'); - Smilies::add($b, ':pleading face:', '🥺'); - Smilies::add($b, ':frowning face with open mouth:', '😦'); - Smilies::add($b, ':anguished face:', '😧'); - Smilies::add($b, ':fearful face:', '😨'); - Smilies::add($b, ':anxious face with sweat:', '😰'); - Smilies::add($b, ':sad but relieved face:', '😥'); - Smilies::add($b, ':crying face:', '😢'); - Smilies::add($b, ':loudly crying face:', '😭'); - Smilies::add($b, ':face screaming in fear:', '😱'); - Smilies::add($b, ':confounded face:', '😖'); - Smilies::add($b, ':persevering face:', '😣'); - Smilies::add($b, ':disappointed face:', '😞'); + Smilies::add($b, ':pleading face:', '🥺'); + Smilies::add($b, ':frowning face with open mouth:', '😦'); + Smilies::add($b, ':anguished face:', '😧'); + Smilies::add($b, ':fearful face:', '😨'); + Smilies::add($b, ':anxious face with sweat:', '😰'); + Smilies::add($b, ':sad but relieved face:', '😥'); + Smilies::add($b, ':crying face:', '😢'); + Smilies::add($b, ':loudly crying face:', '😭'); + Smilies::add($b, ':face screaming in fear:', '😱'); + Smilies::add($b, ':confounded face:', '😖'); + Smilies::add($b, ':persevering face:', '😣'); + Smilies::add($b, ':disappointed face:', '😞'); // face-negative - Smilies::add($b, ':face with steam from nose:', '😤'); - Smilies::add($b, ':pouting face:', '😡'); - Smilies::add($b, ':angry face:', '😠'); - Smilies::add($b, ':face with symbols on mouth:', '🤬'); - Smilies::add($b, ':smiling face with horns:', '😈'); - Smilies::add($b, ':angry face with horns:', '👿'); - Smilies::add($b, ':skull:', '💀'); - Smilies::add($b, ':skull and crossbones:', '☠'); + Smilies::add($b, ':face with steam from nose:', '😤'); + Smilies::add($b, ':pouting face:', '😡'); + Smilies::add($b, ':angry face:', '😠'); + Smilies::add($b, ':face with symbols on mouth:', '🤬'); + Smilies::add($b, ':smiling face with horns:', '😈'); + Smilies::add($b, ':angry face with horns:', '👿'); + Smilies::add($b, ':skull:', '💀'); + Smilies::add($b, ':skull and crossbones:', '☠'); // face-costume - Smilies::add($b, ':pile of poo:', '💩'); - Smilies::add($b, ':clown face:', '🤡'); - Smilies::add($b, ':ogre:', '👹'); - Smilies::add($b, ':goblin:', '👺'); - Smilies::add($b, ':ghost:', '👻'); - Smilies::add($b, ':alien:', '👽'); - Smilies::add($b, ':alien monster:', '👾'); - Smilies::add($b, ':robot:', '🤖'); + Smilies::add($b, ':pile of poo:', '💩'); + Smilies::add($b, ':clown face:', '🤡'); + Smilies::add($b, ':ogre:', '👹'); + Smilies::add($b, ':goblin:', '👺'); + Smilies::add($b, ':ghost:', '👻'); + Smilies::add($b, ':alien:', '👽'); + Smilies::add($b, ':alien monster:', '👾'); + Smilies::add($b, ':robot:', '🤖'); // cat-face - Smilies::add($b, ':grinning cat:', '😺'); - Smilies::add($b, ':grinning cat with smiling eyes:', '😸'); - Smilies::add($b, ':cat with tears of joy:', '😹'); - Smilies::add($b, ':smiling cat with heart-eyes:', '😻'); - Smilies::add($b, ':cat with wry smile:', '😼'); - Smilies::add($b, ':kissing cat:', '😽'); - Smilies::add($b, ':weary cat:', '🙀'); - Smilies::add($b, ':crying cat:', '😿'); - Smilies::add($b, ':pouting cat:', '😾'); + Smilies::add($b, ':grinning cat:', '😺'); + Smilies::add($b, ':grinning cat with smiling eyes:', '😸'); + Smilies::add($b, ':cat with tears of joy:', '😹'); + Smilies::add($b, ':smiling cat with heart-eyes:', '😻'); + Smilies::add($b, ':cat with wry smile:', '😼'); + Smilies::add($b, ':kissing cat:', '😽'); + Smilies::add($b, ':weary cat:', '🙀'); + Smilies::add($b, ':crying cat:', '😿'); + Smilies::add($b, ':pouting cat:', '😾'); // monkey-face - Smilies::add($b, ':see-no-evil monkey:', '🙈'); - Smilies::add($b, ':hear-no-evil monkey:', '🙉'); - Smilies::add($b, ':speak-no-evil monkey:', '🙊'); + Smilies::add($b, ':see-no-evil monkey:', '🙈'); + Smilies::add($b, ':hear-no-evil monkey:', '🙉'); + Smilies::add($b, ':speak-no-evil monkey:', '🙊'); //emotion - Smilies::add($b, ':kiss mark:', '💋'); - Smilies::add($b, ':love letter:', '💌'); - Smilies::add($b, ':heart with arrow:', '💘'); - Smilies::add($b, ':heart with ribbon:', '💝'); - Smilies::add($b, ':sparkling heart:', '💖'); - Smilies::add($b, ':loveheart:', '💖'); - Smilies::add($b, ':growing heart:', '💗'); - Smilies::add($b, ':beating heart:', '💓'); - Smilies::add($b, ':revolving hearts:', '💞'); - Smilies::add($b, ':two hearts:', '💕'); - Smilies::add($b, ':heart decoration:', '💟'); - Smilies::add($b, ':heart exclamation:', '❣'); - Smilies::add($b, ':broken heart:', '💔'); - Smilies::add($b, ':red heart:', '❤'); - Smilies::add($b, ':orange heart:', '🧡'); - Smilies::add($b, ':yellow heart:', '💛'); - Smilies::add($b, ':green heart:', '💚'); - Smilies::add($b, ':blue heart:', '💙'); - Smilies::add($b, ':purple heart:', '💜'); - Smilies::add($b, ':brown heart:', '🤎'); - Smilies::add($b, ':black heart:', '🖤'); - Smilies::add($b, ':white heart:', '🤍'); - Smilies::add($b, ':hundred points:', '💯'); - Smilies::add($b, ':anger symbol:', '💢'); - Smilies::add($b, ':collision:', '💥'); - Smilies::add($b, ':dizzy:', '💫'); - Smilies::add($b, ':sweat droplets:', '💦'); - Smilies::add($b, ':dashing away:', '💨'); - Smilies::add($b, ':hole:', '🕳'); - Smilies::add($b, ':bomb:', '💣'); - Smilies::add($b, ':speech balloon:', '💬'); - Smilies::add($b, ':left speech bubble:', '🗨'); - Smilies::add($b, ':right anger bubble:', '🗯'); - Smilies::add($b, ':thought balloon:', '💭'); - Smilies::add($b, ':zzz:', '💤'); + Smilies::add($b, ':kiss mark:', '💋'); + Smilies::add($b, ':love letter:', '💌'); + Smilies::add($b, ':heart with arrow:', '💘'); + Smilies::add($b, ':heart with ribbon:', '💝'); + Smilies::add($b, ':sparkling heart:', '💖'); + Smilies::add($b, ':loveheart:', '💖'); + Smilies::add($b, ':growing heart:', '💗'); + Smilies::add($b, ':beating heart:', '💓'); + Smilies::add($b, ':revolving hearts:', '💞'); + Smilies::add($b, ':two hearts:', '💕'); + Smilies::add($b, ':heart decoration:', '💟'); + Smilies::add($b, ':heart exclamation:', '❣'); + Smilies::add($b, ':broken heart:', '💔'); + Smilies::add($b, ':red heart:', '❤'); + Smilies::add($b, ':orange heart:', '🧡'); + Smilies::add($b, ':yellow heart:', '💛'); + Smilies::add($b, ':green heart:', '💚'); + Smilies::add($b, ':blue heart:', '💙'); + Smilies::add($b, ':purple heart:', '💜'); + Smilies::add($b, ':brown heart:', '🤎'); + Smilies::add($b, ':black heart:', '🖤'); + Smilies::add($b, ':white heart:', '🤍'); + Smilies::add($b, ':hundred points:', '💯'); + Smilies::add($b, ':anger symbol:', '💢'); + Smilies::add($b, ':collision:', '💥'); + Smilies::add($b, ':dizzy:', '💫'); + Smilies::add($b, ':sweat droplets:', '💦'); + Smilies::add($b, ':dashing away:', '💨'); + Smilies::add($b, ':hole:', '🕳'); + Smilies::add($b, ':bomb:', '💣'); + Smilies::add($b, ':speech balloon:', '💬'); + Smilies::add($b, ':left speech bubble:', '🗨'); + Smilies::add($b, ':right anger bubble:', '🗯'); + Smilies::add($b, ':thought balloon:', '💭'); + Smilies::add($b, ':zzz:', '💤'); // People & Body // hand-fingers-open - Smilies::add($b, ':waving hand:', '👋'); - Smilies::add($b, ':raised back of hand:', '🤚'); - Smilies::add($b, ':hand with fingers splayed:', '🖐'); - Smilies::add($b, ':raised hand:', '✋'); - Smilies::add($b, ':vulcan salute:', '🖖'); + Smilies::add($b, ':waving hand:', '👋'); + Smilies::add($b, ':raised back of hand:', '🤚'); + Smilies::add($b, ':hand with fingers splayed:', '🖐'); + Smilies::add($b, ':raised hand:', '✋'); + Smilies::add($b, ':vulcan salute:', '🖖'); // hand-fingers-partial - Smilies::add($b, ':OK hand:', '👌'); -// Smilies::add($b, ':pinching hand:', '🤏'); - Smilies::add($b, ':victory hand:', '✌'); - Smilies::add($b, ':crossed fingers:', '🤞'); - Smilies::add($b, ':love-you gesture:', '🤟'); - Smilies::add($b, ':sign of the horns:', '🤘'); - Smilies::add($b, ':call me hand:', '🤙'); + Smilies::add($b, ':OK hand:', '👌'); + Smilies::add($b, ':victory hand:', '✌'); + Smilies::add($b, ':crossed fingers:', '🤞'); + Smilies::add($b, ':love-you gesture:', '🤟'); + Smilies::add($b, ':sign of the horns:', '🤘'); + Smilies::add($b, ':call me hand:', '🤙'); // hand-single-finger - Smilies::add($b, ':backhand index pointing left:', '👈'); - Smilies::add($b, ':backhand index pointing right:', '👉'); - Smilies::add($b, ':backhand index pointing up:', '👆'); - Smilies::add($b, ':middle finger:', '🖕'); - Smilies::add($b, ':backhand index pointing down:', '👇'); - Smilies::add($b, ':index pointing up:', '☝'); + Smilies::add($b, ':backhand index pointing left:', '👈'); + Smilies::add($b, ':backhand index pointing right:', '👉'); + Smilies::add($b, ':backhand index pointing up:', '👆'); + Smilies::add($b, ':middle finger:', '🖕'); + Smilies::add($b, ':backhand index pointing down:', '👇'); + Smilies::add($b, ':index pointing up:', '☝'); // hand-fingers-closed - Smilies::add($b, ':thumbs up:', '👍'); + Smilies::add($b, ':thumbs up:', '👍'); Smilies::add($b, ':like:', '👍'); Smilies::add($b, '\\o/', '👍'); - Smilies::add($b, ':thumbs down:', '👎'); + Smilies::add($b, ':thumbs down:', '👎'); Smilies::add($b, ':dislike:', '👎'); - Smilies::add($b, ':raised fist:', '✊'); - Smilies::add($b, ':oncoming fist:', '👊'); - Smilies::add($b, ':left-facing fist:', '🤛'); - Smilies::add($b, ':right-facing fist:', '🤜'); + Smilies::add($b, ':raised fist:', '✊'); + Smilies::add($b, ':oncoming fist:', '👊'); + Smilies::add($b, ':left-facing fist:', '🤛'); + Smilies::add($b, ':right-facing fist:', '🤜'); // hands - Smilies::add($b, ':clapping hands:', '👏'); - Smilies::add($b, ':raising hands:', '🙌'); - Smilies::add($b, ':open hands:', '👐'); - Smilies::add($b, ':palms up together:', '🤲'); - Smilies::add($b, ':handshake:', '🤝'); - Smilies::add($b, ':folded hands:', '🙏'); + Smilies::add($b, ':clapping hands:', '👏'); + Smilies::add($b, ':raising hands:', '🙌'); + Smilies::add($b, ':open hands:', '👐'); + Smilies::add($b, ':palms up together:', '🤲'); + Smilies::add($b, ':handshake:', '🤝'); + Smilies::add($b, ':folded hands:', '🙏'); // hand-prop - Smilies::add($b, ':writing hand:', '✍'); - Smilies::add($b, ':nail polish:', '💅'); - Smilies::add($b, ':selfie:', '🤳'); + Smilies::add($b, ':writing hand:', '✍'); + Smilies::add($b, ':nail polish:', '💅'); + Smilies::add($b, ':selfie:', '🤳'); // body-parts - Smilies::add($b, ':flexed biceps:', '💪'); - Smilies::add($b, ':mechanical arm:', '🦾'); - Smilies::add($b, ':mechanical leg:', '🦿'); - Smilies::add($b, ':leg:', '🦵'); - Smilies::add($b, ':foot:', '🦶'); - Smilies::add($b, ':ear:', '👂'); -// Smilies::add($b, ':ear with hearing aid:', '🦻'); - Smilies::add($b, ':nose:', '👃'); - Smilies::add($b, ':brain:', '🧠'); - Smilies::add($b, ':tooth:', '🦷'); - Smilies::add($b, ':bone:', '🦴'); - Smilies::add($b, ':eyes:', '👀'); - Smilies::add($b, ':eye:', '👁'); - Smilies::add($b, ':tongue:', '👅'); - Smilies::add($b, ':mouth:', '👄'); + Smilies::add($b, ':flexed biceps:', '💪'); + Smilies::add($b, ':mechanical arm:', '🦾'); + Smilies::add($b, ':mechanical leg:', '🦿'); + Smilies::add($b, ':leg:', '🦵'); + Smilies::add($b, ':foot:', '🦶'); + Smilies::add($b, ':ear:', '👂'); + Smilies::add($b, ':brain:', '🧠'); + Smilies::add($b, ':tooth:', '🦷'); + Smilies::add($b, ':bone:', '🦴'); + Smilies::add($b, ':eyes:', '👀'); + Smilies::add($b, ':eye:', '👁'); + Smilies::add($b, ':tongue:', '👅'); + Smilies::add($b, ':mouth:', '👄'); // person - Smilies::add($b, ':baby:', '👶'); - Smilies::add($b, ':child:', '🧒'); - Smilies::add($b, ':boy:', '👦'); - Smilies::add($b, ':girl:', '👧'); - Smilies::add($b, ':person:', '🧑'); - Smilies::add($b, ':person: blond hair:', '👱'); - Smilies::add($b, ':man:', '👨'); - Smilies::add($b, ':man: beard:', '🧔'); + Smilies::add($b, ':baby:', '👶'); + Smilies::add($b, ':child:', '🧒'); + Smilies::add($b, ':boy:', '👦'); + Smilies::add($b, ':girl:', '👧'); + Smilies::add($b, ':person:', '🧑'); + Smilies::add($b, ':person: blond hair:', '👱'); + Smilies::add($b, ':man:', '👨'); + Smilies::add($b, ':man: beard:', '🧔'); Smilies::add($b, ':beard:', '🧔'); - Smilies::add($b, ':man: red hair:', '👨‍🦰'); - Smilies::add($b, ':man: curly hair:', '👨‍🦱'); - Smilies::add($b, ':man: white hair:', '👨‍🦳'); - Smilies::add($b, ':man: bald:', '👨‍🦲'); - Smilies::add($b, ':woman:', '👩'); - Smilies::add($b, ':woman: red hair:', '👩‍🦰'); - Smilies::add($b, ':person: red hair:', '🧑‍🦰'); - Smilies::add($b, ':woman: curly hair:', '👩‍🦱'); - Smilies::add($b, ':person: curly hair:', '🧑‍🦱'); - Smilies::add($b, ':woman: white hair:', '👩‍🦳'); - Smilies::add($b, ':person: white hair:', '🧑‍🦳'); - Smilies::add($b, ':woman: bald:', '👩‍🦲'); - Smilies::add($b, ':bald::', '🧑‍🦲'); - Smilies::add($b, ':woman: blond hair:', '👱‍♀️'); - Smilies::add($b, ':man: blond hair:', '👱‍♂️'); - Smilies::add($b, ':older person:', '🧓'); - Smilies::add($b, ':old man:', '👴'); - Smilies::add($b, ':old woman:', '👵'); + Smilies::add($b, ':man: red hair:', '👨‍🦰'); + Smilies::add($b, ':man: curly hair:', '👨‍🦱'); + Smilies::add($b, ':man: white hair:', '👨‍🦳'); + Smilies::add($b, ':man: bald:', '👨‍🦲'); + Smilies::add($b, ':woman:', '👩'); + Smilies::add($b, ':woman: red hair:', '👩‍🦰'); + Smilies::add($b, ':person: red hair:', '🧑‍🦰'); + Smilies::add($b, ':woman: curly hair:', '👩‍🦱'); + Smilies::add($b, ':person: curly hair:', '🧑‍🦱'); + Smilies::add($b, ':woman: white hair:', '👩‍🦳'); + Smilies::add($b, ':person: white hair:', '🧑‍🦳'); + Smilies::add($b, ':woman: bald:', '👩‍🦲'); + Smilies::add($b, ':bald::', '🧑‍🦲'); + Smilies::add($b, ':woman: blond hair:', '👱‍♀️'); + Smilies::add($b, ':man: blond hair:', '👱‍♂️'); + Smilies::add($b, ':older person:', '🧓'); + Smilies::add($b, ':old man:', '👴'); + Smilies::add($b, ':old woman:', '👵'); Smilies::add($b, ':pregnant:', '🤰'); // person-gesture - Smilies::add($b, ':person frowning:', '🙍'); - Smilies::add($b, ':man frowning:', '🙍‍♂️'); - Smilies::add($b, ':woman frowning:', '🙍‍♀️'); - Smilies::add($b, ':person pouting:', '🙎'); - Smilies::add($b, ':man pouting:', '🙎‍♂️'); - Smilies::add($b, ':woman pouting:', '🙎‍♀️'); - Smilies::add($b, ':person gesturing NO:', '🙅'); - Smilies::add($b, ':man gesturing NO:', '🙅‍♂️'); - Smilies::add($b, ':woman gesturing NO:', '🙅‍♀️'); - Smilies::add($b, ':person gesturing OK:', '🙆'); - Smilies::add($b, ':man gesturing OK:', '🙆‍♂️'); - Smilies::add($b, ':woman gesturing OK:', '🙆‍♀️'); - Smilies::add($b, ':person tipping hand:', '💁'); - Smilies::add($b, ':man tipping hand:', '💁‍♂️'); - Smilies::add($b, ':woman tipping hand:', '💁‍♀️'); - Smilies::add($b, ':person raising hand:', '🙋'); - Smilies::add($b, ':man raising hand:', '🙋‍♂️'); - Smilies::add($b, ':woman raising hand', '🙋‍♀️'); -// Smilies::add($b, ':deaf person:', '🧏'); -// Smilies::add($b, ':deaf man:', '🧏‍♂️'); -// Smilies::add($b, ':deaf woman:', '🧏‍♀️'); - Smilies::add($b, ':person bowing:', '🙇'); + Smilies::add($b, ':person frowning:', '🙍'); + Smilies::add($b, ':man frowning:', '🙍‍♂️'); + Smilies::add($b, ':woman frowning:', '🙍‍♀️'); + Smilies::add($b, ':person pouting:', '🙎'); + Smilies::add($b, ':man pouting:', '🙎‍♂️'); + Smilies::add($b, ':woman pouting:', '🙎‍♀️'); + Smilies::add($b, ':person gesturing NO:', '🙅'); + Smilies::add($b, ':man gesturing NO:', '🙅‍♂️'); + Smilies::add($b, ':woman gesturing NO:', '🙅‍♀️'); + Smilies::add($b, ':person gesturing OK:', '🙆'); + Smilies::add($b, ':man gesturing OK:', '🙆‍♂️'); + Smilies::add($b, ':woman gesturing OK:', '🙆‍♀️'); + Smilies::add($b, ':person tipping hand:', '💁'); + Smilies::add($b, ':man tipping hand:', '💁‍♂️'); + Smilies::add($b, ':woman tipping hand:', '💁‍♀️'); + Smilies::add($b, ':person raising hand:', '🙋'); + Smilies::add($b, ':man raising hand:', '🙋‍♂️'); + Smilies::add($b, ':woman raising hand', '🙋‍♀️'); +// Smilies::add($b, ':deaf person:', '🧏'); +// Smilies::add($b, ':deaf man:', '🧏‍♂️'); +// Smilies::add($b, ':deaf woman:', '🧏‍♀️'); + Smilies::add($b, ':person bowing:', '🙇'); Smilies::add($b, ':bow:', '🙇'); - Smilies::add($b, ':man bowing:', '🙇‍♂️'); - Smilies::add($b, ':woman bowing:', '🙇‍♀️'); - Smilies::add($b, ':person facepalming:', '🤦'); + Smilies::add($b, ':man bowing:', '🙇‍♂️'); + Smilies::add($b, ':woman bowing:', '🙇‍♀️'); + Smilies::add($b, ':person facepalming:', '🤦'); Smilies::add($b, ':facepalm:', '🤦'); - Smilies::add($b, ':man facepalming:', '🤦‍♂️'); - Smilies::add($b, ':woman facepalming:', '🤦‍♀️'); - Smilies::add($b, ':person shrugging:', '🤷'); + Smilies::add($b, ':man facepalming:', '🤦‍♂️'); + Smilies::add($b, ':woman facepalming:', '🤦‍♀️'); + Smilies::add($b, ':person shrugging:', '🤷'); Smilies::add($b, ':shrug:', '🤷'); - Smilies::add($b, ':man shrugging:', '🤷‍♂️'); - Smilies::add($b, ':woman shrugging:', '🤷‍♀️'); + Smilies::add($b, ':man shrugging:', '🤷‍♂️'); + Smilies::add($b, ':woman shrugging:', '🤷‍♀️'); // person-role // person-fantasy - Smilies::add($b, ':baby angel:', '👼'); + Smilies::add($b, ':baby angel:', '👼'); Smilies::add($b, ':angel:', '👼'); Smilies::add($b, ':cherub:', '👼'); - Smilies::add($b, ':Santa Claus:', '🎅'); - Smilies::add($b, ':Mrs. Claus:', '🤶'); - Smilies::add($b, ':superhero:', '🦸'); - Smilies::add($b, ':man superhero:', '🦸‍♂️'); - Smilies::add($b, ':woman superhero:', '🦸‍♀️'); - Smilies::add($b, ':supervillain:', '🦹'); - Smilies::add($b, ':man supervillain:', '🦹‍♂️'); - Smilies::add($b, ':woman supervillain:', '🦹‍♀️'); - Smilies::add($b, ':mage:', '🧙'); - Smilies::add($b, ':man mage:', '🧙‍♂️'); - Smilies::add($b, ':woman mage:', '🧙‍♀️'); - Smilies::add($b, ':fairy:', '🧚'); - Smilies::add($b, ':man fairy:', '🧚‍♂️'); - Smilies::add($b, ':woman fairy:', '🧚‍♀️'); - Smilies::add($b, ':vampire:', '🧛'); - Smilies::add($b, ':man vampire:', '🧛‍♂️'); - Smilies::add($b, ':woman vampire:', '🧛‍♀️'); - Smilies::add($b, ':merperson:', '🧜'); - Smilies::add($b, ':merman:', '🧜‍♂️'); - Smilies::add($b, ':mermaid:', '🧜‍♀️'); - Smilies::add($b, ':elf:', '🧝'); - Smilies::add($b, ':man elf:', '🧝‍♂️'); - Smilies::add($b, ':woman elf:', '🧝‍♀️'); - Smilies::add($b, ':genie:', '🧞'); - Smilies::add($b, ':man genie:', '🧞‍♂️'); - Smilies::add($b, ':woman genie:', '🧞‍♀️'); - Smilies::add($b, ':zombie:', '🧟'); - Smilies::add($b, ':man zombie:', '🧟‍♂️'); - Smilies::add($b, ':woman zombie:', '🧟‍♀️'); + Smilies::add($b, ':Santa Claus:', '🎅'); + Smilies::add($b, ':Mrs. Claus:', '🤶'); + Smilies::add($b, ':superhero:', '🦸'); + Smilies::add($b, ':man superhero:', '🦸‍♂️'); + Smilies::add($b, ':woman superhero:', '🦸‍♀️'); + Smilies::add($b, ':supervillain:', '🦹'); + Smilies::add($b, ':man supervillain:', '🦹‍♂️'); + Smilies::add($b, ':woman supervillain:', '🦹‍♀️'); + Smilies::add($b, ':mage:', '🧙'); + Smilies::add($b, ':man mage:', '🧙‍♂️'); + Smilies::add($b, ':woman mage:', '🧙‍♀️'); + Smilies::add($b, ':fairy:', '🧚'); + Smilies::add($b, ':man fairy:', '🧚‍♂️'); + Smilies::add($b, ':woman fairy:', '🧚‍♀️'); + Smilies::add($b, ':vampire:', '🧛'); + Smilies::add($b, ':man vampire:', '🧛‍♂️'); + Smilies::add($b, ':woman vampire:', '🧛‍♀️'); + Smilies::add($b, ':merperson:', '🧜'); + Smilies::add($b, ':merman:', '🧜‍♂️'); + Smilies::add($b, ':mermaid:', '🧜‍♀️'); + Smilies::add($b, ':elf:', '🧝'); + Smilies::add($b, ':man elf:', '🧝‍♂️'); + Smilies::add($b, ':woman elf:', '🧝‍♀️'); + Smilies::add($b, ':genie:', '🧞'); + Smilies::add($b, ':man genie:', '🧞‍♂️'); + Smilies::add($b, ':woman genie:', '🧞‍♀️'); + Smilies::add($b, ':zombie:', '🧟'); + Smilies::add($b, ':man zombie:', '🧟‍♂️'); + Smilies::add($b, ':woman zombie:', '🧟‍♀️'); // person-activity @@ -411,83 +408,83 @@ function unicode_smilies_smilies(array &$b) // person-resting // family - Smilies::add($b, ':people holding hands:', '🧑‍🤝‍🧑'); - Smilies::add($b, ':women holding hands:', '👭'); - Smilies::add($b, ':woman and man holding hands:', '👫'); - Smilies::add($b, ':men holding hands:', '👬'); - Smilies::add($b, ':kiss:', '💏'); - Smilies::add($b, ':couple with heart:', '💑'); - Smilies::add($b, ':family:', '👪'); + Smilies::add($b, ':people holding hands:', '🧑‍🤝‍🧑'); + Smilies::add($b, ':women holding hands:', '👭'); + Smilies::add($b, ':woman and man holding hands:', '👫'); + Smilies::add($b, ':men holding hands:', '👬'); + Smilies::add($b, ':kiss:', '💏'); + Smilies::add($b, ':couple with heart:', '💑'); + Smilies::add($b, ':family:', '👪'); // person-symbol - Smilies::add($b, ':speaking head:', '🗣'); - Smilies::add($b, ':bust in silhouette:', '👤'); - Smilies::add($b, ':busts in silhouette:', '👥'); - Smilies::add($b, ':footprints:', '👣'); + Smilies::add($b, ':speaking head:', '🗣'); + Smilies::add($b, ':bust in silhouette:', '👤'); + Smilies::add($b, ':busts in silhouette:', '👥'); + Smilies::add($b, ':footprints:', '👣'); // Component // hair-style // Animals & Nature // animal-mammal - Smilies::add($b, ':monkey face:', '🐵'); - Smilies::add($b, ':monkey:', '🐒'); - Smilies::add($b, ':gorilla:', '🦍'); - Smilies::add($b, ':orangutan:', '🦧'); - Smilies::add($b, ':dog face:', '🐶'); - Smilies::add($b, ':dog:', '🐕'); - Smilies::add($b, ':guide dog:', '🦮'); - Smilies::add($b, ':poodle:', '🐩'); - Smilies::add($b, ':wolf:', '🐺'); - Smilies::add($b, ':fox:', '🦊'); - Smilies::add($b, ':raccoon:', '🦝'); - Smilies::add($b, ':cat face:', '🐱'); - Smilies::add($b, ':cat:', '🐈'); - Smilies::add($b, ':lion:', '🦁'); - Smilies::add($b, ':tiger face:', '🐯'); - Smilies::add($b, ':tiger:', '🐅'); - Smilies::add($b, ':leopard:', '🐆'); - Smilies::add($b, ':horse face:', '🐴'); - Smilies::add($b, ':horse:', '🐎'); - Smilies::add($b, ':unicorn:', '🦄'); - Smilies::add($b, ':zebra:', '🦓'); - Smilies::add($b, ':deer:', '🦌'); - Smilies::add($b, ':cow face:', '🐮'); - Smilies::add($b, ':ox:', '🐂'); - Smilies::add($b, ':water buffalo:', '🐃'); - Smilies::add($b, ':cow:', '🐄'); - Smilies::add($b, ':pig face:', '🐷'); - Smilies::add($b, ':pig:', '🐖'); + Smilies::add($b, ':monkey face:', '🐵'); + Smilies::add($b, ':monkey:', '🐒'); + Smilies::add($b, ':gorilla:', '🦍'); + Smilies::add($b, ':orangutan:', '🦧'); + Smilies::add($b, ':dog face:', '🐶'); + Smilies::add($b, ':dog:', '🐕'); + Smilies::add($b, ':guide dog:', '🦮'); + Smilies::add($b, ':poodle:', '🐩'); + Smilies::add($b, ':wolf:', '🐺'); + Smilies::add($b, ':fox:', '🦊'); + Smilies::add($b, ':raccoon:', '🦝'); + Smilies::add($b, ':cat face:', '🐱'); + Smilies::add($b, ':cat:', '🐈'); + Smilies::add($b, ':lion:', '🦁'); + Smilies::add($b, ':tiger face:', '🐯'); + Smilies::add($b, ':tiger:', '🐅'); + Smilies::add($b, ':leopard:', '🐆'); + Smilies::add($b, ':horse face:', '🐴'); + Smilies::add($b, ':horse:', '🐎'); + Smilies::add($b, ':unicorn:', '🦄'); + Smilies::add($b, ':zebra:', '🦓'); + Smilies::add($b, ':deer:', '🦌'); + Smilies::add($b, ':cow face:', '🐮'); + Smilies::add($b, ':ox:', '🐂'); + Smilies::add($b, ':water buffalo:', '🐃'); + Smilies::add($b, ':cow:', '🐄'); + Smilies::add($b, ':pig face:', '🐷'); + Smilies::add($b, ':pig:', '🐖'); Smilies::add($b, ':boar:', '🐗'); - Smilies::add($b, ':pig nose:', '🐽'); - Smilies::add($b, ':ram:', '🐏'); - Smilies::add($b, ':sheep:', '🐑'); - Smilies::add($b, ':goat:', '🐐'); + Smilies::add($b, ':pig nose:', '🐽'); + Smilies::add($b, ':ram:', '🐏'); + Smilies::add($b, ':sheep:', '🐑'); + Smilies::add($b, ':goat:', '🐐'); Smilies::add($b, ':camel:', '🐪'); - Smilies::add($b, ':two-hump camel:', '🐫'); - Smilies::add($b, ':llama:', '🦙'); - Smilies::add($b, ':giraffe:', '🦒'); - Smilies::add($b, ':elephant:', '🐘'); - Smilies::add($b, ':rhinoceros:', '🦏'); - Smilies::add($b, ':hippopotamus:', '🦛'); - Smilies::add($b, ':mouse face:', '🐭'); - Smilies::add($b, ':mouse:', '🐁'); - Smilies::add($b, ':rat:', '🐀'); - Smilies::add($b, ':hamster:', '🐹'); - Smilies::add($b, ':rabbit face:', '🐰'); - Smilies::add($b, ':rabbit:', '🐇'); - Smilies::add($b, ':chipmunk:', '🐿'); - Smilies::add($b, ':hedgehog:', '🦔'); - Smilies::add($b, ':bat:', '🦇'); - Smilies::add($b, ':bear:', '🐻'); - Smilies::add($b, ':koala:', '🐨'); - Smilies::add($b, ':panda:', '🐼'); - Smilies::add($b, ':sloth:', '🦥'); - Smilies::add($b, ':otter:', '🦦'); - Smilies::add($b, ':skunk:', '🦨'); - Smilies::add($b, ':kangaroo:', '🦘'); - Smilies::add($b, ':badger:', '🦡'); - Smilies::add($b, ':paw prints:', '🐾'); + Smilies::add($b, ':two-hump camel:', '🐫'); + Smilies::add($b, ':llama:', '🦙'); + Smilies::add($b, ':giraffe:', '🦒'); + Smilies::add($b, ':elephant:', '🐘'); + Smilies::add($b, ':rhinoceros:', '🦏'); + Smilies::add($b, ':hippopotamus:', '🦛'); + Smilies::add($b, ':mouse face:', '🐭'); + Smilies::add($b, ':mouse:', '🐁'); + Smilies::add($b, ':rat:', '🐀'); + Smilies::add($b, ':hamster:', '🐹'); + Smilies::add($b, ':rabbit face:', '🐰'); + Smilies::add($b, ':rabbit:', '🐇'); + Smilies::add($b, ':chipmunk:', '🐿'); + Smilies::add($b, ':hedgehog:', '🦔'); + Smilies::add($b, ':bat:', '🦇'); + Smilies::add($b, ':bear:', '🐻'); + Smilies::add($b, ':koala:', '🐨'); + Smilies::add($b, ':panda:', '🐼'); + Smilies::add($b, ':sloth:', '🦥'); + Smilies::add($b, ':otter:', '🦦'); + Smilies::add($b, ':skunk:', '🦨'); + Smilies::add($b, ':kangaroo:', '🦘'); + Smilies::add($b, ':badger:', '🦡'); + Smilies::add($b, ':paw prints:', '🐾'); // Smilies::add($b, ':bunnyflowers:', '&#x;'); Smilies::add($b, ':chick:', '🐤'); Smilies::add($b, ':ladybird:', '🐞'); @@ -495,959 +492,958 @@ function unicode_smilies_smilies(array &$b) // Smilies::add($b, ':dragonfly:', '&#x;'); // animal-bird - Smilies::add($b, ':turkey:', '🦃'); - Smilies::add($b, ':chicken:', '🐔'); - Smilies::add($b, ':rooster:', '🐓'); - Smilies::add($b, ':hatching chick:', '🐣'); - Smilies::add($b, ':baby chick:', '🐤'); - Smilies::add($b, ':front-facing baby chick:', '🐥'); - Smilies::add($b, ':bird:', '🐦'); - Smilies::add($b, ':tux:', '🐧'); - Smilies::add($b, ':dove:', '🕊'); - Smilies::add($b, ':eagle:', '🦅'); - Smilies::add($b, ':duck:', '🦆'); - Smilies::add($b, ':swan:', '🦢'); - Smilies::add($b, ':owl:', '🦉'); - Smilies::add($b, ':flamingo:', '🦩'); - Smilies::add($b, ':peacock:', '🦚'); - Smilies::add($b, ':parrot:', '🦜'); + Smilies::add($b, ':turkey:', '🦃'); + Smilies::add($b, ':chicken:', '🐔'); + Smilies::add($b, ':rooster:', '🐓'); + Smilies::add($b, ':hatching chick:', '🐣'); + Smilies::add($b, ':baby chick:', '🐤'); + Smilies::add($b, ':front-facing baby chick:', '🐥'); + Smilies::add($b, ':bird:', '🐦'); + Smilies::add($b, ':tux:', '🐧'); + Smilies::add($b, ':dove:', '🕊'); + Smilies::add($b, ':eagle:', '🦅'); + Smilies::add($b, ':duck:', '🦆'); + Smilies::add($b, ':swan:', '🦢'); + Smilies::add($b, ':owl:', '🦉'); + Smilies::add($b, ':flamingo:', '🦩'); + Smilies::add($b, ':peacock:', '🦚'); + Smilies::add($b, ':parrot:', '🦜'); // animal-amphibian - Smilies::add($b, ':frog:', '🐸'); + Smilies::add($b, ':frog:', '🐸'); // animal-reptile - Smilies::add($b, ':crocodile:', '🐊'); - Smilies::add($b, ':turtle:', '🐢'); - Smilies::add($b, ':lizard:', '🦎'); - Smilies::add($b, ':snake:', '🐍'); - Smilies::add($b, ':dragon face:', '🐲'); - Smilies::add($b, ':dragon:', '🐉'); + Smilies::add($b, ':crocodile:', '🐊'); + Smilies::add($b, ':turtle:', '🐢'); + Smilies::add($b, ':lizard:', '🦎'); + Smilies::add($b, ':snake:', '🐍'); + Smilies::add($b, ':dragon face:', '🐲'); + Smilies::add($b, ':dragon:', '🐉'); Smilies::add($b, ':draco:', '🐉'); - Smilies::add($b, ':sauropod:', '🦕'); - Smilies::add($b, ':T-Rex:', '🦖'); + Smilies::add($b, ':sauropod:', '🦕'); + Smilies::add($b, ':T-Rex:', '🦖'); // animal-marine - Smilies::add($b, ':spouting whale:', '🐳'); - Smilies::add($b, ':whale:', '🐋'); - Smilies::add($b, ':dolphin:', '🐬'); - Smilies::add($b, ':fish:', '🐟'); - Smilies::add($b, ':tropical fish:', '🐠'); - Smilies::add($b, ':blowfish:', '🐡'); - Smilies::add($b, ':shark:', '🦈'); - Smilies::add($b, ':octopus:', '🐙'); - Smilies::add($b, ':spiral shell:', '🐚'); + Smilies::add($b, ':spouting whale:', '🐳'); + Smilies::add($b, ':whale:', '🐋'); + Smilies::add($b, ':dolphin:', '🐬'); + Smilies::add($b, ':fish:', '🐟'); + Smilies::add($b, ':tropical fish:', '🐠'); + Smilies::add($b, ':blowfish:', '🐡'); + Smilies::add($b, ':shark:', '🦈'); + Smilies::add($b, ':octopus:', '🐙'); + Smilies::add($b, ':spiral shell:', '🐚'); // animal-bug - Smilies::add($b, ':snail:', '🐌'); - Smilies::add($b, ':butterfly:', '🦋'); - Smilies::add($b, ':bug:', '🐛'); - Smilies::add($b, ':ant:', '🐜'); - Smilies::add($b, ':honeybee:', '🐝'); - Smilies::add($b, ':lady beetle:', '🐞'); - Smilies::add($b, ':cricket:', '🦗'); - Smilies::add($b, ':spider:', '🕷'); - Smilies::add($b, ':spider web:', '🕸'); - Smilies::add($b, ':scorpion:', '🦂'); - Smilies::add($b, ':mosquito:', '🦟'); - Smilies::add($b, ':microbe:', '🦠'); + Smilies::add($b, ':snail:', '🐌'); + Smilies::add($b, ':butterfly:', '🦋'); + Smilies::add($b, ':bug:', '🐛'); + Smilies::add($b, ':ant:', '🐜'); + Smilies::add($b, ':honeybee:', '🐝'); + Smilies::add($b, ':lady beetle:', '🐞'); + Smilies::add($b, ':cricket:', '🦗'); + Smilies::add($b, ':spider:', '🕷'); + Smilies::add($b, ':spider web:', '🕸'); + Smilies::add($b, ':scorpion:', '🦂'); + Smilies::add($b, ':mosquito:', '🦟'); + Smilies::add($b, ':microbe:', '🦠'); // plant-flower - Smilies::add($b, ':bouquet:', '💐'); - Smilies::add($b, ':cherry blossom:', '🌸'); - Smilies::add($b, ':white flower:', '💮'); - Smilies::add($b, ':rosette:', '🏵'); - Smilies::add($b, ':rose:', '🌹'); - Smilies::add($b, ':wilted flower:', '🥀'); - Smilies::add($b, ':hibiscus:', '🌺'); - Smilies::add($b, ':sunflower:', '🌻'); - Smilies::add($b, ':blossom:', '🌼'); - Smilies::add($b, ':tulip:', '🌷'); + Smilies::add($b, ':bouquet:', '💐'); + Smilies::add($b, ':cherry blossom:', '🌸'); + Smilies::add($b, ':white flower:', '💮'); + Smilies::add($b, ':rosette:', '🏵'); + Smilies::add($b, ':rose:', '🌹'); + Smilies::add($b, ':wilted flower:', '🥀'); + Smilies::add($b, ':hibiscus:', '🌺'); + Smilies::add($b, ':sunflower:', '🌻'); + Smilies::add($b, ':blossom:', '🌼'); + Smilies::add($b, ':tulip:', '🌷'); // plant-other - Smilies::add($b, ':seedling:', '🌱'); - Smilies::add($b, ':evergreen tree:', '🌲'); - Smilies::add($b, ':deciduous tree:', '🌳'); - Smilies::add($b, ':palm tree:', '🌴'); - Smilies::add($b, ':cactus:', '🌵'); - Smilies::add($b, ':sheaf of rice:', '🌾'); - Smilies::add($b, ':herb:', '🌿'); - Smilies::add($b, ':shamrock:', '☘'); - Smilies::add($b, ':four leaf clover:', '🍀'); - Smilies::add($b, ':maple leaf:', '🍁'); - Smilies::add($b, ':fallen leaf:', '🍂'); - Smilies::add($b, ':leaf fluttering in wind:', '🍃'); + Smilies::add($b, ':seedling:', '🌱'); + Smilies::add($b, ':evergreen tree:', '🌲'); + Smilies::add($b, ':deciduous tree:', '🌳'); + Smilies::add($b, ':palm tree:', '🌴'); + Smilies::add($b, ':cactus:', '🌵'); + Smilies::add($b, ':sheaf of rice:', '🌾'); + Smilies::add($b, ':herb:', '🌿'); + Smilies::add($b, ':shamrock:', '☘'); + Smilies::add($b, ':four leaf clover:', '🍀'); + Smilies::add($b, ':maple leaf:', '🍁'); + Smilies::add($b, ':fallen leaf:', '🍂'); + Smilies::add($b, ':leaf fluttering in wind:', '🍃'); // Food & Drink // food-fruit - Smilies::add($b, ':grapes:', '🍇'); - Smilies::add($b, ':melon:', '🍈'); - Smilies::add($b, ':watermelon:', '🍉'); - Smilies::add($b, ':tangerine:', '🍊'); - Smilies::add($b, ':lemon:', '🍋'); - Smilies::add($b, ':banana:', '🍌'); - Smilies::add($b, ':pineapple:', '🍍'); - Smilies::add($b, ':mango:', '🥭'); - Smilies::add($b, ':red apple:', '🍎'); + Smilies::add($b, ':grapes:', '🍇'); + Smilies::add($b, ':melon:', '🍈'); + Smilies::add($b, ':watermelon:', '🍉'); + Smilies::add($b, ':tangerine:', '🍊'); + Smilies::add($b, ':lemon:', '🍋'); + Smilies::add($b, ':banana:', '🍌'); + Smilies::add($b, ':pineapple:', '🍍'); + Smilies::add($b, ':mango:', '🥭'); + Smilies::add($b, ':red apple:', '🍎'); Smilies::add($b, ':apple:', '🍎'); - Smilies::add($b, ':green apple:', '🍏'); - Smilies::add($b, ':pear:', '🍐'); - Smilies::add($b, ':peach:', '🍑'); - Smilies::add($b, ':cherries:', '🍒'); - Smilies::add($b, ':strawberry:', '🍓'); - Smilies::add($b, ':kiwi fruit:', '🥝'); - Smilies::add($b, ':tomato:', '🍅'); - Smilies::add($b, ':coconut:', '🥥'); + Smilies::add($b, ':green apple:', '🍏'); + Smilies::add($b, ':pear:', '🍐'); + Smilies::add($b, ':peach:', '🍑'); + Smilies::add($b, ':cherries:', '🍒'); + Smilies::add($b, ':strawberry:', '🍓'); + Smilies::add($b, ':kiwi fruit:', '🥝'); + Smilies::add($b, ':tomato:', '🍅'); + Smilies::add($b, ':coconut:', '🥥'); // food-vegetable - Smilies::add($b, ':avocado:', '🥑'); - Smilies::add($b, ':eggplant:', '🍆'); - Smilies::add($b, ':potato:', '🥔'); - Smilies::add($b, ':carrot:', '🥕'); - Smilies::add($b, ':ear of corn:', '🌽'); - Smilies::add($b, ':hot pepper:', '🌶'); - Smilies::add($b, ':cucumber:', '🥒'); - Smilies::add($b, ':leafy green:', '🥬'); - Smilies::add($b, ':broccoli:', '🥦'); - Smilies::add($b, ':garlic:', '🧄'); - Smilies::add($b, ':onion:', '🧅'); - Smilies::add($b, ':mushroom:', '🍄'); - Smilies::add($b, ':peanuts:', '🥜'); - Smilies::add($b, ':chestnut:', '🌰'); + Smilies::add($b, ':avocado:', '🥑'); + Smilies::add($b, ':eggplant:', '🍆'); + Smilies::add($b, ':potato:', '🥔'); + Smilies::add($b, ':carrot:', '🥕'); + Smilies::add($b, ':ear of corn:', '🌽'); + Smilies::add($b, ':hot pepper:', '🌶'); + Smilies::add($b, ':cucumber:', '🥒'); + Smilies::add($b, ':leafy green:', '🥬'); + Smilies::add($b, ':broccoli:', '🥦'); + Smilies::add($b, ':garlic:', '🧄'); + Smilies::add($b, ':onion:', '🧅'); + Smilies::add($b, ':mushroom:', '🍄'); + Smilies::add($b, ':peanuts:', '🥜'); + Smilies::add($b, ':chestnut:', '🌰'); // food-prepared - Smilies::add($b, ':bread:', '🍞'); - Smilies::add($b, ':croissant:', '🥐'); - Smilies::add($b, ':baguette bread:', '🥖'); - Smilies::add($b, ':pretzel:', '🥨'); - Smilies::add($b, ':bagel:', '🥯'); - Smilies::add($b, ':pancakes:', '🥞'); - Smilies::add($b, ':waffle:', '🧇'); - Smilies::add($b, ':cheese wedge:', '🧀'); - Smilies::add($b, ':meat on bone:', '🍖'); - Smilies::add($b, ':poultry leg:', '🍗'); - Smilies::add($b, ':cut of meat:', '🥩'); - Smilies::add($b, ':bacon:', '🥓'); - Smilies::add($b, ':hamburger:', '🍔'); - Smilies::add($b, ':french fries:', '🍟'); - Smilies::add($b, ':pizza:', '🍕'); - Smilies::add($b, ':hot dog:', '🌭'); - Smilies::add($b, ':sandwich:', '🥪'); - Smilies::add($b, ':taco:', '🌮'); - Smilies::add($b, ':burrito:', '🌯'); - Smilies::add($b, ':stuffed flatbread:', '🥙'); - Smilies::add($b, ':falafel:', '🧆'); - Smilies::add($b, ':egg:', '🥚'); - Smilies::add($b, ':cooking:', '🍳'); + Smilies::add($b, ':bread:', '🍞'); + Smilies::add($b, ':croissant:', '🥐'); + Smilies::add($b, ':baguette bread:', '🥖'); + Smilies::add($b, ':pretzel:', '🥨'); + Smilies::add($b, ':bagel:', '🥯'); + Smilies::add($b, ':pancakes:', '🥞'); + Smilies::add($b, ':waffle:', '🧇'); + Smilies::add($b, ':cheese wedge:', '🧀'); + Smilies::add($b, ':meat on bone:', '🍖'); + Smilies::add($b, ':poultry leg:', '🍗'); + Smilies::add($b, ':cut of meat:', '🥩'); + Smilies::add($b, ':bacon:', '🥓'); + Smilies::add($b, ':hamburger:', '🍔'); + Smilies::add($b, ':french fries:', '🍟'); + Smilies::add($b, ':pizza:', '🍕'); + Smilies::add($b, ':hot dog:', '🌭'); + Smilies::add($b, ':sandwich:', '🥪'); + Smilies::add($b, ':taco:', '🌮'); + Smilies::add($b, ':burrito:', '🌯'); + Smilies::add($b, ':stuffed flatbread:', '🥙'); + Smilies::add($b, ':falafel:', '🧆'); + Smilies::add($b, ':egg:', '🥚'); + Smilies::add($b, ':cooking:', '🍳'); Smilies::add($b, ':fryegg:', '🍳'); - Smilies::add($b, ':shallow pan of food:', '🥘'); - Smilies::add($b, ':pot of food:', '🍲'); - Smilies::add($b, ':bowl with spoon:', '🥣'); - Smilies::add($b, ':green salad:', '🥗'); - Smilies::add($b, ':popcorn:', '🍿'); - Smilies::add($b, ':butter:', '🧈'); - Smilies::add($b, ':salt:', '🧂'); - Smilies::add($b, ':canned food:', '🥫'); + Smilies::add($b, ':shallow pan of food:', '🥘'); + Smilies::add($b, ':pot of food:', '🍲'); + Smilies::add($b, ':bowl with spoon:', '🥣'); + Smilies::add($b, ':green salad:', '🥗'); + Smilies::add($b, ':popcorn:', '🍿'); + Smilies::add($b, ':butter:', '🧈'); + Smilies::add($b, ':salt:', '🧂'); + Smilies::add($b, ':canned food:', '🥫'); // food-asian - Smilies::add($b, ':bento box:', '🍱'); - Smilies::add($b, ':rice cracker:', '🍘'); - Smilies::add($b, ':rice ball:', '🍙'); - Smilies::add($b, ':cooked rice:', '🍚'); - Smilies::add($b, ':curry rice:', '🍛'); - Smilies::add($b, ':steaming bowl:', '🍜'); - Smilies::add($b, ':spaghetti:', '🍝'); - Smilies::add($b, ':roasted sweet potato:', '🍠'); - Smilies::add($b, ':oden:', '🍢'); - Smilies::add($b, ':sushi:', '🍣'); - Smilies::add($b, ':fried shrimp:', '🍤'); - Smilies::add($b, ':fish cake with swirl:', '🍥'); - Smilies::add($b, ':moon cake:', '🥮'); - Smilies::add($b, ':dango:', '🍡'); - Smilies::add($b, ':dumpling:', '🥟'); - Smilies::add($b, ':fortune cookie:', '🥠'); - Smilies::add($b, ':takeout box:', '🥡'); + Smilies::add($b, ':bento box:', '🍱'); + Smilies::add($b, ':rice cracker:', '🍘'); + Smilies::add($b, ':rice ball:', '🍙'); + Smilies::add($b, ':cooked rice:', '🍚'); + Smilies::add($b, ':curry rice:', '🍛'); + Smilies::add($b, ':steaming bowl:', '🍜'); + Smilies::add($b, ':spaghetti:', '🍝'); + Smilies::add($b, ':roasted sweet potato:', '🍠'); + Smilies::add($b, ':oden:', '🍢'); + Smilies::add($b, ':sushi:', '🍣'); + Smilies::add($b, ':fried shrimp:', '🍤'); + Smilies::add($b, ':fish cake with swirl:', '🍥'); + Smilies::add($b, ':moon cake:', '🥮'); + Smilies::add($b, ':dango:', '🍡'); + Smilies::add($b, ':dumpling:', '🥟'); + Smilies::add($b, ':fortune cookie:', '🥠'); + Smilies::add($b, ':takeout box:', '🥡'); // food-marine - Smilies::add($b, ':crab:', '🦀'); - Smilies::add($b, ':lobster:', '🦞'); - Smilies::add($b, ':shrimp:', '🦐'); - Smilies::add($b, ':squid:', '🦑'); -// Smilies::add($b, ':oyster:', '🦪'); + Smilies::add($b, ':crab:', '🦀'); + Smilies::add($b, ':lobster:', '🦞'); + Smilies::add($b, ':shrimp:', '🦐'); + Smilies::add($b, ':squid:', '🦑'); +// Smilies::add($b, ':oyster:', '🦪'); // food-sweet - Smilies::add($b, ':soft ice cream:', '🍦'); - Smilies::add($b, ':shaved ice:', '🍧'); - Smilies::add($b, ':ice cream:', '🍨'); - Smilies::add($b, ':doughnut:', '🍩'); - Smilies::add($b, ':cookie:', '🍪'); - Smilies::add($b, ':birthday cake:', '🎂'); - Smilies::add($b, ':shortcake:', '🍰'); + Smilies::add($b, ':soft ice cream:', '🍦'); + Smilies::add($b, ':shaved ice:', '🍧'); + Smilies::add($b, ':ice cream:', '🍨'); + Smilies::add($b, ':doughnut:', '🍩'); + Smilies::add($b, ':cookie:', '🍪'); + Smilies::add($b, ':birthday cake:', '🎂'); + Smilies::add($b, ':shortcake:', '🍰'); Smilies::add($b, ':cake:', '🍰'); - Smilies::add($b, ':cupcake:', '🧁'); - Smilies::add($b, ':pie:', '🥧'); - Smilies::add($b, ':chocolate bar:', '🍫'); - Smilies::add($b, ':candy:', '🍬'); - Smilies::add($b, ':lollipop:', '🍭'); - Smilies::add($b, ':custard:', '🍮'); - Smilies::add($b, ':honey pot:', '🍯'); + Smilies::add($b, ':cupcake:', '🧁'); + Smilies::add($b, ':pie:', '🥧'); + Smilies::add($b, ':chocolate bar:', '🍫'); + Smilies::add($b, ':candy:', '🍬'); + Smilies::add($b, ':lollipop:', '🍭'); + Smilies::add($b, ':custard:', '🍮'); + Smilies::add($b, ':honey pot:', '🍯'); -// drink - Smilies::add($b, ':baby bottle:', '🍼'); - Smilies::add($b, ':glass of milk:', '🥛'); - Smilies::add($b, ':hot beverage:', '☕'); +// drink + Smilies::add($b, ':baby bottle:', '🍼'); + Smilies::add($b, ':glass of milk:', '🥛'); + Smilies::add($b, ':hot beverage:', '☕'); Smilies::add($b, ':coffee:', '☕'); Smilies::add($b, ':tea:', '☕'); Smilies::add($b, ':tee:', '☕'); - Smilies::add($b, ':teacup without handle:', '🍵'); - Smilies::add($b, ':sake:', '🍶'); - Smilies::add($b, ':bottle with popping cork:', '🍾'); - Smilies::add($b, ':wine glass:', '🍷'); - Smilies::add($b, ':cocktail glass:', '🍸'); - Smilies::add($b, ':tropical drink:', '🍹'); - Smilies::add($b, ':beer mug:', '🍺'); + Smilies::add($b, ':teacup without handle:', '🍵'); + Smilies::add($b, ':sake:', '🍶'); + Smilies::add($b, ':bottle with popping cork:', '🍾'); + Smilies::add($b, ':wine glass:', '🍷'); + Smilies::add($b, ':cocktail glass:', '🍸'); + Smilies::add($b, ':tropical drink:', '🍹'); + Smilies::add($b, ':beer mug:', '🍺'); Smilies::add($b, ':beer:', '🍺'); Smilies::add($b, ':homebrew:', '🍺'); - Smilies::add($b, ':clinking beer mugs:', '🍻'); - Smilies::add($b, ':clinking glasses:', '🥂'); - Smilies::add($b, ':tumbler glass:', '🥃'); - Smilies::add($b, ':cup with straw:', '🥤'); -// Smilies::add($b, ':beverage box:', '🧃'); - Smilies::add($b, ':mate:', '🧉'); - Smilies::add($b, ':ice:', '🧊'); + Smilies::add($b, ':clinking beer mugs:', '🍻'); + Smilies::add($b, ':clinking glasses:', '🥂'); + Smilies::add($b, ':tumbler glass:', '🥃'); + Smilies::add($b, ':cup with straw:', '🥤'); +// Smilies::add($b, ':beverage box:', '🧃'); + Smilies::add($b, ':mate:', '🧉'); + Smilies::add($b, ':ice:', '🧊'); // dishware - Smilies::add($b, ':chopsticks:', '🥢'); - Smilies::add($b, ':fork and knife with plate:', '🍽'); - Smilies::add($b, ':fork and knife:', '🍴'); - Smilies::add($b, ':spoon:', '🥄'); - Smilies::add($b, ':kitchen knife:', '🔪'); - Smilies::add($b, ':amphora:', '🏺'); + Smilies::add($b, ':chopsticks:', '🥢'); + Smilies::add($b, ':fork and knife with plate:', '🍽'); + Smilies::add($b, ':fork and knife:', '🍴'); + Smilies::add($b, ':spoon:', '🥄'); + Smilies::add($b, ':kitchen knife:', '🔪'); + Smilies::add($b, ':amphora:', '🏺'); // Travel & Places // place-map - Smilies::add($b, ':globe showing Europe-Africa:', '🌍'); - Smilies::add($b, ':globe showing Americas:', '🌎'); - Smilies::add($b, ':globe showing Asia-Australia:', '🌏'); - Smilies::add($b, ':globe with meridians:', '🌐'); - Smilies::add($b, ':world map:', '🗺'); - Smilies::add($b, ':map of Japan:', '🗾'); - Smilies::add($b, ':compass:', '🧭'); + Smilies::add($b, ':globe showing Europe-Africa:', '🌍'); + Smilies::add($b, ':globe showing Americas:', '🌎'); + Smilies::add($b, ':globe showing Asia-Australia:', '🌏'); + Smilies::add($b, ':globe with meridians:', '🌐'); + Smilies::add($b, ':world map:', '🗺'); + Smilies::add($b, ':map of Japan:', '🗾'); + Smilies::add($b, ':compass:', '🧭'); // place-geographic - Smilies::add($b, ':snow-capped mountain:', '🏔'); - Smilies::add($b, ':mountain:', '⛰'); - Smilies::add($b, ':volcano:', '🌋'); - Smilies::add($b, ':mount fuji:', '🗻'); - Smilies::add($b, ':camping:', '🏕'); - Smilies::add($b, ':beach with umbrella:', '🏖'); - Smilies::add($b, ':desert:', '🏜'); - Smilies::add($b, ':desert island:', '🏝'); - Smilies::add($b, ':national park:', '🏞'); + Smilies::add($b, ':snow-capped mountain:', '🏔'); + Smilies::add($b, ':mountain:', '⛰'); + Smilies::add($b, ':volcano:', '🌋'); + Smilies::add($b, ':mount fuji:', '🗻'); + Smilies::add($b, ':camping:', '🏕'); + Smilies::add($b, ':beach with umbrella:', '🏖'); + Smilies::add($b, ':desert:', '🏜'); + Smilies::add($b, ':desert island:', '🏝'); + Smilies::add($b, ':national park:', '🏞'); // place-building - Smilies::add($b, ':stadium:', '🏟'); - Smilies::add($b, ':classical building:', '🏛'); - Smilies::add($b, ':building construction:', '🏗'); - Smilies::add($b, ':brick:', '🧱'); - Smilies::add($b, ':houses:', '🏘'); - Smilies::add($b, ':derelict house:', '🏚'); - Smilies::add($b, ':house:', '🏠'); - Smilies::add($b, ':house with garden:', '🏡'); - Smilies::add($b, ':office building:', '🏢'); - Smilies::add($b, ':Japanese post office:', '🏣'); - Smilies::add($b, ':post office:', '🏤'); - Smilies::add($b, ':hospital:', '🏥'); - Smilies::add($b, ':bank:', '🏦'); - Smilies::add($b, ':hotel:', '🏨'); - Smilies::add($b, ':love hotel:', '🏩'); - Smilies::add($b, ':convenience store:', '🏪'); - Smilies::add($b, ':school:', '🏫'); - Smilies::add($b, ':department store:', '🏬'); - Smilies::add($b, ':factory:', '🏭'); - Smilies::add($b, ':Japanese castle:', '🏯'); - Smilies::add($b, ':castle:', '🏰'); - Smilies::add($b, ':wedding:', '💒'); - Smilies::add($b, ':Tokyo tower:', '🗼'); - Smilies::add($b, ':Statue of Liberty:', '🗽'); - + Smilies::add($b, ':stadium:', '🏟'); + Smilies::add($b, ':classical building:', '🏛'); + Smilies::add($b, ':building construction:', '🏗'); + Smilies::add($b, ':brick:', '🧱'); + Smilies::add($b, ':houses:', '🏘'); + Smilies::add($b, ':derelict house:', '🏚'); + Smilies::add($b, ':house:', '🏠'); + Smilies::add($b, ':house with garden:', '🏡'); + Smilies::add($b, ':office building:', '🏢'); + Smilies::add($b, ':Japanese post office:', '🏣'); + Smilies::add($b, ':post office:', '🏤'); + Smilies::add($b, ':hospital:', '🏥'); + Smilies::add($b, ':bank:', '🏦'); + Smilies::add($b, ':hotel:', '🏨'); + Smilies::add($b, ':love hotel:', '🏩'); + Smilies::add($b, ':convenience store:', '🏪'); + Smilies::add($b, ':school:', '🏫'); + Smilies::add($b, ':department store:', '🏬'); + Smilies::add($b, ':factory:', '🏭'); + Smilies::add($b, ':Japanese castle:', '🏯'); + Smilies::add($b, ':castle:', '🏰'); + Smilies::add($b, ':wedding:', '💒'); + Smilies::add($b, ':Tokyo tower:', '🗼'); + Smilies::add($b, ':Statue of Liberty:', '🗽'); // place-religious - Smilies::add($b, ':church:', '⛪'); - Smilies::add($b, ':mosque:', '🕌'); -// Smilies::add($b, ':hindu temple:', '🛕'); - Smilies::add($b, ':synagogue:', '🕍'); - Smilies::add($b, ':shinto shrine:', '⛩'); - Smilies::add($b, ':kaaba:', '🕋'); + Smilies::add($b, ':church:', '⛪'); + Smilies::add($b, ':mosque:', '🕌'); +// Smilies::add($b, ':hindu temple:', '🛕'); + Smilies::add($b, ':synagogue:', '🕍'); + Smilies::add($b, ':shinto shrine:', '⛩'); + Smilies::add($b, ':kaaba:', '🕋'); // place-other - Smilies::add($b, ':fountain:', '⛲'); - Smilies::add($b, ':tent:', '⛺'); - Smilies::add($b, ':foggy:', '🌁'); - Smilies::add($b, ':night with stars:', '🌃'); - Smilies::add($b, ':cityscape:', '🏙'); - Smilies::add($b, ':sunrise over mountains:', '🌄'); - Smilies::add($b, ':sunrise:', '🌅'); - Smilies::add($b, ':cityscape at dusk:', '🌆'); - Smilies::add($b, ':sunset:', '🌇'); - Smilies::add($b, ':bridge at night:', '🌉'); - Smilies::add($b, ':hot springs:', '♨'); - Smilies::add($b, ':carousel horse:', '🎠'); - Smilies::add($b, ':ferris wheel:', '🎡'); - Smilies::add($b, ':roller coaster:', '🎢'); - Smilies::add($b, ':barber pole:', '💈'); - Smilies::add($b, ':circus tent:', '🎪'); + Smilies::add($b, ':fountain:', '⛲'); + Smilies::add($b, ':tent:', '⛺'); + Smilies::add($b, ':foggy:', '🌁'); + Smilies::add($b, ':night with stars:', '🌃'); + Smilies::add($b, ':cityscape:', '🏙'); + Smilies::add($b, ':sunrise over mountains:', '🌄'); + Smilies::add($b, ':sunrise:', '🌅'); + Smilies::add($b, ':cityscape at dusk:', '🌆'); + Smilies::add($b, ':sunset:', '🌇'); + Smilies::add($b, ':bridge at night:', '🌉'); + Smilies::add($b, ':hot springs:', '♨'); + Smilies::add($b, ':carousel horse:', '🎠'); + Smilies::add($b, ':ferris wheel:', '🎡'); + Smilies::add($b, ':roller coaster:', '🎢'); + Smilies::add($b, ':barber pole:', '💈'); + Smilies::add($b, ':circus tent:', '🎪'); // transport-ground - Smilies::add($b, ':locomotive:', '🚂'); - Smilies::add($b, ':railway car:', '🚃'); - Smilies::add($b, ':high-speed train:', '🚄'); - Smilies::add($b, ':bullet train:', '🚅'); - Smilies::add($b, ':train:', '🚆'); - Smilies::add($b, ':metro:', '🚇'); - Smilies::add($b, ':light rail:', '🚈'); - Smilies::add($b, ':station:', '🚉'); - Smilies::add($b, ':tram:', '🚊'); - Smilies::add($b, ':monorail:', '🚝'); - Smilies::add($b, ':mountain railway:', '🚞'); - Smilies::add($b, ':tram car:', '🚋'); - Smilies::add($b, ':bus:', '🚌'); - Smilies::add($b, ':oncoming bus:', '🚍'); - Smilies::add($b, ':trolleybus:', '🚎'); - Smilies::add($b, ':minibus:', '🚐'); - Smilies::add($b, ':ambulance:', '🚑'); - Smilies::add($b, ':fire engine:', '🚒'); - Smilies::add($b, ':police car:', '🚓'); - Smilies::add($b, ':oncoming police car:', '🚔'); - Smilies::add($b, ':taxi:', '🚕'); - Smilies::add($b, ':oncoming taxi:', '🚖'); - Smilies::add($b, ':automobile:', '🚗'); - Smilies::add($b, ':oncoming automobile:', '🚘'); - Smilies::add($b, ':sport utility vehicle:', '🚙'); - Smilies::add($b, ':delivery truck:', '🚚'); - Smilies::add($b, ':articulated lorry:', '🚛'); - Smilies::add($b, ':tractor:', '🚜'); - Smilies::add($b, ':racing car:', '🏎'); - Smilies::add($b, ':motorcycle:', '🏍'); - Smilies::add($b, ':motor scooter:', '🛵'); -// Smilies::add($b, ':manual wheelchair:', '🦽'); -// Smilies::add($b, ':motorized wheelchair:', '🦼'); -// Smilies::add($b, ':auto rickshaw:', '🛺'); - Smilies::add($b, ':bicycle:', '🚲'); - Smilies::add($b, ':kick scooter:', '🛴'); - Smilies::add($b, ':skateboard:', '🛹'); - Smilies::add($b, ':bus stop:', '🚏'); - Smilies::add($b, ':motorway:', '🛣'); - Smilies::add($b, ':railway track:', '🛤'); - Smilies::add($b, ':oil drum:', '🛢'); - Smilies::add($b, ':fuel pump:', '⛽'); - Smilies::add($b, ':police car light:', '🚨'); - Smilies::add($b, ':horizontal traffic light:', '🚥'); - Smilies::add($b, ':vertical traffic light:', '🚦'); - Smilies::add($b, ':stop sign:', '🛑'); - Smilies::add($b, ':construction:', '🚧'); + Smilies::add($b, ':locomotive:', '🚂'); + Smilies::add($b, ':railway car:', '🚃'); + Smilies::add($b, ':high-speed train:', '🚄'); + Smilies::add($b, ':bullet train:', '🚅'); + Smilies::add($b, ':train:', '🚆'); + Smilies::add($b, ':metro:', '🚇'); + Smilies::add($b, ':light rail:', '🚈'); + Smilies::add($b, ':station:', '🚉'); + Smilies::add($b, ':tram:', '🚊'); + Smilies::add($b, ':monorail:', '🚝'); + Smilies::add($b, ':mountain railway:', '🚞'); + Smilies::add($b, ':tram car:', '🚋'); + Smilies::add($b, ':bus:', '🚌'); + Smilies::add($b, ':oncoming bus:', '🚍'); + Smilies::add($b, ':trolleybus:', '🚎'); + Smilies::add($b, ':minibus:', '🚐'); + Smilies::add($b, ':ambulance:', '🚑'); + Smilies::add($b, ':fire engine:', '🚒'); + Smilies::add($b, ':police car:', '🚓'); + Smilies::add($b, ':oncoming police car:', '🚔'); + Smilies::add($b, ':taxi:', '🚕'); + Smilies::add($b, ':oncoming taxi:', '🚖'); + Smilies::add($b, ':automobile:', '🚗'); + Smilies::add($b, ':oncoming automobile:', '🚘'); + Smilies::add($b, ':sport utility vehicle:', '🚙'); + Smilies::add($b, ':delivery truck:', '🚚'); + Smilies::add($b, ':articulated lorry:', '🚛'); + Smilies::add($b, ':tractor:', '🚜'); + Smilies::add($b, ':racing car:', '🏎'); + Smilies::add($b, ':motorcycle:', '🏍'); + Smilies::add($b, ':motor scooter:', '🛵'); +// Smilies::add($b, ':manual wheelchair:', '🦽'); +// Smilies::add($b, ':motorized wheelchair:', '🦼'); +// Smilies::add($b, ':auto rickshaw:', '🛺'); + Smilies::add($b, ':bicycle:', '🚲'); + Smilies::add($b, ':kick scooter:', '🛴'); + Smilies::add($b, ':skateboard:', '🛹'); + Smilies::add($b, ':bus stop:', '🚏'); + Smilies::add($b, ':motorway:', '🛣'); + Smilies::add($b, ':railway track:', '🛤'); + Smilies::add($b, ':oil drum:', '🛢'); + Smilies::add($b, ':fuel pump:', '⛽'); + Smilies::add($b, ':police car light:', '🚨'); + Smilies::add($b, ':horizontal traffic light:', '🚥'); + Smilies::add($b, ':vertical traffic light:', '🚦'); + Smilies::add($b, ':stop sign:', '🛑'); + Smilies::add($b, ':construction:', '🚧'); // transport-water - Smilies::add($b, ':anchor:', '⚓'); - Smilies::add($b, ':sailboat:', '⛵'); - Smilies::add($b, ':canoe:', '🛶'); - Smilies::add($b, ':speedboat:', '🚤'); - Smilies::add($b, ':passenger ship:', '🛳'); - Smilies::add($b, ':ferry:', '⛴'); - Smilies::add($b, ':motor boat:', '🛥'); - Smilies::add($b, ':ship:', '🚢'); + Smilies::add($b, ':anchor:', '⚓'); + Smilies::add($b, ':sailboat:', '⛵'); + Smilies::add($b, ':canoe:', '🛶'); + Smilies::add($b, ':speedboat:', '🚤'); + Smilies::add($b, ':passenger ship:', '🛳'); + Smilies::add($b, ':ferry:', '⛴'); + Smilies::add($b, ':motor boat:', '🛥'); + Smilies::add($b, ':ship:', '🚢'); // transport-air - Smilies::add($b, ':airplane:', '✈'); - Smilies::add($b, ':small airplane:', '🛩'); - Smilies::add($b, ':airplane departure:', '🛫'); - Smilies::add($b, ':airplane arrival:', '🛬'); - Smilies::add($b, ':parachute:', '🪂'); - Smilies::add($b, ':seat:', '💺'); - Smilies::add($b, ':helicopter:', '🚁'); - Smilies::add($b, ':suspension railway:', '🚟'); - Smilies::add($b, ':mountain cableway:', '🚠'); - Smilies::add($b, ':aerial tramway:', '🚡'); - Smilies::add($b, ':satellite:', '🛰'); - Smilies::add($b, ':rocket:', '🚀'); - Smilies::add($b, ':flying saucer:', '🛸'); + Smilies::add($b, ':airplane:', '✈'); + Smilies::add($b, ':small airplane:', '🛩'); + Smilies::add($b, ':airplane departure:', '🛫'); + Smilies::add($b, ':airplane arrival:', '🛬'); + Smilies::add($b, ':parachute:', '🪂'); + Smilies::add($b, ':seat:', '💺'); + Smilies::add($b, ':helicopter:', '🚁'); + Smilies::add($b, ':suspension railway:', '🚟'); + Smilies::add($b, ':mountain cableway:', '🚠'); + Smilies::add($b, ':aerial tramway:', '🚡'); + Smilies::add($b, ':satellite:', '🛰'); + Smilies::add($b, ':rocket:', '🚀'); + Smilies::add($b, ':flying saucer:', '🛸'); // hotel - Smilies::add($b, ':bellhop bell:', '🛎'); - Smilies::add($b, ':luggage:', '🧳'); + Smilies::add($b, ':bellhop bell:', '🛎'); + Smilies::add($b, ':luggage:', '🧳'); // time - Smilies::add($b, ':hourglass done:', '⌛'); - Smilies::add($b, ':hourglass not done:', '⏳'); - Smilies::add($b, ':watch:', '⌚'); - Smilies::add($b, ':alarm clock:', '⏰'); - Smilies::add($b, ':stopwatch:', '⏱'); - Smilies::add($b, ':timer clock:', '⏲'); - Smilies::add($b, ':mantelpiece clock:', '🕰'); - Smilies::add($b, ':twelve o’clock:', '🕛'); - Smilies::add($b, ':twelve-thirty:', '🕧'); - Smilies::add($b, ':one o’clock:', '🕐'); - Smilies::add($b, ':one-thirty:', '🕜'); - Smilies::add($b, ':two o’clock:', '🕑'); - Smilies::add($b, ':two-thirty:', '🕝'); - Smilies::add($b, ':three o’clock:', '🕒'); - Smilies::add($b, ':three-thirty:', '🕞'); - Smilies::add($b, ':four o’clock:', '🕓'); - Smilies::add($b, ':four-thirty:', '🕟'); - Smilies::add($b, ':five o’clock:', '🕔'); - Smilies::add($b, ':five-thirty:', '🕠'); - Smilies::add($b, ':six o’clock:', '🕕'); - Smilies::add($b, ':six-thirty:', '🕡'); - Smilies::add($b, ':seven o’clock:', '🕖'); - Smilies::add($b, ':seven-thirty:', '🕢'); - Smilies::add($b, ':eight o’clock:', '🕗'); - Smilies::add($b, ':eight-thirty:', '🕣'); - Smilies::add($b, ':nine o’clock:', '🕘'); - Smilies::add($b, ':nine-thirty:', '🕤'); - Smilies::add($b, ':ten o’clock:', '🕙'); - Smilies::add($b, ':ten-thirty:', '🕥'); - Smilies::add($b, ':eleven o’clock:', '🕚'); - Smilies::add($b, ':eleven-thirty:', '🕦'); + Smilies::add($b, ':hourglass done:', '⌛'); + Smilies::add($b, ':hourglass not done:', '⏳'); + Smilies::add($b, ':watch:', '⌚'); + Smilies::add($b, ':alarm clock:', '⏰'); + Smilies::add($b, ':stopwatch:', '⏱'); + Smilies::add($b, ':timer clock:', '⏲'); + Smilies::add($b, ':mantelpiece clock:', '🕰'); + Smilies::add($b, ':twelve o’clock:', '🕛'); + Smilies::add($b, ':twelve-thirty:', '🕧'); + Smilies::add($b, ':one o’clock:', '🕐'); + Smilies::add($b, ':one-thirty:', '🕜'); + Smilies::add($b, ':two o’clock:', '🕑'); + Smilies::add($b, ':two-thirty:', '🕝'); + Smilies::add($b, ':three o’clock:', '🕒'); + Smilies::add($b, ':three-thirty:', '🕞'); + Smilies::add($b, ':four o’clock:', '🕓'); + Smilies::add($b, ':four-thirty:', '🕟'); + Smilies::add($b, ':five o’clock:', '🕔'); + Smilies::add($b, ':five-thirty:', '🕠'); + Smilies::add($b, ':six o’clock:', '🕕'); + Smilies::add($b, ':six-thirty:', '🕡'); + Smilies::add($b, ':seven o’clock:', '🕖'); + Smilies::add($b, ':seven-thirty:', '🕢'); + Smilies::add($b, ':eight o’clock:', '🕗'); + Smilies::add($b, ':eight-thirty:', '🕣'); + Smilies::add($b, ':nine o’clock:', '🕘'); + Smilies::add($b, ':nine-thirty:', '🕤'); + Smilies::add($b, ':ten o’clock:', '🕙'); + Smilies::add($b, ':ten-thirty:', '🕥'); + Smilies::add($b, ':eleven o’clock:', '🕚'); + Smilies::add($b, ':eleven-thirty:', '🕦'); // sky & weather - Smilies::add($b, ':new moon:', '🌑'); - Smilies::add($b, ':waxing crescent moon:', '🌒'); - Smilies::add($b, ':first quarter moon:', '🌓'); - Smilies::add($b, ':waxing gibbous moon:', '🌔'); - Smilies::add($b, ':full moon:', '🌕'); - Smilies::add($b, ':waning gibbous moon:', '🌖'); - Smilies::add($b, ':last quarter moon:', '🌗'); - Smilies::add($b, ':waning crescent moon:', '🌘'); - Smilies::add($b, ':crescent moon:', '🌙'); - Smilies::add($b, ':new moon face:', '🌚'); - Smilies::add($b, ':first quarter moon face:', '🌛'); - Smilies::add($b, ':last quarter moon face:', '🌜'); - Smilies::add($b, ':thermometer:', '🌡'); - Smilies::add($b, ':sun:', '☀'); - Smilies::add($b, ':full moon face:', '🌝'); - Smilies::add($b, ':sun with face:', '🌞'); - Smilies::add($b, ':ringed planet:', '🪐'); - Smilies::add($b, ':star:', '⭐'); - Smilies::add($b, ':glowing star:', '🌟'); - Smilies::add($b, ':shooting star:', '🌠'); - Smilies::add($b, ':milky way:', '🌌'); - Smilies::add($b, ':cloud:', '☁'); - Smilies::add($b, ':sun behind cloud:', '⛅'); - Smilies::add($b, ':cloud with lightning and rain:', '⛈'); - Smilies::add($b, ':sun behind small cloud:', '🌤'); - Smilies::add($b, ':sun behind large cloud:', '🌥'); - Smilies::add($b, ':sun behind rain cloud:', '🌦'); - Smilies::add($b, ':cloud with rain:', '🌧'); - Smilies::add($b, ':cloud with snow:', '🌨'); - Smilies::add($b, ':cloud with lightning:', '🌩'); - Smilies::add($b, ':tornado:', '🌪'); - Smilies::add($b, ':fog:', '🌫'); - Smilies::add($b, ':wind face:', '🌬'); - Smilies::add($b, ':cyclone:', '🌀'); - Smilies::add($b, ':rainbow:', '🌈'); - Smilies::add($b, ':closed umbrella:', '🌂'); - Smilies::add($b, ':umbrella:', '☂'); - Smilies::add($b, ':umbrella with rain drops:', '☔'); - Smilies::add($b, ':umbrella on ground:', '⛱'); - Smilies::add($b, ':high voltage:', '⚡'); - Smilies::add($b, ':snowflake:', '❄'); - Smilies::add($b, ':snowman:', '☃'); - Smilies::add($b, ':snowman without snow:', '⛄'); - Smilies::add($b, ':comet:', '☄'); - Smilies::add($b, ':fire:', '🔥'); - Smilies::add($b, ':droplet:', '💧'); - Smilies::add($b, ':water wave:', '🌊'); + Smilies::add($b, ':new moon:', '🌑'); + Smilies::add($b, ':waxing crescent moon:', '🌒'); + Smilies::add($b, ':first quarter moon:', '🌓'); + Smilies::add($b, ':waxing gibbous moon:', '🌔'); + Smilies::add($b, ':full moon:', '🌕'); + Smilies::add($b, ':waning gibbous moon:', '🌖'); + Smilies::add($b, ':last quarter moon:', '🌗'); + Smilies::add($b, ':waning crescent moon:', '🌘'); + Smilies::add($b, ':crescent moon:', '🌙'); + Smilies::add($b, ':new moon face:', '🌚'); + Smilies::add($b, ':first quarter moon face:', '🌛'); + Smilies::add($b, ':last quarter moon face:', '🌜'); + Smilies::add($b, ':thermometer:', '🌡'); + Smilies::add($b, ':sun:', '☀'); + Smilies::add($b, ':full moon face:', '🌝'); + Smilies::add($b, ':sun with face:', '🌞'); + Smilies::add($b, ':ringed planet:', '🪐'); + Smilies::add($b, ':star:', '⭐'); + Smilies::add($b, ':glowing star:', '🌟'); + Smilies::add($b, ':shooting star:', '🌠'); + Smilies::add($b, ':milky way:', '🌌'); + Smilies::add($b, ':cloud:', '☁'); + Smilies::add($b, ':sun behind cloud:', '⛅'); + Smilies::add($b, ':cloud with lightning and rain:', '⛈'); + Smilies::add($b, ':sun behind small cloud:', '🌤'); + Smilies::add($b, ':sun behind large cloud:', '🌥'); + Smilies::add($b, ':sun behind rain cloud:', '🌦'); + Smilies::add($b, ':cloud with rain:', '🌧'); + Smilies::add($b, ':cloud with snow:', '🌨'); + Smilies::add($b, ':cloud with lightning:', '🌩'); + Smilies::add($b, ':tornado:', '🌪'); + Smilies::add($b, ':fog:', '🌫'); + Smilies::add($b, ':wind face:', '🌬'); + Smilies::add($b, ':cyclone:', '🌀'); + Smilies::add($b, ':rainbow:', '🌈'); + Smilies::add($b, ':closed umbrella:', '🌂'); + Smilies::add($b, ':umbrella:', '☂'); + Smilies::add($b, ':umbrella with rain drops:', '☔'); + Smilies::add($b, ':umbrella on ground:', '⛱'); + Smilies::add($b, ':high voltage:', '⚡'); + Smilies::add($b, ':snowflake:', '❄'); + Smilies::add($b, ':snowman:', '☃'); + Smilies::add($b, ':snowman without snow:', '⛄'); + Smilies::add($b, ':comet:', '☄'); + Smilies::add($b, ':fire:', '🔥'); + Smilies::add($b, ':droplet:', '💧'); + Smilies::add($b, ':water wave:', '🌊'); // Activities // event - Smilies::add($b, ':jack-o-lantern:', '🎃'); - Smilies::add($b, ':Christmas tree:', '🎄'); - Smilies::add($b, ':fireworks:', '🎆'); - Smilies::add($b, ':sparkler:', '🎇'); - Smilies::add($b, ':firecracker:', '🧨'); - Smilies::add($b, ':sparkles:', '✨'); - Smilies::add($b, ':balloon:', '🎈'); - Smilies::add($b, ':party popper:', '🎉'); - Smilies::add($b, ':confetti ball:', '🎊'); - Smilies::add($b, ':tanabata tree:', '🎋'); - Smilies::add($b, ':pine decoration:', '🎍'); - Smilies::add($b, ':Japanese dolls:', '🎎'); - Smilies::add($b, ':carp streamer:', '🎏'); - Smilies::add($b, ':wind chime:', '🎐'); - Smilies::add($b, ':moon viewing ceremony:', '🎑'); - Smilies::add($b, ':red envelope:', '🧧'); - Smilies::add($b, ':ribbon:', '🎀'); - Smilies::add($b, ':wrapped gift:', '🎁'); - Smilies::add($b, ':reminder ribbon:', '🎗'); - Smilies::add($b, ':admission tickets:', '🎟'); - Smilies::add($b, ':ticket:', '🎫'); + Smilies::add($b, ':jack-o-lantern:', '🎃'); + Smilies::add($b, ':Christmas tree:', '🎄'); + Smilies::add($b, ':fireworks:', '🎆'); + Smilies::add($b, ':sparkler:', '🎇'); + Smilies::add($b, ':firecracker:', '🧨'); + Smilies::add($b, ':sparkles:', '✨'); + Smilies::add($b, ':balloon:', '🎈'); + Smilies::add($b, ':party popper:', '🎉'); + Smilies::add($b, ':confetti ball:', '🎊'); + Smilies::add($b, ':tanabata tree:', '🎋'); + Smilies::add($b, ':pine decoration:', '🎍'); + Smilies::add($b, ':Japanese dolls:', '🎎'); + Smilies::add($b, ':carp streamer:', '🎏'); + Smilies::add($b, ':wind chime:', '🎐'); + Smilies::add($b, ':moon viewing ceremony:', '🎑'); + Smilies::add($b, ':red envelope:', '🧧'); + Smilies::add($b, ':ribbon:', '🎀'); + Smilies::add($b, ':wrapped gift:', '🎁'); + Smilies::add($b, ':reminder ribbon:', '🎗'); + Smilies::add($b, ':admission tickets:', '🎟'); + Smilies::add($b, ':ticket:', '🎫'); // award-medal - Smilies::add($b, ':military medal:', '🎖'); - Smilies::add($b, ':trophy:', '🏆'); - Smilies::add($b, ':sports medal:', '🏅'); - Smilies::add($b, ':1st place medal:', '🥇'); - Smilies::add($b, ':2nd place medal:', '🥈'); - Smilies::add($b, ':3rd place medal:', '🥉'); + Smilies::add($b, ':military medal:', '🎖'); + Smilies::add($b, ':trophy:', '🏆'); + Smilies::add($b, ':sports medal:', '🏅'); + Smilies::add($b, ':1st place medal:', '🥇'); + Smilies::add($b, ':2nd place medal:', '🥈'); + Smilies::add($b, ':3rd place medal:', '🥉'); // sport - Smilies::add($b, ':soccer ball:', '⚽'); - Smilies::add($b, ':baseball:', '⚾'); - Smilies::add($b, ':softball:', '🥎'); - Smilies::add($b, ':basketball:', '🏀'); - Smilies::add($b, ':volleyball:', '🏐'); - Smilies::add($b, ':american football:', '🏈'); + Smilies::add($b, ':soccer ball:', '⚽'); + Smilies::add($b, ':baseball:', '⚾'); + Smilies::add($b, ':softball:', '🥎'); + Smilies::add($b, ':basketball:', '🏀'); + Smilies::add($b, ':volleyball:', '🏐'); + Smilies::add($b, ':american football:', '🏈'); Smilies::add($b, ':football:', '🏈'); - Smilies::add($b, ':rugby football:', '🏉'); - Smilies::add($b, ':tennis:', '🎾'); - Smilies::add($b, ':flying disc:', '🥏'); - Smilies::add($b, ':bowling:', '🎳'); - Smilies::add($b, ':cricket game:', '🏏'); - Smilies::add($b, ':field hockey:', '🏑'); - Smilies::add($b, ':ice hockey:', '🏒'); - Smilies::add($b, ':lacrosse:', '🥍'); - Smilies::add($b, ':ping pong:', '🏓'); - Smilies::add($b, ':badminton:', '🏸'); - Smilies::add($b, ':boxing glove:', '🥊'); - Smilies::add($b, ':martial arts uniform:', '🥋'); - Smilies::add($b, ':goal net:', '🥅'); - Smilies::add($b, ':flag in hole:', '⛳'); - Smilies::add($b, ':ice skate:', '⛸'); - Smilies::add($b, ':fishing pole:', '🎣'); -// Smilies::add($b, ':diving mask:', '🤿'); - Smilies::add($b, ':running shirt:', '🎽'); - Smilies::add($b, ':skis:', '🎿'); - Smilies::add($b, ':sled:', '🛷'); - Smilies::add($b, ':curling stone:', '🥌'); + Smilies::add($b, ':rugby football:', '🏉'); + Smilies::add($b, ':tennis:', '🎾'); + Smilies::add($b, ':flying disc:', '🥏'); + Smilies::add($b, ':bowling:', '🎳'); + Smilies::add($b, ':cricket game:', '🏏'); + Smilies::add($b, ':field hockey:', '🏑'); + Smilies::add($b, ':ice hockey:', '🏒'); + Smilies::add($b, ':lacrosse:', '🥍'); + Smilies::add($b, ':ping pong:', '🏓'); + Smilies::add($b, ':badminton:', '🏸'); + Smilies::add($b, ':boxing glove:', '🥊'); + Smilies::add($b, ':martial arts uniform:', '🥋'); + Smilies::add($b, ':goal net:', '🥅'); + Smilies::add($b, ':flag in hole:', '⛳'); + Smilies::add($b, ':ice skate:', '⛸'); + Smilies::add($b, ':fishing pole:', '🎣'); +// Smilies::add($b, ':diving mask:', '🤿'); + Smilies::add($b, ':running shirt:', '🎽'); + Smilies::add($b, ':skis:', '🎿'); + Smilies::add($b, ':sled:', '🛷'); + Smilies::add($b, ':curling stone:', '🥌'); Smilies::add($b, ':cycling:', '🚴'); Smilies::add($b, ':darts:', '🎯'); Smilies::add($b, ':fencing:', '🤺'); Smilies::add($b, ':juggling:', '🤹'); -// Smilies::add($b, ':skipping:', '&#x;'); -// Smilies::add($b, ':archery:', '&#x;'); +// Smilies::add($b, ':skipping:', '&#x;'); +// Smilies::add($b, ':archery:', '&#x;'); Smilies::add($b, ':surfing:', '🏄'); Smilies::add($b, ':snooker:', '🎱'); Smilies::add($b, ':horseriding:', '🏇'); // game - Smilies::add($b, ':direct hit:', '🎯'); - Smilies::add($b, ':yo-yo:', '🪀'); - Smilies::add($b, ':kite:', '🪁'); - Smilies::add($b, ':pool 8 ball:', '🎱'); - Smilies::add($b, ':crystal ball:', '🔮'); - Smilies::add($b, ':nazar amulet:', '🧿'); - Smilies::add($b, ':video game:', '🎮'); - Smilies::add($b, ':joystick:', '🕹'); - Smilies::add($b, ':slot machine:', '🎰'); - Smilies::add($b, ':game die:', '🎲'); - Smilies::add($b, ':puzzle piece:', '🧩'); - Smilies::add($b, ':teddy bear:', '🧸'); - Smilies::add($b, ':spade suit:', '♠'); - Smilies::add($b, ':heart suit:', '♥'); - Smilies::add($b, ':diamond suit:', '♦'); - Smilies::add($b, ':club suit:', '♣'); - Smilies::add($b, ':chess pawn:', '♟'); - Smilies::add($b, ':joker:', '🃏'); - Smilies::add($b, ':mahjong red dragon:', '🀄'); - Smilies::add($b, ':flower playing cards:', '🎴'); + Smilies::add($b, ':direct hit:', '🎯'); + Smilies::add($b, ':yo-yo:', '🪀'); + Smilies::add($b, ':kite:', '🪁'); + Smilies::add($b, ':pool 8 ball:', '🎱'); + Smilies::add($b, ':crystal ball:', '🔮'); + Smilies::add($b, ':nazar amulet:', '🧿'); + Smilies::add($b, ':video game:', '🎮'); + Smilies::add($b, ':joystick:', '🕹'); + Smilies::add($b, ':slot machine:', '🎰'); + Smilies::add($b, ':game die:', '🎲'); + Smilies::add($b, ':puzzle piece:', '🧩'); + Smilies::add($b, ':teddy bear:', '🧸'); + Smilies::add($b, ':spade suit:', '♠'); + Smilies::add($b, ':heart suit:', '♥'); + Smilies::add($b, ':diamond suit:', '♦'); + Smilies::add($b, ':club suit:', '♣'); + Smilies::add($b, ':chess pawn:', '♟'); + Smilies::add($b, ':joker:', '🃏'); + Smilies::add($b, ':mahjong red dragon:', '🀄'); + Smilies::add($b, ':flower playing cards:', '🎴'); // arts & crafts - Smilies::add($b, ':performing arts:', '🎭'); - Smilies::add($b, ':framed picture:', '🖼'); - Smilies::add($b, ':artist palette:', '🎨'); - Smilies::add($b, ':thread:', '🧵'); - Smilies::add($b, ':yarn:', '🧶'); + Smilies::add($b, ':performing arts:', '🎭'); + Smilies::add($b, ':framed picture:', '🖼'); + Smilies::add($b, ':artist palette:', '🎨'); + Smilies::add($b, ':thread:', '🧵'); + Smilies::add($b, ':yarn:', '🧶'); // Objects // clothing - Smilies::add($b, ':glasses:', '👓'); - Smilies::add($b, ':sunglasses:', '🕶'); - Smilies::add($b, ':goggles:', '🥽'); - Smilies::add($b, ':lab coat:', '🥼'); - Smilies::add($b, ':safety vest:', '🦺'); - Smilies::add($b, ':necktie:', '👔'); - Smilies::add($b, ':t-shirt:', '👕'); - Smilies::add($b, ':jeans:', '👖'); - Smilies::add($b, ':scarf:', '🧣'); - Smilies::add($b, ':gloves:', '🧤'); - Smilies::add($b, ':coat:', '🧥'); - Smilies::add($b, ':socks:', '🧦'); - Smilies::add($b, ':dress:', '👗'); - Smilies::add($b, ':kimono:', '👘'); - Smilies::add($b, ':sari:', '🥻'); - Smilies::add($b, ':one-piece swimsuit:', '🩱'); - Smilies::add($b, ':briefs:', '🩲'); - Smilies::add($b, ':shorts:', '🩳'); - Smilies::add($b, ':bikini:', '👙'); - Smilies::add($b, ':woman’s clothes:', '👚'); - Smilies::add($b, ':purse:', '👛'); - Smilies::add($b, ':handbag:', '👜'); - Smilies::add($b, ':clutch bag:', '👝'); - Smilies::add($b, ':shopping bags:', '🛍'); - Smilies::add($b, ':backpack:', '🎒'); - Smilies::add($b, ':man’s shoe:', '👞'); - Smilies::add($b, ':running shoe:', '👟'); - Smilies::add($b, ':hiking boot:', '🥾'); - Smilies::add($b, ':flat shoe:', '🥿'); - Smilies::add($b, ':high-heeled shoe:', '👠'); - Smilies::add($b, ':woman’s sandal:', '👡'); -// Smilies::add($b, ':ballet shoes:', '🩰'); - Smilies::add($b, ':woman’s boot:', '👢'); - Smilies::add($b, ':crown:', '👑'); - Smilies::add($b, ':woman’s hat:', '👒'); - Smilies::add($b, ':top hat:', '🎩'); - Smilies::add($b, ':graduation cap:', '🎓'); - Smilies::add($b, ':billed cap:', '🧢'); - Smilies::add($b, ':rescue worker’s helmet:', '⛑'); - Smilies::add($b, ':prayer beads:', '📿'); - Smilies::add($b, ':lipstick:', '💄'); - Smilies::add($b, ':ring:', '💍'); - Smilies::add($b, ':gem stone:', '💎'); + Smilies::add($b, ':glasses:', '👓'); + Smilies::add($b, ':sunglasses:', '🕶'); + Smilies::add($b, ':goggles:', '🥽'); + Smilies::add($b, ':lab coat:', '🥼'); + Smilies::add($b, ':safety vest:', '🦺'); + Smilies::add($b, ':necktie:', '👔'); + Smilies::add($b, ':t-shirt:', '👕'); + Smilies::add($b, ':jeans:', '👖'); + Smilies::add($b, ':scarf:', '🧣'); + Smilies::add($b, ':gloves:', '🧤'); + Smilies::add($b, ':coat:', '🧥'); + Smilies::add($b, ':socks:', '🧦'); + Smilies::add($b, ':dress:', '👗'); + Smilies::add($b, ':kimono:', '👘'); + Smilies::add($b, ':sari:', '🥻'); + Smilies::add($b, ':one-piece swimsuit:', '🩱'); + Smilies::add($b, ':briefs:', '🩲'); + Smilies::add($b, ':shorts:', '🩳'); + Smilies::add($b, ':bikini:', '👙'); + Smilies::add($b, ':woman’s clothes:', '👚'); + Smilies::add($b, ':purse:', '👛'); + Smilies::add($b, ':handbag:', '👜'); + Smilies::add($b, ':clutch bag:', '👝'); + Smilies::add($b, ':shopping bags:', '🛍'); + Smilies::add($b, ':backpack:', '🎒'); + Smilies::add($b, ':man’s shoe:', '👞'); + Smilies::add($b, ':running shoe:', '👟'); + Smilies::add($b, ':hiking boot:', '🥾'); + Smilies::add($b, ':flat shoe:', '🥿'); + Smilies::add($b, ':high-heeled shoe:', '👠'); + Smilies::add($b, ':woman’s sandal:', '👡'); +// Smilies::add($b, ':ballet shoes:', '🩰'); + Smilies::add($b, ':woman’s boot:', '👢'); + Smilies::add($b, ':crown:', '👑'); + Smilies::add($b, ':woman’s hat:', '👒'); + Smilies::add($b, ':top hat:', '🎩'); + Smilies::add($b, ':graduation cap:', '🎓'); + Smilies::add($b, ':billed cap:', '🧢'); + Smilies::add($b, ':rescue worker’s helmet:', '⛑'); + Smilies::add($b, ':prayer beads:', '📿'); + Smilies::add($b, ':lipstick:', '💄'); + Smilies::add($b, ':ring:', '💍'); + Smilies::add($b, ':gem stone:', '💎'); // sound - Smilies::add($b, ':muted speaker:', '🔇'); - Smilies::add($b, ':speaker low volume:', '🔈'); - Smilies::add($b, ':speaker medium volume:', '🔉'); - Smilies::add($b, ':speaker high volume:', '🔊'); - Smilies::add($b, ':loudspeaker:', '📢'); - Smilies::add($b, ':megaphone:', '📣'); - Smilies::add($b, ':postal horn:', '📯'); - Smilies::add($b, ':bell:', '🔔'); - Smilies::add($b, ':bell with slash:', '🔕'); + Smilies::add($b, ':muted speaker:', '🔇'); + Smilies::add($b, ':speaker low volume:', '🔈'); + Smilies::add($b, ':speaker medium volume:', '🔉'); + Smilies::add($b, ':speaker high volume:', '🔊'); + Smilies::add($b, ':loudspeaker:', '📢'); + Smilies::add($b, ':megaphone:', '📣'); + Smilies::add($b, ':postal horn:', '📯'); + Smilies::add($b, ':bell:', '🔔'); + Smilies::add($b, ':bell with slash:', '🔕'); // musik - Smilies::add($b, ':musical score:', '🎼'); - Smilies::add($b, ':musical note:', '🎵'); - Smilies::add($b, ':musical notes:', '🎶'); - Smilies::add($b, ':studio microphone:', '🎙'); - Smilies::add($b, ':level slider:', '🎚'); - Smilies::add($b, ':control knobs:', '🎛'); - Smilies::add($b, ':microphone:', '🎤'); - Smilies::add($b, ':headphone:', '🎧'); - Smilies::add($b, ':radio:', '📻'); + Smilies::add($b, ':musical score:', '🎼'); + Smilies::add($b, ':musical note:', '🎵'); + Smilies::add($b, ':musical notes:', '🎶'); + Smilies::add($b, ':studio microphone:', '🎙'); + Smilies::add($b, ':level slider:', '🎚'); + Smilies::add($b, ':control knobs:', '🎛'); + Smilies::add($b, ':microphone:', '🎤'); + Smilies::add($b, ':headphone:', '🎧'); + Smilies::add($b, ':radio:', '📻'); // musical-instrument - Smilies::add($b, ':saxophone:', '🎷'); - Smilies::add($b, ':guitar:', '🎸'); - Smilies::add($b, ':musical keyboard:', '🎹'); - Smilies::add($b, ':trumpet:', '🎺'); - Smilies::add($b, ':violin:', '🎻'); -// Smilies::add($b, ':banjo:', '🪕'); - Smilies::add($b, ':drum:', '🥁'); + Smilies::add($b, ':saxophone:', '🎷'); + Smilies::add($b, ':guitar:', '🎸'); + Smilies::add($b, ':musical keyboard:', '🎹'); + Smilies::add($b, ':trumpet:', '🎺'); + Smilies::add($b, ':violin:', '🎻'); +// Smilies::add($b, ':banjo:', '🪕'); + Smilies::add($b, ':drum:', '🥁'); // phone - Smilies::add($b, ':mobile phone:', '📱'); - Smilies::add($b, ':mobile phone with arrow:', '📲'); - Smilies::add($b, ':telephone:', '☎'); - Smilies::add($b, ':telephone receiver:', '📞'); - Smilies::add($b, ':pager:', '📟'); - Smilies::add($b, ':fax machine:', '📠'); + Smilies::add($b, ':mobile phone:', '📱'); + Smilies::add($b, ':mobile phone with arrow:', '📲'); + Smilies::add($b, ':telephone:', '☎'); + Smilies::add($b, ':telephone receiver:', '📞'); + Smilies::add($b, ':pager:', '📟'); + Smilies::add($b, ':fax machine:', '📠'); // computer - Smilies::add($b, ':battery:', '🔋'); - Smilies::add($b, ':electric plug:', '🔌'); - Smilies::add($b, ':laptop:', '💻'); - Smilies::add($b, ':desktop computer:', '🖥'); - Smilies::add($b, ':printer:', '🖨'); - Smilies::add($b, ':keyboard:', '⌨'); - Smilies::add($b, ':computer mouse:', '🖱'); - Smilies::add($b, ':trackball:', '🖲'); - Smilies::add($b, ':computer disk:', '💽'); - Smilies::add($b, ':floppy disk:', '💾'); - Smilies::add($b, ':optical disk:', '💿'); - Smilies::add($b, ':dvd:', '📀'); - Smilies::add($b, ':abacus:', '🧮'); + Smilies::add($b, ':battery:', '🔋'); + Smilies::add($b, ':electric plug:', '🔌'); + Smilies::add($b, ':laptop:', '💻'); + Smilies::add($b, ':desktop computer:', '🖥'); + Smilies::add($b, ':printer:', '🖨'); + Smilies::add($b, ':keyboard:', '⌨'); + Smilies::add($b, ':computer mouse:', '🖱'); + Smilies::add($b, ':trackball:', '🖲'); + Smilies::add($b, ':computer disk:', '💽'); + Smilies::add($b, ':floppy disk:', '💾'); + Smilies::add($b, ':optical disk:', '💿'); + Smilies::add($b, ':dvd:', '📀'); + Smilies::add($b, ':abacus:', '🧮'); // light & video - Smilies::add($b, ':movie camera:', '🎥'); - Smilies::add($b, ':film frames:', '🎞'); - Smilies::add($b, ':film projector:', '📽'); - Smilies::add($b, ':clapper board:', '🎬'); - Smilies::add($b, ':television:', '📺'); - Smilies::add($b, ':camera:', '📷'); - Smilies::add($b, ':camera with flash:', '📸'); - Smilies::add($b, ':video camera:', '📹'); - Smilies::add($b, ':videocassette:', '📼'); - Smilies::add($b, ':magnifying glass tilted left:', '🔍'); - Smilies::add($b, ':magnifying glass tilted right:', '🔎'); - Smilies::add($b, ':candle:', '🕯'); - Smilies::add($b, ':light bulb:', '💡'); - Smilies::add($b, ':flashlight:', '🔦'); - Smilies::add($b, ':red paper lantern:', '🏮'); -// Smilies::add($b, ':diya lamp:', '🪔'); + Smilies::add($b, ':movie camera:', '🎥'); + Smilies::add($b, ':film frames:', '🎞'); + Smilies::add($b, ':film projector:', '📽'); + Smilies::add($b, ':clapper board:', '🎬'); + Smilies::add($b, ':television:', '📺'); + Smilies::add($b, ':camera:', '📷'); + Smilies::add($b, ':camera with flash:', '📸'); + Smilies::add($b, ':video camera:', '📹'); + Smilies::add($b, ':videocassette:', '📼'); + Smilies::add($b, ':magnifying glass tilted left:', '🔍'); + Smilies::add($b, ':magnifying glass tilted right:', '🔎'); + Smilies::add($b, ':candle:', '🕯'); + Smilies::add($b, ':light bulb:', '💡'); + Smilies::add($b, ':flashlight:', '🔦'); + Smilies::add($b, ':red paper lantern:', '🏮'); +// Smilies::add($b, ':diya lamp:', '🪔'); // book-paper - Smilies::add($b, ':notebook with decorative cover:', '📔'); - Smilies::add($b, ':closed book:', '📕'); - Smilies::add($b, ':open book:', '📖'); - Smilies::add($b, ':green book:', '📗'); - Smilies::add($b, ':blue book:', '📘'); - Smilies::add($b, ':orange book:', '📙'); - Smilies::add($b, ':books:', '📚'); - Smilies::add($b, ':notebook:', '📓'); - Smilies::add($b, ':ledger:', '📒'); - Smilies::add($b, ':page with curl:', '📃'); - Smilies::add($b, ':scroll:', '📜'); - Smilies::add($b, ':page facing up:', '📄'); - Smilies::add($b, ':newspaper:', '📰'); - Smilies::add($b, ':rolled-up newspaper:', '🗞'); - Smilies::add($b, ':bookmark tabs:', '📑'); - Smilies::add($b, ':bookmark:', '🔖'); - Smilies::add($b, ':label:', '🏷'); + Smilies::add($b, ':notebook with decorative cover:', '📔'); + Smilies::add($b, ':closed book:', '📕'); + Smilies::add($b, ':open book:', '📖'); + Smilies::add($b, ':green book:', '📗'); + Smilies::add($b, ':blue book:', '📘'); + Smilies::add($b, ':orange book:', '📙'); + Smilies::add($b, ':books:', '📚'); + Smilies::add($b, ':notebook:', '📓'); + Smilies::add($b, ':ledger:', '📒'); + Smilies::add($b, ':page with curl:', '📃'); + Smilies::add($b, ':scroll:', '📜'); + Smilies::add($b, ':page facing up:', '📄'); + Smilies::add($b, ':newspaper:', '📰'); + Smilies::add($b, ':rolled-up newspaper:', '🗞'); + Smilies::add($b, ':bookmark tabs:', '📑'); + Smilies::add($b, ':bookmark:', '🔖'); + Smilies::add($b, ':label:', '🏷'); // money - Smilies::add($b, ':money bag:', '💰'); - Smilies::add($b, ':yen banknote:', '💴'); - Smilies::add($b, ':dollar banknote:', '💵'); - Smilies::add($b, ':euro banknote:', '💶'); - Smilies::add($b, ':pound banknote:', '💷'); - Smilies::add($b, ':money with wings:', '💸'); - Smilies::add($b, ':credit card:', '💳'); - Smilies::add($b, ':receipt:', '🧾'); - Smilies::add($b, ':chart increasing with yen:', '💹'); + Smilies::add($b, ':money bag:', '💰'); + Smilies::add($b, ':yen banknote:', '💴'); + Smilies::add($b, ':dollar banknote:', '💵'); + Smilies::add($b, ':euro banknote:', '💶'); + Smilies::add($b, ':pound banknote:', '💷'); + Smilies::add($b, ':money with wings:', '💸'); + Smilies::add($b, ':credit card:', '💳'); + Smilies::add($b, ':receipt:', '🧾'); + Smilies::add($b, ':chart increasing with yen:', '💹'); // mail - Smilies::add($b, ':envelope:', '✉'); - Smilies::add($b, ':e-mail:', '📧'); - Smilies::add($b, ':incoming envelope:', '📨'); - Smilies::add($b, ':envelope with arrow:', '📩'); - Smilies::add($b, ':outbox tray:', '📤'); - Smilies::add($b, ':inbox tray:', '📥'); - Smilies::add($b, ':package:', '📦'); - Smilies::add($b, ':closed mailbox with raised flag:', '📫'); - Smilies::add($b, ':closed mailbox with lowered flag:', '📪'); - Smilies::add($b, ':open mailbox with raised flag:', '📬'); - Smilies::add($b, ':open mailbox with lowered flag:', '📭'); - Smilies::add($b, ':postbox:', '📮'); - Smilies::add($b, ':ballot box with ballot:', '🗳'); + Smilies::add($b, ':envelope:', '✉'); + Smilies::add($b, ':e-mail:', '📧'); + Smilies::add($b, ':incoming envelope:', '📨'); + Smilies::add($b, ':envelope with arrow:', '📩'); + Smilies::add($b, ':outbox tray:', '📤'); + Smilies::add($b, ':inbox tray:', '📥'); + Smilies::add($b, ':package:', '📦'); + Smilies::add($b, ':closed mailbox with raised flag:', '📫'); + Smilies::add($b, ':closed mailbox with lowered flag:', '📪'); + Smilies::add($b, ':open mailbox with raised flag:', '📬'); + Smilies::add($b, ':open mailbox with lowered flag:', '📭'); + Smilies::add($b, ':postbox:', '📮'); + Smilies::add($b, ':ballot box with ballot:', '🗳'); // writing - Smilies::add($b, ':pencil:', '✏'); - Smilies::add($b, ':black nib:', '✒'); - Smilies::add($b, ':fountain pen:', '🖋'); - Smilies::add($b, ':pen:', '🖊'); - Smilies::add($b, ':paintbrush:', '🖌'); - Smilies::add($b, ':crayon:', '🖍'); - Smilies::add($b, ':memo:', '📝'); + Smilies::add($b, ':pencil:', '✏'); + Smilies::add($b, ':black nib:', '✒'); + Smilies::add($b, ':fountain pen:', '🖋'); + Smilies::add($b, ':pen:', '🖊'); + Smilies::add($b, ':paintbrush:', '🖌'); + Smilies::add($b, ':crayon:', '🖍'); + Smilies::add($b, ':memo:', '📝'); // office - Smilies::add($b, ':briefcase:', '💼'); - Smilies::add($b, ':file folder:', '📁'); - Smilies::add($b, ':open file folder:', '📂'); - Smilies::add($b, ':card index dividers:', '🗂'); - Smilies::add($b, ':calendar:', '📅'); - Smilies::add($b, ':tear-off calendar:', '📆'); - Smilies::add($b, ':spiral notepad:', '🗒'); - Smilies::add($b, ':spiral calendar:', '🗓'); - Smilies::add($b, ':card index:', '📇'); - Smilies::add($b, ':chart increasing:', '📈'); - Smilies::add($b, ':chart decreasing:', '📉'); - Smilies::add($b, ':bar chart:', '📊'); - Smilies::add($b, ':clipboard:', '📋'); - Smilies::add($b, ':pushpin:', '📌'); - Smilies::add($b, ':round pushpin:', '📍'); - Smilies::add($b, ':paperclip:', '📎'); - Smilies::add($b, ':linked paperclips:', '🖇'); - Smilies::add($b, ':straight ruler:', '📏'); - Smilies::add($b, ':triangular ruler:', '📐'); - Smilies::add($b, ':scissors:', '✂'); - Smilies::add($b, ':card file box:', '🗃'); - Smilies::add($b, ':file cabinet:', '🗄'); - Smilies::add($b, ':wastebasket:', '🗑'); + Smilies::add($b, ':briefcase:', '💼'); + Smilies::add($b, ':file folder:', '📁'); + Smilies::add($b, ':open file folder:', '📂'); + Smilies::add($b, ':card index dividers:', '🗂'); + Smilies::add($b, ':calendar:', '📅'); + Smilies::add($b, ':tear-off calendar:', '📆'); + Smilies::add($b, ':spiral notepad:', '🗒'); + Smilies::add($b, ':spiral calendar:', '🗓'); + Smilies::add($b, ':card index:', '📇'); + Smilies::add($b, ':chart increasing:', '📈'); + Smilies::add($b, ':chart decreasing:', '📉'); + Smilies::add($b, ':bar chart:', '📊'); + Smilies::add($b, ':clipboard:', '📋'); + Smilies::add($b, ':pushpin:', '📌'); + Smilies::add($b, ':round pushpin:', '📍'); + Smilies::add($b, ':paperclip:', '📎'); + Smilies::add($b, ':linked paperclips:', '🖇'); + Smilies::add($b, ':straight ruler:', '📏'); + Smilies::add($b, ':triangular ruler:', '📐'); + Smilies::add($b, ':scissors:', '✂'); + Smilies::add($b, ':card file box:', '🗃'); + Smilies::add($b, ':file cabinet:', '🗄'); + Smilies::add($b, ':wastebasket:', '🗑'); // lock - Smilies::add($b, ':locked:', '🔒'); - Smilies::add($b, ':unlocked:', '🔓'); - Smilies::add($b, ':locked with pen:', '🔏'); - Smilies::add($b, ':locked with key:', '🔐'); - Smilies::add($b, ':key:', '🔑'); - Smilies::add($b, ':old key:', '🗝'); + Smilies::add($b, ':locked:', '🔒'); + Smilies::add($b, ':unlocked:', '🔓'); + Smilies::add($b, ':locked with pen:', '🔏'); + Smilies::add($b, ':locked with key:', '🔐'); + Smilies::add($b, ':key:', '🔑'); + Smilies::add($b, ':old key:', '🗝'); // tool - Smilies::add($b, ':hammer:', '🔨'); -// Smilies::add($b, ':axe:', '🪓'); - Smilies::add($b, ':pick:', '⛏'); - Smilies::add($b, ':hammer and pick:', '⚒'); - Smilies::add($b, ':hammer and wrench:', '🛠'); - Smilies::add($b, ':dagger:', '🗡'); + Smilies::add($b, ':hammer:', '🔨'); +// Smilies::add($b, ':axe:', '🪓'); + Smilies::add($b, ':pick:', '⛏'); + Smilies::add($b, ':hammer and pick:', '⚒'); + Smilies::add($b, ':hammer and wrench:', '🛠'); + Smilies::add($b, ':dagger:', '🗡'); Smilies::add($b, ':sabre:', '🗡'); - Smilies::add($b, ':crossed swords:', '⚔'); - Smilies::add($b, ':pistol:', '🔫'); - Smilies::add($b, ':bow and arrow:', '🏹'); - Smilies::add($b, ':shield:', '🛡'); - Smilies::add($b, ':wrench:', '🔧'); - Smilies::add($b, ':nut and bolt:', '🔩'); - Smilies::add($b, ':gear:', '⚙'); - Smilies::add($b, ':clamp:', '🗜'); - Smilies::add($b, ':balance scale:', '⚖'); - Smilies::add($b, ':white cane:', '🦯'); - Smilies::add($b, ':link:', '🔗'); - Smilies::add($b, ':chains:', '⛓'); - Smilies::add($b, ':toolbox:', '🧰'); - Smilies::add($b, ':magnet:', '🧲'); + Smilies::add($b, ':crossed swords:', '⚔'); + Smilies::add($b, ':pistol:', '🔫'); + Smilies::add($b, ':bow and arrow:', '🏹'); + Smilies::add($b, ':shield:', '🛡'); + Smilies::add($b, ':wrench:', '🔧'); + Smilies::add($b, ':nut and bolt:', '🔩'); + Smilies::add($b, ':gear:', '⚙'); + Smilies::add($b, ':clamp:', '🗜'); + Smilies::add($b, ':balance scale:', '⚖'); + Smilies::add($b, ':white cane:', '🦯'); + Smilies::add($b, ':link:', '🔗'); + Smilies::add($b, ':chains:', '⛓'); + Smilies::add($b, ':toolbox:', '🧰'); + Smilies::add($b, ':magnet:', '🧲'); // science - Smilies::add($b, ':alembic:', '⚗'); - Smilies::add($b, ':test tube:', '🧪'); - Smilies::add($b, ':petri dish:', '🧫'); - Smilies::add($b, ':dna:', '🧬'); - Smilies::add($b, ':microscope:', '🔬'); - Smilies::add($b, ':telescope:', '🔭'); - Smilies::add($b, ':satellite antenna:', '📡'); - Smilies::add($b, ':asterism:', '⁂'); - Smilies::add($b, ':outlines white star:', '⚝'); + Smilies::add($b, ':alembic:', '⚗'); + Smilies::add($b, ':test tube:', '🧪'); + Smilies::add($b, ':petri dish:', '🧫'); + Smilies::add($b, ':dna:', '🧬'); + Smilies::add($b, ':microscope:', '🔬'); + Smilies::add($b, ':telescope:', '🔭'); + Smilies::add($b, ':satellite antenna:', '📡'); + Smilies::add($b, ':asterism:', '⁂'); + Smilies::add($b, ':outlines white star:', '颅'); // medical - Smilies::add($b, ':syringe:', '💉'); - Smilies::add($b, ':drop of blood:', '🩸'); - Smilies::add($b, ':pill:', '💊'); - Smilies::add($b, ':adhesive bandage:', '🩹'); - Smilies::add($b, ':stethoscope:', '🩺'); + Smilies::add($b, ':syringe:', '💉'); + Smilies::add($b, ':drop of blood:', '🩸'); + Smilies::add($b, ':pill:', '💊'); + Smilies::add($b, ':adhesive bandage:', '🩹'); + Smilies::add($b, ':stethoscope:', '🩺'); // household - Smilies::add($b, ':door:', '🚪'); - Smilies::add($b, ':bed:', '🛏'); - Smilies::add($b, ':couch and lamp:', '🛋'); -// Smilies::add($b, ':chair:', '🪑'); - Smilies::add($b, ':toilet:', '🚽'); - Smilies::add($b, ':shower:', '🚿'); - Smilies::add($b, ':bathtub:', '🛁'); - Smilies::add($b, ':razor:', '🪒'); - Smilies::add($b, ':lotion bottle:', '🧴'); - Smilies::add($b, ':safety pin:', '🧷'); - Smilies::add($b, ':broom:', '🧹'); - Smilies::add($b, ':basket:', '🧺'); - Smilies::add($b, ':roll of paper:', '🧻'); - Smilies::add($b, ':soap:', '🧼'); - Smilies::add($b, ':sponge:', '🧽'); - Smilies::add($b, ':fire extinguisher:', '🧯'); - Smilies::add($b, ':shopping cart:', '🛒'); + Smilies::add($b, ':door:', '🚪'); + Smilies::add($b, ':bed:', '🛏'); + Smilies::add($b, ':couch and lamp:', '🛋'); +// Smilies::add($b, ':chair:', '🪑'); + Smilies::add($b, ':toilet:', '🚽'); + Smilies::add($b, ':shower:', '🚿'); + Smilies::add($b, ':bathtub:', '🛁'); + Smilies::add($b, ':razor:', '🪒'); + Smilies::add($b, ':lotion bottle:', '🧴'); + Smilies::add($b, ':safety pin:', '🧷'); + Smilies::add($b, ':broom:', '🧹'); + Smilies::add($b, ':basket:', '🧺'); + Smilies::add($b, ':roll of paper:', '🧻'); + Smilies::add($b, ':soap:', '🧼'); + Smilies::add($b, ':sponge:', '🧽'); + Smilies::add($b, ':fire extinguisher:', '🧯'); + Smilies::add($b, ':shopping cart:', '🛒'); // other-object - Smilies::add($b, ':cigarette:', '🚬'); - Smilies::add($b, ':coffin:', '⚰'); - Smilies::add($b, ':funeral urn:', '⚱'); - Smilies::add($b, ':moai:', '🗿'); + Smilies::add($b, ':cigarette:', '🚬'); + Smilies::add($b, ':coffin:', '⚰'); + Smilies::add($b, ':funeral urn:', '⚱'); + Smilies::add($b, ':moai:', '🗿'); // Symbols // transport-sign - Smilies::add($b, ':atm sign:', '🏧'); - Smilies::add($b, ':litter in bin sign:', '🚮'); - Smilies::add($b, ':potable water:', '🚰'); - Smilies::add($b, ':wheelchair symbol:', '♿'); - Smilies::add($b, ':men’s room:', '🚹'); - Smilies::add($b, ':women’s room:', '🚺'); - Smilies::add($b, ':restroom:', '🚻'); - Smilies::add($b, ':baby symbol:', '🚼'); - Smilies::add($b, ':water closet:', '🚾'); - Smilies::add($b, ':passport control:', '🛂'); - Smilies::add($b, ':customs:', '🛃'); - Smilies::add($b, ':baggage claim:', '🛄'); - Smilies::add($b, ':left luggage:', '🛅'); + Smilies::add($b, ':atm sign:', '🏧'); + Smilies::add($b, ':litter in bin sign:', '🚮'); + Smilies::add($b, ':potable water:', '🚰'); + Smilies::add($b, ':wheelchair symbol:', '♿'); + Smilies::add($b, ':men’s room:', '🚹'); + Smilies::add($b, ':women’s room:', '🚺'); + Smilies::add($b, ':restroom:', '🚻'); + Smilies::add($b, ':baby symbol:', '🚼'); + Smilies::add($b, ':water closet:', '🚾'); + Smilies::add($b, ':passport control:', '🛂'); + Smilies::add($b, ':customs:', '🛃'); + Smilies::add($b, ':baggage claim:', '🛄'); + Smilies::add($b, ':left luggage:', '🛅'); // warning - Smilies::add($b, ':warning:', '⚠'); - Smilies::add($b, ':children crossing:', '🚸'); - Smilies::add($b, ':no entry:', '⛔'); - Smilies::add($b, ':prohibited:', '🚫'); - Smilies::add($b, ':no bicycles:', '🚳'); - Smilies::add($b, ':no smoking:', '🚭'); - Smilies::add($b, ':no littering:', '🚯'); - Smilies::add($b, ':non-potable water:', '🚱'); - Smilies::add($b, ':no pedestrians:', '🚷'); - Smilies::add($b, ':no mobile phones:', '📵'); - Smilies::add($b, ':no one under eighteen:', '🔞'); - Smilies::add($b, ':radioactive:', '☢'); - Smilies::add($b, ':biohazard:', '☣'); + Smilies::add($b, ':warning:', '⚠'); + Smilies::add($b, ':children crossing:', '🚸'); + Smilies::add($b, ':no entry:', '⛔'); + Smilies::add($b, ':prohibited:', '🚫'); + Smilies::add($b, ':no bicycles:', '🚳'); + Smilies::add($b, ':no smoking:', '🚭'); + Smilies::add($b, ':no littering:', '🚯'); + Smilies::add($b, ':non-potable water:', '🚱'); + Smilies::add($b, ':no pedestrians:', '🚷'); + Smilies::add($b, ':no mobile phones:', '📵'); + Smilies::add($b, ':no one under eighteen:', '🔞'); + Smilies::add($b, ':radioactive:', '☢'); + Smilies::add($b, ':biohazard:', '☣'); Smilies::add($b, ':army:', '🪖'); // arrow - Smilies::add($b, ':up arrow:', '⬆'); - Smilies::add($b, ':up-right arrow:', '↗'); - Smilies::add($b, ':right arrow:', '➡'); - Smilies::add($b, ':down-right arrow:', '↘'); - Smilies::add($b, ':down arrow:', '⬇'); - Smilies::add($b, ':down-left arrow:', '↙'); - Smilies::add($b, ':left arrow:', '⬅'); - Smilies::add($b, ':up-left arrow:', '↖'); - Smilies::add($b, ':up-down arrow:', '↕'); - Smilies::add($b, ':left-right arrow:', '↔'); - Smilies::add($b, ':right arrow curving left:', '↩'); - Smilies::add($b, ':left arrow curving right:', '↪'); - Smilies::add($b, ':right arrow curving up:', '⤴'); - Smilies::add($b, ':right arrow curving down:', '⤵'); - Smilies::add($b, ':clockwise vertical arrows:', '🔃'); - Smilies::add($b, ':counterclockwise arrows button:', '🔄'); - Smilies::add($b, ':BACK arrow:', '🔙'); - Smilies::add($b, ':END arrow:', '🔚'); - Smilies::add($b, ':ON! arrow:', '🔛'); - Smilies::add($b, ':SOON arrow:', '🔜'); - Smilies::add($b, ':TOP arrow:', '🔝'); + Smilies::add($b, ':up arrow:', '⬆'); + Smilies::add($b, ':up-right arrow:', '↗'); + Smilies::add($b, ':right arrow:', '➡'); + Smilies::add($b, ':down-right arrow:', '↘'); + Smilies::add($b, ':down arrow:', '⬇'); + Smilies::add($b, ':down-left arrow:', '↙'); + Smilies::add($b, ':left arrow:', '⬅'); + Smilies::add($b, ':up-left arrow:', '↖'); + Smilies::add($b, ':up-down arrow:', '↕'); + Smilies::add($b, ':left-right arrow:', '↔'); + Smilies::add($b, ':right arrow curving left:', '↩'); + Smilies::add($b, ':left arrow curving right:', '↪'); + Smilies::add($b, ':right arrow curving up:', '⤴'); + Smilies::add($b, ':right arrow curving down:', '⤵'); + Smilies::add($b, ':clockwise vertical arrows:', '🔃'); + Smilies::add($b, ':counterclockwise arrows button:', '🔄'); + Smilies::add($b, ':BACK arrow:', '🔙'); + Smilies::add($b, ':END arrow:', '🔚'); + Smilies::add($b, ':ON! arrow:', '🔛'); + Smilies::add($b, ':SOON arrow:', '🔜'); + Smilies::add($b, ':TOP arrow:', '🔝'); // religion - Smilies::add($b, ':place of worship:', '🛐'); - Smilies::add($b, ':atom symbol:', '⚛'); - Smilies::add($b, ':om:', '🕉'); - Smilies::add($b, ':star of David:', '✡'); - Smilies::add($b, ':wheel of dharma:', '☸'); - Smilies::add($b, ':yin yang:', '☯'); - Smilies::add($b, ':latin cross:', '✝'); - Smilies::add($b, ':orthodox cross:', '☦'); - Smilies::add($b, ':star and crescent:', '☪'); - Smilies::add($b, ':peace symbol:', '☮'); - Smilies::add($b, ':menorah:', '🕎'); - Smilies::add($b, ':dotted six-pointed star:', '🔯'); + Smilies::add($b, ':place of worship:', '🛐'); + Smilies::add($b, ':atom symbol:', '⚛'); + Smilies::add($b, ':om:', '🕉'); + Smilies::add($b, ':star of David:', '✡'); + Smilies::add($b, ':wheel of dharma:', '☸'); + Smilies::add($b, ':yin yang:', '☯'); + Smilies::add($b, ':latin cross:', '✝'); + Smilies::add($b, ':orthodox cross:', '☦'); + Smilies::add($b, ':star and crescent:', '☪'); + Smilies::add($b, ':peace symbol:', '☮'); + Smilies::add($b, ':menorah:', '🕎'); + Smilies::add($b, ':dotted six-pointed star:', '🔯'); // zodiac - Smilies::add($b, ':Aries:', '♈'); - Smilies::add($b, ':Taurus:', '♉'); - Smilies::add($b, ':Gemini:', '♊'); - Smilies::add($b, ':Cancer:', '♋'); - Smilies::add($b, ':Leo:', '♌'); - Smilies::add($b, ':Virgo:', '♍'); - Smilies::add($b, ':Libra:', '♎'); - Smilies::add($b, ':Scorpio:', '♏'); - Smilies::add($b, ':Sagittarius:', '♐'); - Smilies::add($b, ':Capricorn:', '♑'); - Smilies::add($b, ':Aquarius:', '♒'); - Smilies::add($b, ':Pisces:', '♓'); - Smilies::add($b, ':Ophiuchus:', '⛎'); + Smilies::add($b, ':Aries:', '♈'); + Smilies::add($b, ':Taurus:', '♉'); + Smilies::add($b, ':Gemini:', '♊'); + Smilies::add($b, ':Cancer:', '♋'); + Smilies::add($b, ':Leo:', '♌'); + Smilies::add($b, ':Virgo:', '♍'); + Smilies::add($b, ':Libra:', '♎'); + Smilies::add($b, ':Scorpio:', '♏'); + Smilies::add($b, ':Sagittarius:', '♐'); + Smilies::add($b, ':Capricorn:', '♑'); + Smilies::add($b, ':Aquarius:', '♒'); + Smilies::add($b, ':Pisces:', '♓'); + Smilies::add($b, ':Ophiuchus:', '⛎'); // av-symbol - Smilies::add($b, ':shuffle tracks button:', '🔀'); - Smilies::add($b, ':repeat button:', '🔁'); - Smilies::add($b, ':repeat single button:', '🔂'); - Smilies::add($b, ':play button:', '▶'); - Smilies::add($b, ':fast-forward button:', '⏩'); - Smilies::add($b, ':next track button:', '⏭'); - Smilies::add($b, ':play or pause button:', '⏯'); - Smilies::add($b, ':reverse button:', '◀'); - Smilies::add($b, ':fast reverse button:', '⏪'); - Smilies::add($b, ':last track button:', '⏮'); - Smilies::add($b, ':upwards button:', '🔼'); - Smilies::add($b, ':fast up button:', '⏫'); - Smilies::add($b, ':downwards button:', '🔽'); - Smilies::add($b, ':fast down button:', '⏬'); - Smilies::add($b, ':pause button:', '⏸'); - Smilies::add($b, ':stop button:', '⏹'); - Smilies::add($b, ':record button:', '⏺'); - Smilies::add($b, ':eject button:', '⏏'); - Smilies::add($b, ':cinema:', '🎦'); - Smilies::add($b, ':dim button:', '🔅'); - Smilies::add($b, ':bright button:', '🔆'); - Smilies::add($b, ':antenna bars:', '📶'); - Smilies::add($b, ':vibration mode:', '📳'); - Smilies::add($b, ':mobile phone off:', '📴'); + Smilies::add($b, ':shuffle tracks button:', '🔀'); + Smilies::add($b, ':repeat button:', '🔁'); + Smilies::add($b, ':repeat single button:', '🔂'); + Smilies::add($b, ':play button:', '▶'); + Smilies::add($b, ':fast-forward button:', '⏩'); + Smilies::add($b, ':next track button:', '⏭'); + Smilies::add($b, ':play or pause button:', '⏯'); + Smilies::add($b, ':reverse button:', '◀'); + Smilies::add($b, ':fast reverse button:', '⏪'); + Smilies::add($b, ':last track button:', '⏮'); + Smilies::add($b, ':upwards button:', '🔼'); + Smilies::add($b, ':fast up button:', '⏫'); + Smilies::add($b, ':downwards button:', '🔽'); + Smilies::add($b, ':fast down button:', '⏬'); + Smilies::add($b, ':pause button:', '⏸'); + Smilies::add($b, ':stop button:', '⏹'); + Smilies::add($b, ':record button:', '⏺'); + Smilies::add($b, ':eject button:', '⏏'); + Smilies::add($b, ':cinema:', '🎦'); + Smilies::add($b, ':dim button:', '🔅'); + Smilies::add($b, ':bright button:', '🔆'); + Smilies::add($b, ':antenna bars:', '📶'); + Smilies::add($b, ':vibration mode:', '📳'); + Smilies::add($b, ':mobile phone off:', '📴'); // gender - Smilies::add($b, ':female sign:', '♀'); - Smilies::add($b, ':male sign:', '♂'); + Smilies::add($b, ':female sign:', '♀'); + Smilies::add($b, ':male sign:', '♂'); // math - Smilies::add($b, ':multiply:', '✖'); - Smilies::add($b, ':plus:', '➕'); - Smilies::add($b, ':minus:', '➖'); - Smilies::add($b, ':divide:', '➗'); - Smilies::add($b, ':infinity:', '♾'); + Smilies::add($b, ':multiply:', '✖'); + Smilies::add($b, ':plus:', '➕'); + Smilies::add($b, ':minus:', '➖'); + Smilies::add($b, ':divide:', '➗'); + Smilies::add($b, ':infinity:', '♾'); Smilies::add($b, ':kreisoperator:', '∘'); Smilies::add($b, ':leere menge:', '∅'); Smilies::add($b, ':rundung:', '≈'); @@ -1458,407 +1454,408 @@ function unicode_smilies_smilies(array &$b) Smilies::add($b, ':prozent:', '%'); // punctuation - Smilies::add($b, ':double exclamation mark:', '‼'); - Smilies::add($b, ':exclamation question mark:', '⁉'); - Smilies::add($b, ':question mark:', '❓'); - Smilies::add($b, ':white question mark:', '❔'); - Smilies::add($b, ':white exclamation mark:', '❕'); - Smilies::add($b, ':exclamation mark:', '❗'); - Smilies::add($b, ':wavy dash:', '〰'); + Smilies::add($b, ':double exclamation mark:', '‼'); + Smilies::add($b, ':exclamation question mark:', '⁉'); + Smilies::add($b, ':question mark:', '❓'); + Smilies::add($b, ':white question mark:', '❔'); + Smilies::add($b, ':white exclamation mark:', '❕'); + Smilies::add($b, ':exclamation mark:', '❗'); + Smilies::add($b, ':wavy dash:', '〰'); // currency - Smilies::add($b, ':currency exchange:', '💱'); - Smilies::add($b, ':heavy dollar sign:', '💲'); + Smilies::add($b, ':currency exchange:', '💱'); + Smilies::add($b, ':heavy dollar sign:', '💲'); // other-symbol - Smilies::add($b, ':medical symbol:', '⚕'); - Smilies::add($b, ':recycling symbol:', '♻'); - Smilies::add($b, ':fleur-de-lis:', '⚜'); - Smilies::add($b, ':trident emblem:', '🔱'); - Smilies::add($b, ':name badge:', '📛'); - Smilies::add($b, ':Japanese symbol for beginner:', '🔰'); - Smilies::add($b, ':hollow red circle:', '⭕'); - Smilies::add($b, ':check mark button:', '✅'); - Smilies::add($b, ':check box with check:', '☑'); - Smilies::add($b, ':check mark:', '✔'); - Smilies::add($b, ':cross mark:', '❌'); - Smilies::add($b, ':cross mark button:', '❎'); - Smilies::add($b, ':curly loop:', '➰'); - Smilies::add($b, ':double curly loop:', '➿'); - Smilies::add($b, ':part alternation mark:', '〽'); - Smilies::add($b, ':eight-spoked asterisk:', '✳'); - Smilies::add($b, ':eight-pointed star:', '✴'); - Smilies::add($b, ':sparkle:', '❇'); - Smilies::add($b, ':copyright:', '©'); - Smilies::add($b, ':registered:', '®'); - Smilies::add($b, ':trade mark:', '™'); + Smilies::add($b, ':medical symbol:', '⚕'); + Smilies::add($b, ':recycling symbol:', '♻'); + Smilies::add($b, ':fleur-de-lis:', '⚜'); + Smilies::add($b, ':trident emblem:', '🔱'); + Smilies::add($b, ':name badge:', '📛'); + Smilies::add($b, ':Japanese symbol for beginner:', '🔰'); + Smilies::add($b, ':hollow red circle:', '⭕'); + Smilies::add($b, ':check mark button:', '✅'); + Smilies::add($b, ':check box with check:', '☑'); + Smilies::add($b, ':check mark:', '✔'); + Smilies::add($b, ':cross mark:', '❌'); + Smilies::add($b, ':cross mark button:', '❎'); + Smilies::add($b, ':curly loop:', '➰'); + Smilies::add($b, ':double curly loop:', '➿'); + Smilies::add($b, ':part alternation mark:', '〽'); + Smilies::add($b, ':eight-spoked asterisk:', '✳'); + Smilies::add($b, ':eight-pointed star:', '✴'); + Smilies::add($b, ':sparkle:', '❇'); + Smilies::add($b, ':copyright:', '©'); + Smilies::add($b, ':registered:', '®'); + Smilies::add($b, ':trade mark:', '™'); // keycap - Smilies::add($b, ':keycap: #:', '#️⃣'); - Smilies::add($b, ':keycap: *:', '*️⃣'); - Smilies::add($b, ':keycap: 0:', '0️⃣'); - Smilies::add($b, ':keycap: 1:', '1️⃣'); - Smilies::add($b, ':keycap: 2:', '2️⃣'); - Smilies::add($b, ':keycap: 3:', '3️⃣'); - Smilies::add($b, ':keycap: 4:', '4️⃣'); - Smilies::add($b, ':keycap: 5:', '5️⃣'); - Smilies::add($b, ':keycap: 6:', '6️⃣'); - Smilies::add($b, ':keycap: 7:', '7️⃣'); - Smilies::add($b, ':keycap: 8:', '8️⃣'); - Smilies::add($b, ':keycap: 9:', '9️⃣'); - Smilies::add($b, ':keycap: 10:', '🔟'); + Smilies::add($b, ':keycap: #:', '#️⃣'); + Smilies::add($b, ':keycap: *:', '*️⃣'); + Smilies::add($b, ':keycap: 0:', '0️⃣'); + Smilies::add($b, ':keycap: 1:', '1️⃣'); + Smilies::add($b, ':keycap: 2:', '2️⃣'); + Smilies::add($b, ':keycap: 3:', '3️⃣'); + Smilies::add($b, ':keycap: 4:', '4️⃣'); + Smilies::add($b, ':keycap: 5:', '5️⃣'); + Smilies::add($b, ':keycap: 6:', '6️⃣'); + Smilies::add($b, ':keycap: 7:', '7️⃣'); + Smilies::add($b, ':keycap: 8:', '8️⃣'); + Smilies::add($b, ':keycap: 9:', '9️⃣'); + Smilies::add($b, ':keycap: 10:', '🔟'); // alphanum - Smilies::add($b, ':input latin uppercase:', '🔠'); - Smilies::add($b, ':input latin lowercase:', '🔡'); - Smilies::add($b, ':input numbers:', '🔢'); - Smilies::add($b, ':input symbols:', '🔣'); - Smilies::add($b, ':input latin letters:', '🔤'); - Smilies::add($b, ':A button (blood type):', '🅰'); - Smilies::add($b, ':AB button (blood type):', '🆎'); - Smilies::add($b, ':B button (blood type):', '🅱'); - Smilies::add($b, ':CL button:', '🆑'); - Smilies::add($b, ':COOL button:', '🆒'); + Smilies::add($b, ':input latin uppercase:', '🔠'); + Smilies::add($b, ':input latin lowercase:', '🔡'); + Smilies::add($b, ':input numbers:', '🔢'); + Smilies::add($b, ':input symbols:', '🔣'); + Smilies::add($b, ':input latin letters:', '🔤'); + Smilies::add($b, ':A button (blood type):', '🅰'); + Smilies::add($b, ':AB button (blood type):', '🆎'); + Smilies::add($b, ':B button (blood type):', '🅱'); + Smilies::add($b, ':CL button:', '🆑'); + Smilies::add($b, ':COOL button:', '🆒'); Smilies::add($b, ':cool:', '🆒'); - Smilies::add($b, ':FREE button:', '🆓'); - Smilies::add($b, ':information:', 'ℹ'); - Smilies::add($b, ':ID button:', '🆔'); - Smilies::add($b, ':circled M:', 'Ⓜ'); - Smilies::add($b, ':NEW button:', '🆕'); - Smilies::add($b, ':NG button:', '🆖'); - Smilies::add($b, ':O button (blood type):', '🅾'); - Smilies::add($b, ':OK button:', '🆗'); - Smilies::add($b, ':P button:', '🅿'); - Smilies::add($b, ':SOS button:', '🆘'); - Smilies::add($b, ':UP! button:', '🆙'); - Smilies::add($b, ':VS button:', '🆚'); - Smilies::add($b, ':Japanese “here” button:', '🈁'); - Smilies::add($b, ':Japanese “service charge” button:', '🈂'); - Smilies::add($b, ':Japanese “monthly amount” button:', '🈷'); - Smilies::add($b, ':Japanese “not free of charge” button:', '🈶'); - Smilies::add($b, ':Japanese “reserved” button:', '🈯'); - Smilies::add($b, ':Japanese “bargain” button:', '🉐'); - Smilies::add($b, ':Japanese “discount” button:', '🈹'); - Smilies::add($b, ':Japanese “free of charge” button:', '🈚'); - Smilies::add($b, ':Japanese “prohibited” button:', '🈲'); - Smilies::add($b, ':Japanese “acceptable” button:', '🉑'); - Smilies::add($b, ':Japanese “application” button:', '🈸'); - Smilies::add($b, ':Japanese “passing grade” button:', '🈴'); - Smilies::add($b, ':Japanese “vacancy” button:', '🈳'); - Smilies::add($b, ':Japanese “congratulations” button:', '㊗'); - Smilies::add($b, ':Japanese “secret” button:', '㊙'); - Smilies::add($b, ':Japanese “open for business” button:', '🈺'); - Smilies::add($b, ':Japanese “no vacancy” button:', '🈵'); + Smilies::add($b, ':FREE button:', '🆓'); + Smilies::add($b, ':information:', 'ℹ'); + Smilies::add($b, ':ID button:', '🆔'); + Smilies::add($b, ':circled M:', 'Ⓜ'); + Smilies::add($b, ':NEW button:', '🆕'); + Smilies::add($b, ':NG button:', '🆖'); + Smilies::add($b, ':O button (blood type):', '🅾'); + Smilies::add($b, ':OK button:', '🆗'); + Smilies::add($b, ':P button:', '🅿'); + Smilies::add($b, ':SOS button:', '🆘'); + Smilies::add($b, ':UP! button:', '🆙'); + Smilies::add($b, ':VS button:', '🆚'); + Smilies::add($b, ':Japanese “here” button:', '🈁'); + Smilies::add($b, ':Japanese “service charge” button:', '🈂'); + Smilies::add($b, ':Japanese “monthly amount” button:', '🈷'); + Smilies::add($b, ':Japanese “not free of charge” button:', '🈶'); + Smilies::add($b, ':Japanese “reserved” button:', '🈯'); + Smilies::add($b, ':Japanese “bargain” button:', '🉐'); + Smilies::add($b, ':Japanese “discount” button:', '🈹'); + Smilies::add($b, ':Japanese “free of charge” button:', '🈚'); + Smilies::add($b, ':Japanese “prohibited” button:', '🈲'); + Smilies::add($b, ':Japanese “acceptable” button:', '🉑'); + Smilies::add($b, ':Japanese “application” button:', '🈸'); + Smilies::add($b, ':Japanese “passing grade” button:', '🈴'); + Smilies::add($b, ':Japanese “vacancy” button:', '🈳'); + Smilies::add($b, ':Japanese “congratulations” button:', '㊗'); + Smilies::add($b, ':Japanese “secret” button:', '㊙'); + Smilies::add($b, ':Japanese “open for business” button:', '🈺'); + Smilies::add($b, ':Japanese “no vacancy” button:', '🈵'); // geometric - Smilies::add($b, ':red circle:', '🔴'); -// Smilies::add($b, ':orange circle:', '🟠'); -// Smilies::add($b, ':yellow circle:', '🟡'); -// Smilies::add($b, ':green circle:', '🟢'); - Smilies::add($b, ':blue circle:', '🔵'); -// Smilies::add($b, ':purple circle:', '🟣'); -// Smilies::add($b, ':brown circle:', '🟤'); - Smilies::add($b, ':black circle:', '⚫'); - Smilies::add($b, ':white circle:', '⚪'); -// Smilies::add($b, ':red square:', '🟥'); -// Smilies::add($b, ':orange square:', '🟧'); -// Smilies::add($b, ':yellow square:', '🟨'); -// Smilies::add($b, ':green square:', '🟩'); -// Smilies::add($b, ':blue square:', '🟦'); -// Smilies::add($b, ':purple square:', '🟪'); -// Smilies::add($b, ':brown square:', '🟫'); - Smilies::add($b, ':black large square:', '⬛'); - Smilies::add($b, ':white large square:', '⬜'); - Smilies::add($b, ':black medium square:', '◼'); - Smilies::add($b, ':white medium square:', '◻'); - Smilies::add($b, ':black medium-small square:', '◾'); - Smilies::add($b, ':white medium-small square:', '◽'); - Smilies::add($b, ':black small square:', '▪'); - Smilies::add($b, ':white small square:', '▫'); - Smilies::add($b, ':large orange diamond:', '🔶'); - Smilies::add($b, ':large blue diamond:', '🔷'); - Smilies::add($b, ':small orange diamond:', '🔸'); - Smilies::add($b, ':small blue diamond:', '🔹'); - Smilies::add($b, ':red triangle pointed up:', '🔺'); - Smilies::add($b, ':red triangle pointed down:', '🔻'); - Smilies::add($b, ':diamond with a dot:', '💠'); - Smilies::add($b, ':radio button:', '🔘'); - Smilies::add($b, ':white square button:', '🔳'); - Smilies::add($b, ':black square button:', '🔲'); + Smilies::add($b, ':red circle:', '🔴'); +// Smilies::add($b, ':orange circle:', '🟠'); +// Smilies::add($b, ':yellow circle:', '🟡'); +// Smilies::add($b, ':green circle:', '🟢'); + Smilies::add($b, ':blue circle:', '🔵'); +// Smilies::add($b, ':purple circle:', '🟣'); +// Smilies::add($b, ':brown circle:', '🟤'); + Smilies::add($b, ':black circle:', '⚫'); + Smilies::add($b, ':white circle:', '⚪'); +// Smilies::add($b, ':red square:', '🟥'); +// Smilies::add($b, ':orange square:', '🟧'); +// Smilies::add($b, ':yellow square:', '🟨'); +// Smilies::add($b, ':green square:', '🟩'); +// Smilies::add($b, ':blue square:', '🟦'); +// Smilies::add($b, ':purple square:', '🟪'); +// Smilies::add($b, ':brown square:', '🟫'); + Smilies::add($b, ':black large square:', '⬛'); + Smilies::add($b, ':white large square:', '⬜'); + Smilies::add($b, ':black medium square:', '◼'); + Smilies::add($b, ':white medium square:', '◻'); + Smilies::add($b, ':black medium-small square:', '◾'); + Smilies::add($b, ':white medium-small square:', '◽'); + Smilies::add($b, ':black small square:', '▪'); + Smilies::add($b, ':white small square:', '▫'); + Smilies::add($b, ':large orange diamond:', '🔶'); + Smilies::add($b, ':large blue diamond:', '🔷'); + Smilies::add($b, ':small orange diamond:', '🔸'); + Smilies::add($b, ':small blue diamond:', '🔹'); + Smilies::add($b, ':red triangle pointed up:', '🔺'); + Smilies::add($b, ':red triangle pointed down:', '🔻'); + Smilies::add($b, ':diamond with a dot:', '💠'); + Smilies::add($b, ':radio button:', '🔘'); + Smilies::add($b, ':white square button:', '🔳'); + Smilies::add($b, ':black square button:', '🔲'); // Flags // flag - Smilies::add($b, ':chequered flag:', '🏁'); - Smilies::add($b, ':triangular flag:', '🚩'); - Smilies::add($b, ':crossed flags:', '🎌'); - Smilies::add($b, ':black flag:', '🏴'); - Smilies::add($b, ':white flag:', '🏳'); - Smilies::add($b, ':rainbow flag:', '🏳️‍🌈'); - Smilies::add($b, ':pirate flag:', '🏴‍☠️'); + Smilies::add($b, ':chequered flag:', '🏁'); + Smilies::add($b, ':triangular flag:', '🚩'); + Smilies::add($b, ':crossed flags:', '🎌'); + Smilies::add($b, ':black flag:', '🏴'); + Smilies::add($b, ':white flag:', '🏳'); + Smilies::add($b, ':rainbow flag:', '🏳️‍🌈'); + Smilies::add($b, ':pirate flag:', '🏴‍☠️'); // country-flag - Smilies::add($b, ':ascension island:', '🇦🇨'); - Smilies::add($b, ':andorra:', '🇦🇩'); - Smilies::add($b, ':united arab emirates:', '🇦🇪'); - Smilies::add($b, ':afghanistan:', '🇦🇫'); - Smilies::add($b, ':antigua & barbuda:', '🇦🇬'); - Smilies::add($b, ':anguilla:', '🇦🇮'); - Smilies::add($b, ':albania:', '🇦🇱'); - Smilies::add($b, ':armenia:', '🇦🇲'); - Smilies::add($b, ':angola:', '🇦🇴'); - Smilies::add($b, ':antarctica:', '🇦🇶'); - Smilies::add($b, ':argentina:', '🇦🇷'); - Smilies::add($b, ':americansamoa:', '🇦🇸'); - Smilies::add($b, ':austria:', '🇦🇹'); - Smilies::add($b, ':australia:', '🇦🇺'); - Smilies::add($b, ':aruba:', '🇦🇼'); - Smilies::add($b, ':ålandislands:', '🇦🇽'); - Smilies::add($b, ':azerbaijan:', '🇦🇿'); - Smilies::add($b, ':bosnia&herzegovina:', '🇧🇦'); - Smilies::add($b, ':barbados:', '🇧🇧'); - Smilies::add($b, ':bangladesh:', '🇧🇩'); - Smilies::add($b, ':belgium:', '🇧🇪'); - Smilies::add($b, ':burkinafaso:', '🇧🇫'); - Smilies::add($b, ':bulgaria:', '🇧🇬'); - Smilies::add($b, ':bahrain:', '🇧🇭'); - Smilies::add($b, ':burundi:', '🇧🇮'); - Smilies::add($b, ':benin:', '🇧🇯'); - Smilies::add($b, ':st.barthélemy:', '🇧🇱'); - Smilies::add($b, ':bermuda:', '🇧🇲'); - Smilies::add($b, ':brunei:', '🇧🇳'); - Smilies::add($b, ':bolivia:', '🇧🇴'); - Smilies::add($b, ':caribbeannetherlands:', '🇧🇶'); - Smilies::add($b, ':brazil:', '🇧🇷'); - Smilies::add($b, ':bahamas:', '🇧🇸'); - Smilies::add($b, ':bhutan:', '🇧🇹'); - Smilies::add($b, ':bouvetisland:', '🇧🇻'); - Smilies::add($b, ':botswana:', '🇧🇼'); - Smilies::add($b, ':belarus:', '🇧🇾'); - Smilies::add($b, ':belize:', '🇧🇿'); - Smilies::add($b, ':canada:', '🇨🇦'); - Smilies::add($b, ':cocos(keeling)islands:', '🇨🇨'); - Smilies::add($b, ':congo-kinshasa:', '🇨🇩'); - Smilies::add($b, ':centralafricanrepublic:', '🇨🇫'); - Smilies::add($b, ':congo-brazzaville:', '🇨🇬'); - Smilies::add($b, ':switzerland:', '🇨🇭'); - Smilies::add($b, ':côted’ivoire:', '🇨🇮'); - Smilies::add($b, ':cookislands:', '🇨🇰'); - Smilies::add($b, ':chile:', '🇨🇱'); - Smilies::add($b, ':cameroon:', '🇨🇲'); - Smilies::add($b, ':china:', '🇨🇳'); - Smilies::add($b, ':colombia:', '🇨🇴'); - Smilies::add($b, ':clippertonisland:', '🇨🇵'); - Smilies::add($b, ':costarica:', '🇨🇷'); - Smilies::add($b, ':cuba:', '🇨🇺'); - Smilies::add($b, ':capeverde:', '🇨🇻'); - Smilies::add($b, ':curaçao:', '🇨🇼'); - Smilies::add($b, ':christmasisland:', '🇨🇽'); - Smilies::add($b, ':cyprus:', '🇨🇾'); - Smilies::add($b, ':czechia:', '🇨🇿'); - Smilies::add($b, ':germany:', '🇩🇪'); - Smilies::add($b, ':diegogarcia:', '🇩🇬'); - Smilies::add($b, ':djibouti:', '🇩🇯'); - Smilies::add($b, ':denmark:', '🇩🇰'); - Smilies::add($b, ':dominica:', '🇩🇲'); - Smilies::add($b, ':dominicanrepublic:', '🇩🇴'); - Smilies::add($b, ':algeria:', '🇩🇿'); - Smilies::add($b, ':ceuta&melilla:', '🇪🇦'); - Smilies::add($b, ':ecuador:', '🇪🇨'); - Smilies::add($b, ':estonia:', '🇪🇪'); - Smilies::add($b, ':egypt:', '🇪🇬'); - Smilies::add($b, ':westernsahara:', '🇪🇭'); - Smilies::add($b, ':eritrea:', '🇪🇷'); - Smilies::add($b, ':spain:', '🇪🇸'); - Smilies::add($b, ':ethiopia:', '🇪🇹'); - Smilies::add($b, ':europeanunion:', '🇪🇺'); - Smilies::add($b, ':finland:', '🇫🇮'); - Smilies::add($b, ':fiji:', '🇫🇯'); - Smilies::add($b, ':falklandislands:', '🇫🇰'); - Smilies::add($b, ':micronesia:', '🇫🇲'); - Smilies::add($b, ':faroeislands:', '🇫🇴'); - Smilies::add($b, ':france:', '🇫🇷'); - Smilies::add($b, ':gabon:', '🇬🇦'); - Smilies::add($b, ':unitedkingdom:', '🇬🇧'); - Smilies::add($b, ':grenada:', '🇬🇩'); - Smilies::add($b, ':georgia:', '🇬🇪'); - Smilies::add($b, ':frenchguiana:', '🇬🇫'); - Smilies::add($b, ':guernsey:', '🇬🇬'); - Smilies::add($b, ':ghana:', '🇬🇭'); - Smilies::add($b, ':gibraltar:', '🇬🇮'); - Smilies::add($b, ':greenland:', '🇬🇱'); - Smilies::add($b, ':gambia:', '🇬🇲'); - Smilies::add($b, ':guinea:', '🇬🇳'); - Smilies::add($b, ':guadeloupe:', '🇬🇵'); - Smilies::add($b, ':equatorialguinea:', '🇬🇶'); - Smilies::add($b, ':greece:', '🇬🇷'); - Smilies::add($b, ':southgeorgia&southsandwichislands:', '🇬🇸'); - Smilies::add($b, ':guatemala:', '🇬🇹'); - Smilies::add($b, ':guam:', '🇬🇺'); - Smilies::add($b, ':guinea-bissau:', '🇬🇼'); - Smilies::add($b, ':guyana:', '🇬🇾'); - Smilies::add($b, ':hongkongsarchina:', '🇭🇰'); - Smilies::add($b, ':heard&mcdonaldislands:', '🇭🇲'); - Smilies::add($b, ':honduras:', '🇭🇳'); - Smilies::add($b, ':croatia:', '🇭🇷'); - Smilies::add($b, ':haiti:', '🇭🇹'); - Smilies::add($b, ':hungary:', '🇭🇺'); - Smilies::add($b, ':canaryislands:', '🇮🇨'); - Smilies::add($b, ':indonesia:', '🇮🇩'); - Smilies::add($b, ':ireland:', '🇮🇪'); - Smilies::add($b, ':israel:', '🇮🇱'); - Smilies::add($b, ':isleofman:', '🇮🇲'); - Smilies::add($b, ':india:', '🇮🇳'); - Smilies::add($b, ':britishindianoceanterritory:', '🇮🇴'); - Smilies::add($b, ':iraq:', '🇮🇶'); - Smilies::add($b, ':iran:', '🇮🇷'); - Smilies::add($b, ':iceland:', '🇮🇸'); - Smilies::add($b, ':italy:', '🇮🇹'); - Smilies::add($b, ':jersey:', '🇯🇪'); - Smilies::add($b, ':jamaica:', '🇯🇲'); - Smilies::add($b, ':jordan:', '🇯🇴'); - Smilies::add($b, ':japan:', '🇯🇵'); - Smilies::add($b, ':kenya:', '🇰🇪'); - Smilies::add($b, ':kyrgyzstan:', '🇰🇬'); - Smilies::add($b, ':cambodia:', '🇰🇭'); - Smilies::add($b, ':kiribati:', '🇰🇮'); - Smilies::add($b, ':comoros:', '🇰🇲'); - Smilies::add($b, ':st.kitts&nevis:', '🇰🇳'); - Smilies::add($b, ':northkorea:', '🇰🇵'); - Smilies::add($b, ':southkorea:', '🇰🇷'); - Smilies::add($b, ':kuwait:', '🇰🇼'); - Smilies::add($b, ':caymanislands:', '🇰🇾'); - Smilies::add($b, ':kazakhstan:', '🇰🇿'); - Smilies::add($b, ':laos:', '🇱🇦'); - Smilies::add($b, ':lebanon:', '🇱🇧'); - Smilies::add($b, ':st.lucia:', '🇱🇨'); - Smilies::add($b, ':liechtenstein:', '🇱🇮'); - Smilies::add($b, ':srilanka:', '🇱🇰'); - Smilies::add($b, ':liberia:', '🇱🇷'); - Smilies::add($b, ':lesotho:', '🇱🇸'); - Smilies::add($b, ':lithuania:', '🇱🇹'); - Smilies::add($b, ':luxembourg:', '🇱🇺'); - Smilies::add($b, ':latvia:', '🇱🇻'); - Smilies::add($b, ':libya:', '🇱🇾'); - Smilies::add($b, ':morocco:', '🇲🇦'); - Smilies::add($b, ':monaco:', '🇲🇨'); - Smilies::add($b, ':moldova:', '🇲🇩'); - Smilies::add($b, ':montenegro:', '🇲🇪'); - Smilies::add($b, ':st.martin:', '🇲🇫'); - Smilies::add($b, ':madagascar:', '🇲🇬'); - Smilies::add($b, ':marshallislands:', '🇲🇭'); - Smilies::add($b, ':northmacedonia:', '🇲🇰'); - Smilies::add($b, ':mali:', '🇲🇱'); - Smilies::add($b, ':myanmar(burma):', '🇲🇲'); - Smilies::add($b, ':mongolia:', '🇲🇳'); - Smilies::add($b, ':macaosarchina:', '🇲🇴'); - Smilies::add($b, ':northernmarianaislands:', '🇲🇵'); - Smilies::add($b, ':martinique:', '🇲🇶'); - Smilies::add($b, ':mauritania:', '🇲🇷'); - Smilies::add($b, ':montserrat:', '🇲🇸'); - Smilies::add($b, ':malta:', '🇲🇹'); - Smilies::add($b, ':mauritius:', '🇲🇺'); - Smilies::add($b, ':maldives:', '🇲🇻'); - Smilies::add($b, ':malawi:', '🇲🇼'); - Smilies::add($b, ':mexico:', '🇲🇽'); - Smilies::add($b, ':malaysia:', '🇲🇾'); - Smilies::add($b, ':mozambique:', '🇲🇿'); - Smilies::add($b, ':namibia:', '🇳🇦'); - Smilies::add($b, ':newcaledonia:', '🇳🇨'); - Smilies::add($b, ':niger:', '🇳🇪'); - Smilies::add($b, ':norfolkisland:', '🇳🇫'); - Smilies::add($b, ':nigeria:', '🇳🇬'); - Smilies::add($b, ':nicaragua:', '🇳🇮'); - Smilies::add($b, ':netherlands:', '🇳🇱'); - Smilies::add($b, ':norway:', '🇳🇴'); - Smilies::add($b, ':nepal:', '🇳🇵'); - Smilies::add($b, ':nauru:', '🇳🇷'); - Smilies::add($b, ':niue:', '🇳🇺'); - Smilies::add($b, ':newzealand:', '🇳🇿'); - Smilies::add($b, ':oman:', '🇴🇲'); - Smilies::add($b, ':panama:', '🇵🇦'); - Smilies::add($b, ':peru:', '🇵🇪'); - Smilies::add($b, ':frenchpolynesia:', '🇵🇫'); - Smilies::add($b, ':papuanewguinea:', '🇵🇬'); - Smilies::add($b, ':philippines:', '🇵🇭'); - Smilies::add($b, ':pakistan:', '🇵🇰'); - Smilies::add($b, ':poland:', '🇵🇱'); - Smilies::add($b, ':st.pierre&miquelon:', '🇵🇲'); - Smilies::add($b, ':pitcairnislands:', '🇵🇳'); - Smilies::add($b, ':puertorico:', '🇵🇷'); - Smilies::add($b, ':palestinianterritories:', '🇵🇸'); - Smilies::add($b, ':portugal:', '🇵🇹'); - Smilies::add($b, ':palau:', '🇵🇼'); - Smilies::add($b, ':paraguay:', '🇵🇾'); - Smilies::add($b, ':qatar:', '🇶🇦'); - Smilies::add($b, ':réunion:', '🇷🇪'); - Smilies::add($b, ':romania:', '🇷🇴'); - Smilies::add($b, ':serbia:', '🇷🇸'); - Smilies::add($b, ':russia:', '🇷🇺'); - Smilies::add($b, ':rwanda:', '🇷🇼'); - Smilies::add($b, ':saudiarabia:', '🇸🇦'); - Smilies::add($b, ':solomonislands:', '🇸🇧'); - Smilies::add($b, ':seychelles:', '🇸🇨'); - Smilies::add($b, ':sudan:', '🇸🇩'); - Smilies::add($b, ':sweden:', '🇸🇪'); - Smilies::add($b, ':singapore:', '🇸🇬'); - Smilies::add($b, ':st.helena:', '🇸🇭'); - Smilies::add($b, ':slovenia:', '🇸🇮'); - Smilies::add($b, ':svalbard&janmayen:', '🇸🇯'); - Smilies::add($b, ':slovakia:', '🇸🇰'); - Smilies::add($b, ':sierraleone:', '🇸🇱'); - Smilies::add($b, ':sanmarino:', '🇸🇲'); - Smilies::add($b, ':senegal:', '🇸🇳'); - Smilies::add($b, ':somalia:', '🇸🇴'); - Smilies::add($b, ':suriname:', '🇸🇷'); - Smilies::add($b, ':southsudan:', '🇸🇸'); - Smilies::add($b, ':sãotomé&príncipe:', '🇸🇹'); - Smilies::add($b, ':elsalvador:', '🇸🇻'); - Smilies::add($b, ':sintmaarten:', '🇸🇽'); - Smilies::add($b, ':syria:', '🇸🇾'); - Smilies::add($b, ':eswatini:', '🇸🇿'); - Smilies::add($b, ':tristandacunha:', '🇹🇦'); - Smilies::add($b, ':turks&caicosislands:', '🇹🇨'); - Smilies::add($b, ':chad:', '🇹🇩'); - Smilies::add($b, ':frenchsouthernterritories:', '🇹🇫'); - Smilies::add($b, ':togo:', '🇹🇬'); - Smilies::add($b, ':thailand:', '🇹🇭'); - Smilies::add($b, ':tajikistan:', '🇹🇯'); - Smilies::add($b, ':tokelau:', '🇹🇰'); - Smilies::add($b, ':timor-leste:', '🇹🇱'); - Smilies::add($b, ':turkmenistan:', '🇹🇲'); - Smilies::add($b, ':tunisia:', '🇹🇳'); - Smilies::add($b, ':tonga:', '🇹🇴'); - Smilies::add($b, ':turkey:', '🇹🇷'); - Smilies::add($b, ':trinidad&tobago:', '🇹🇹'); - Smilies::add($b, ':tuvalu:', '🇹🇻'); - Smilies::add($b, ':taiwan:', '🇹🇼'); - Smilies::add($b, ':tanzania:', '🇹🇿'); - Smilies::add($b, ':ukraine:', '🇺🇦'); - Smilies::add($b, ':uganda:', '🇺🇬'); - Smilies::add($b, ':u.s.outlyingislands:', '🇺🇲'); - Smilies::add($b, ':unitednations:', '🇺🇳'); - Smilies::add($b, ':unitedstates:', '🇺🇸'); - Smilies::add($b, ':uruguay:', '🇺🇾'); - Smilies::add($b, ':uzbekistan:', '🇺🇿'); - Smilies::add($b, ':vaticancity:', '🇻🇦'); - Smilies::add($b, ':st.vincent&grenadines:', '🇻🇨'); - Smilies::add($b, ':venezuela:', '🇻🇪'); - Smilies::add($b, ':britishvirginislands:', '🇻🇬'); - Smilies::add($b, ':u.s.virginislands:', '🇻🇮'); - Smilies::add($b, ':vietnam:', '🇻🇳'); - Smilies::add($b, ':vanuatu:', '🇻🇺'); - Smilies::add($b, ':wallis&futuna:', '🇼🇫'); - Smilies::add($b, ':samoa:', '🇼🇸'); - Smilies::add($b, ':kosovo:', '🇽🇰'); - Smilies::add($b, ':yemen:', '🇾🇪'); - Smilies::add($b, ':mayotte:', '🇾🇹'); - Smilies::add($b, ':southafrica:', '🇿🇦'); - Smilies::add($b, ':zambia:', '🇿🇲'); - Smilies::add($b, ':zimbabwe:', '🇿🇼'); + Smilies::add($b, ':ascension island:', '🇦🇨'); + Smilies::add($b, ':andorra:', '🇦🇩'); + Smilies::add($b, ':united arab emirates:', '🇦🇪'); + Smilies::add($b, ':afghanistan:', '🇦🇫'); + Smilies::add($b, ':antigua & barbuda:', '🇦🇬'); + Smilies::add($b, ':anguilla:', '🇦🇮'); + Smilies::add($b, ':albania:', '🇦🇱'); + Smilies::add($b, ':armenia:', '🇦🇲'); + Smilies::add($b, ':angola:', '🇦🇴'); + Smilies::add($b, ':antarctica:', '🇦🇶'); + Smilies::add($b, ':argentina:', '🇦🇷'); + Smilies::add($b, ':americansamoa:', '🇦🇸'); + Smilies::add($b, ':austria:', '🇦🇹'); + Smilies::add($b, ':australia:', '🇦🇺'); + Smilies::add($b, ':aruba:', '🇦🇼'); + Smilies::add($b, ':ålandislands:', '🇦🇽'); + Smilies::add($b, ':azerbaijan:', '🇦🇿'); + Smilies::add($b, ':bosnia&herzegovina:', '🇧🇦'); + Smilies::add($b, ':barbados:', '🇧🇧'); + Smilies::add($b, ':bangladesh:', '🇧🇩'); + Smilies::add($b, ':belgium:', '🇧🇪'); + Smilies::add($b, ':burkinafaso:', '🇧🇫'); + Smilies::add($b, ':bulgaria:', '🇧🇬'); + Smilies::add($b, ':bahrain:', '🇧🇭'); + Smilies::add($b, ':burundi:', '🇧🇮'); + Smilies::add($b, ':benin:', '🇧🇯'); + Smilies::add($b, ':st.barthélemy:', '🇧🇱'); + Smilies::add($b, ':bermuda:', '🇧🇲'); + Smilies::add($b, ':brunei:', '🇧🇳'); + Smilies::add($b, ':bolivia:', '🇧🇴'); + Smilies::add($b, ':caribbeannetherlands:', '🇧🇶'); + Smilies::add($b, ':brazil:', '🇧🇷'); + Smilies::add($b, ':bahamas:', '🇧🇸'); + Smilies::add($b, ':bhutan:', '🇧🇹'); + Smilies::add($b, ':bouvetisland:', '🇧🇻'); + Smilies::add($b, ':botswana:', '🇧🇼'); + Smilies::add($b, ':belarus:', '🇧🇾'); + Smilies::add($b, ':belize:', '🇧🇿'); + Smilies::add($b, ':canada:', '🇨🇦'); + Smilies::add($b, ':cocos(keeling)islands:', '🇨🇨'); + Smilies::add($b, ':congo-kinshasa:', '🇨🇩'); + Smilies::add($b, ':centralafricanrepublic:', '🇨🇫'); + Smilies::add($b, ':congo-brazzaville:', '🇨🇬'); + Smilies::add($b, ':switzerland:', '🇨🇭'); + Smilies::add($b, ':côted’ivoire:', '🇨🇮'); + Smilies::add($b, ':cookislands:', '🇨🇰'); + Smilies::add($b, ':chile:', '🇨🇱'); + Smilies::add($b, ':cameroon:', '🇨🇲'); + Smilies::add($b, ':china:', '🇨🇳'); + Smilies::add($b, ':colombia:', '🇨🇴'); + Smilies::add($b, ':clippertonisland:', '🇨🇵'); + Smilies::add($b, ':costarica:', '🇨🇷'); + Smilies::add($b, ':cuba:', '🇨🇺'); + Smilies::add($b, ':capeverde:', '🇨🇻'); + Smilies::add($b, ':curaçao:', '🇨🇼'); + Smilies::add($b, ':christmasisland:', '🇨🇽'); + Smilies::add($b, ':cyprus:', '🇨🇾'); + Smilies::add($b, ':czechia:', '🇨🇿'); + Smilies::add($b, ':germany:', '🇩🇪'); + Smilies::add($b, ':diegogarcia:', '🇩🇬'); + Smilies::add($b, ':djibouti:', '🇩🇯'); + Smilies::add($b, ':denmark:', '🇩🇰'); + Smilies::add($b, ':dominica:', '🇩🇲'); + Smilies::add($b, ':dominicanrepublic:', '🇩🇴'); + Smilies::add($b, ':algeria:', '🇩🇿'); + Smilies::add($b, ':ceuta&melilla:', '🇪🇦'); + Smilies::add($b, ':ecuador:', '🇪🇨'); + Smilies::add($b, ':estonia:', '🇪🇪'); + Smilies::add($b, ':egypt:', '🇪🇬'); + Smilies::add($b, ':westernsahara:', '🇪🇭'); + Smilies::add($b, ':eritrea:', '🇪🇷'); + Smilies::add($b, ':spain:', '🇪🇸'); + Smilies::add($b, ':ethiopia:', '🇪🇹'); + Smilies::add($b, ':europeanunion:', '🇪🇺'); + Smilies::add($b, ':finland:', '🇫🇮'); + Smilies::add($b, ':fiji:', '🇫🇯'); + Smilies::add($b, ':falklandislands:', '🇫🇰'); + Smilies::add($b, ':micronesia:', '🇫🇲'); + Smilies::add($b, ':faroeislands:', '🇫🇴'); + Smilies::add($b, ':france:', '🇫🇷'); + Smilies::add($b, ':gabon:', '🇬🇦'); + Smilies::add($b, ':unitedkingdom:', '🇬🇧'); + Smilies::add($b, ':grenada:', '🇬🇩'); + Smilies::add($b, ':georgia:', '🇬🇪'); + Smilies::add($b, ':frenchguiana:', '🇬🇫'); + Smilies::add($b, ':guernsey:', '🇬🇬'); + Smilies::add($b, ':ghana:', '🇬🇭'); + Smilies::add($b, ':gibraltar:', '🇬🇮'); + Smilies::add($b, ':greenland:', '🇬🇱'); + Smilies::add($b, ':gambia:', '🇬🇲'); + Smilies::add($b, ':guinea:', '🇬🇳'); + Smilies::add($b, ':guadeloupe:', '🇬🇵'); + Smilies::add($b, ':equatorialguinea:', '🇬🇶'); + Smilies::add($b, ':greece:', '🇬,;🇷'); + Smilies::add($b, ':southgeorgia&southsandwichislands:', '🇬🇸'); + Smilies::add($b, ':guatemala:', '🇬🇹'); + Smilies::add($b, ':guam:', '🇬🇺'); + Smilies::add($b, ':guinea-bissau:', '🇬🇼'); + Smilies::add($b, ':guyana:', '🇬🇾'); + Smilies::add($b, ':hongkongsarchina:', '🇭🇰'); + Smilies::add($b, ':heard&mcdonaldislands:', '🇭🇲'); + Smilies::add($b, ':honduras:', '🇭🇳'); + Smilies::add($b, ':croatia:', '🇭🇷'); + Smilies::add($b, ':haiti:', '🇭🇹'); + Smilies::add($b, ':hungary:', '🇭🇺'); + Smilies::add($b, ':canaryislands:', '🇮🇨'); + Smilies::add($b, ':indonesia:', '🇮🇩'); + Smilies::add($b, ':ireland:', '🇮🇪'); + Smilies::add($b, ':israel:', '🇮🇱'); + Smilies::add($b, ':isleofman:', '🇮🇲'); + Smilies::add($b, ':india:', '🇮🇳'); + Smilies::add($b, ':britishindianoceanterritory:', '🇮🇴'); + Smilies::add($b, ':iraq:', '🇮🇶'); + Smilies::add($b, ':iran:', '🇮🇷'); + Smilies::add($b, ':iceland:', '🇮🇸'); + Smilies::add($b, ':italy:', '🇮🇹'); + Smilies::add($b, ':jersey:', '🇯🇪'); + Smilies::add($b, ':jamaica:', '🇯🇲'); + Smilies::add($b, ':jordan:', '🇯🇴'); + Smilies::add($b, ':japan:', '🇯🇵'); + Smilies::add($b, ':kenya:', '🇰🇪'); + Smilies::add($b, ':kyrgyzstan:', '🇰🇬'); + Smilies::add($b, ':cambodia:', '🇰🇭'); + Smilies::add($b, ':kiribati:', '🇰🇮'); + Smilies::add($b, ':comoros:', '🇰🇲'); + Smilies::add($b, ':st.kitts&nevis:', '🇰🇳'); + Smilies::add($b, ':northkorea:', '🇰🇵'); + Smilies::add($b, ':southkorea:', '🇰🇷'); + Smilies::add($b, ':kuwait:', '🇰🇼'); + Smilies::add($b, ':caymanislands:', '🇰🇾'); + Smilies::add($b, ':kazakhstan:', '🇰🇿'); + Smilies::add($b, ':laos:', '🇱🇦'); + Smilies::add($b, ':lebanon:', '🇱🇧'); + Smilies::add($b, ':st.lucia:', '🇱🇨'); + Smilies::add($b, ':liechtenstein:', '🇱🇮'); + Smilies::add($b, ':srilanka:', '🇱🇰'); + Smilies::add($b, ':liberia:', '🇱🇷'); + Smilies::add($b, ':lesotho:', '🇱🇸'); + Smilies::add($b, ':lithuania:', '🇱🇹'); + Smilies::add($b, ':luxembourg:', '🇱🇺'); + Smilies::add($b, ':latvia:', '🇱🇻'); + Smilies::add($b, ':libya:', '🇱🇾'); + Smilies::add($b, ':morocco:', '🇲🇦'); + Smilies::add($b, ':monaco:', '🇲🇨'); + Smilies::add($b, ':moldova:', '🇲🇩'); + Smilies::add($b, ':montenegro:', '🇲🇪'); + Smilies::add($b, ':st.martin:', '🇲🇫'); + Smilies::add($b, ':madagascar:', '🇲🇬'); + Smilies::add($b, ':marshallislands:', '🇲🇭'); + Smilies::add($b, ':northmacedonia:', '🇲🇰'); + Smilies::add($b, ':mali:', '🇲🇱'); + Smilies::add($b, ':myanmar(burma):', '🇲🇲'); + Smilies::add($b, ':mongolia:', '🇲🇳'); + Smilies::add($b, ':macaosarchina:', '🇲🇴'); + Smilies::add($b, ':northernmarianaislands:', '🇲🇵'); + Smilies::add($b, ':martinique:', '🇲🇶'); + Smilies::add($b, ':mauritania:', '🇲🇷'); + Smilies::add($b, ':montserrat:', '🇲🇸'); + Smilies::add($b, ':malta:', '🇲🇹'); + Smilies::add($b, ':mauritius:', '🇲🇺'); + Smilies::add($b, ':maldives:', '🇲🇻'); + Smilies::add($b, ':malawi:', '🇲🇼'); + Smilies::add($b, ':mexico:', '🇲🇽'); + Smilies::add($b, ':malaysia:', '🇲🇾'); + Smilies::add($b, ':mozambique:', '🇲🇿'); + Smilies::add($b, ':namibia:', '🇳🇦'); + Smilies::add($b, ':newcaledonia:', '🇳🇨'); + Smilies::add($b, ':niger:', '🇳🇪'); + Smilies::add($b, ':norfolkisland:', '🇳🇫'); + Smilies::add($b, ':nigeria:', '🇳🇬'); + Smilies::add($b, ':nicaragua:', '🇳🇮'); + Smilies::add($b, ':netherlands:', '🇳🇱'); + Smilies::add($b, ':norway:', '🇳🇴'); + Smilies::add($b, ':nepal:', '🇳🇵'); + Smilies::add($b, ':nauru:', '🇳🇷'); + Smilies::add($b, ':niue:', '🇳🇺'); + Smilies::add($b, ':newzealand:', '🇳🇿'); + Smilies::add($b, ':oman:', '🇴🇲'); + Smilies::add($b, ':panama:', '🇵🇦'); + Smilies::add($b, ':peru:', '🇵🇪'); + Smilies::add($b, ':frenchpolynesia:', '🇵🇫'); + Smilies::add($b, ':papuanewguinea:', '🇵🇬'); + Smilies::add($b, ':philippines:', '🇵🇭'); + Smilies::add($b, ':pakistan:', '🇵🇰'); + Smilies::add($b, ':poland:', '🇵🇱'); + Smilies::add($b, ':st.pierre&miquelon:', '🇵🇲'); + Smilies::add($b, ':pitcairnislands:', '🇵🇳'); + Smilies::add($b, ':puertorico:', '🇵🇷'); + Smilies::add($b, ':palestinianterritories:', '🇵🇸'); + Smilies::add($b, ':portugal:', '🇵🇹'); + Smilies::add($b, ':palau:', '🇵🇼'); + Smilies::add($b, ':paraguay:', '🇵🇾'); + Smilies::add($b, ':qatar:', '🇶🇦'); + Smilies::add($b, ':réunion:', '🇷🇪'); + Smilies::add($b, ':romania:', '🇷🇴'); + Smilies::add($b, ':serbia:', '🇷🇸'); + Smilies::add($b, ':russia:', '🇷🇺'); + Smilies::add($b, ':rwanda:', '🇷🇼'); + Smilies::add($b, ':saudiarabia:', '🇸🇦'); + Smilies::add($b, ':solomonislands:', '🇸🇧'); + Smilies::add($b, ':seychelles:', '🇸🇨'); + Smilies::add($b, ':sudan:', '🇸🇩'); + Smilies::add($b, ':sweden:', '🇸🇪'); + Smilies::add($b, ':singapore:', '🇸🇬'); + Smilies::add($b, ':st.helena:', '🇸🇭'); + Smilies::add($b, ':slovenia:', '🇸🇮'); + Smilies::add($b, ':svalbard&janmayen:', '🇸🇯'); + Smilies::add($b, ':slovakia:', '🇸🇰'); + Smilies::add($b, ':sierraleone:', '🇸🇱'); + Smilies::add($b, ':sanmarino:', '🇸🇲'); + Smilies::add($b, ':senegal:', '🇸🇳'); + Smilies::add($b, ':somalia:', '🇸🇴'); + Smilies::add($b, ':suriname:', '🇸🇷'); + Smilies::add($b, ':southsudan:', '🇸🇸'); + Smilies::add($b, ':sãotomé&príncipe:', '🇸🇹'); + Smilies::add($b, ':elsalvador:', '🇸🇻'); + Smilies::add($b, ':sintmaarten:', '🇸🇽'); + Smilies::add($b, ':syria:', '🇸🇾'); + Smilies::add($b, ':eswatini:', '🇸🇿'); + Smilies::add($b, ':tristandacunha:', '🇹🇦'); + Smilies::add($b, ':turks&caicosislands:', '🇹🇨'); + Smilies::add($b, ':chad:', '🇹🇩'); + Smilies::add($b, ':frenchsouthernterritories:', '🇹🇫'); + Smilies::add($b, ':togo:', '🇹🇬'); + Smilies::add($b, ':thailand:', '🇹🇭'); + Smilies::add($b, ':tajikistan:', '🇹🇯'); + Smilies::add($b, ':tokelau:', '🇹🇰'); + Smilies::add($b, ':timor-leste:', '🇹🇱'); + Smilies::add($b, ':turkmenistan:', '🇹🇲'); + Smilies::add($b, ':tunisia:', '🇹🇳'); + Smilies::add($b, ':tonga:', '🇹🇴'); + Smilies::add($b, ':turkey:', '🇹🇷'); + Smilies::add($b, ':trinidad&tobago:', '🇹🇹'); + Smilies::add($b, ':tuvalu:', '🇹🇻'); + Smilies::add($b, ':taiwan:', '🇹🇼'); + Smilies::add($b, ':tanzania:', '🇹🇿'); + Smilies::add($b, ':ukraine:', '🇺🇦'); + Smilies::add($b, ':uganda:', '🇺🇬'); + Smilies::add($b, ':u.s.outlyingislands:', '🇺🇲'); + Smilies::add($b, ':unitednations:', '🇺🇳'); + Smilies::add($b, ':unitedstates:', '🇺🇸'); + Smilies::add($b, ':uruguay:', '🇺🇾'); + Smilies::add($b, ':uzbekistan:', '🇺🇿'); + Smilies::add($b, ':vaticancity:', '🇻🇦'); + Smilies::add($b, ':st.vincent&grenadines:', '🇻🇨'); + Smilies::add($b, ':venezuela:', '🇻🇪'); + Smilies::add($b, ':britishvirginislands:', '🇻🇬'); + Smilies::add($b, ':u.s.virginislands:', '🇻🇮'); + Smilies::add($b, ':vietnam:', '🇻🇳'); + Smilies::add($b, ':vanuatu:', '🇻🇺'); + Smilies::add($b, ':wallis&futuna:', '🇼🇫'); + Smilies::add($b, ':samoa:', '🇼🇸'); + Smilies::add($b, ':kosovo:', '🇽🇰'); + Smilies::add($b, ':yemen:', '🇾🇪'); + Smilies::add($b, ':mayotte:', '🇾🇹'); + Smilies::add($b, ':southafrica:', '🇿🇦'); + Smilies::add($b, ':zambia:', '🇿🇲'); + Smilies::add($b, ':zimbabwe:', '🇿🇼'); // subdivision-flag - Smilies::add($b, ':england:', '🏴󠁧󠁢󠁥󠁮󠁧󠁿'); - Smilies::add($b, ':scotland:', '🏴󠁧󠁢󠁳󠁴󠁿'); - Smilies::add($b, ':wales:', '🏴󠁧󠁢󠁷󠁬󠁳󠁿'); + Smilies::add($b, ':england:', '🏴󠁧󠁢󠁥󠁮󠁧󠁿'); + Smilies::add($b, ':scotland:', '🏴󠁧󠁢󠁳󠁴󠁿'); + Smilies::add($b, ':wales:', '🏴󠁧󠁢󠁷󠁬󠁳󠁿'); } + From 0697f078f11af094ec8455d1ec9e59ec63cd66d0 Mon Sep 17 00:00:00 2001 From: Philipp Date: Sun, 22 Dec 2024 08:38:17 +0100 Subject: [PATCH 300/388] [CI] Fix codecov --- .woodpecker/.phpunit.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.woodpecker/.phpunit.yml b/.woodpecker/.phpunit.yml index 887e897e0..3f713d19b 100644 --- a/.woodpecker/.phpunit.yml +++ b/.woodpecker/.phpunit.yml @@ -98,9 +98,9 @@ pipeline: - friendica/friendica-addons commands: - codecov -R '.' -Z -f 'clover.xml' - secrets: - - source: codecov-token - target: codecov_token + environment: + codecov_token: + from_secret: codecov-token services: mariadb: From 5f50fd2498b58787f8671c3e6cff6658d9dd38dd Mon Sep 17 00:00:00 2001 From: Philipp Date: Sun, 22 Dec 2024 08:54:51 +0100 Subject: [PATCH 301/388] Fix codecov token env --- .woodpecker/.phpunit.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.woodpecker/.phpunit.yml b/.woodpecker/.phpunit.yml index 3f713d19b..6acbf787c 100644 --- a/.woodpecker/.phpunit.yml +++ b/.woodpecker/.phpunit.yml @@ -99,7 +99,7 @@ pipeline: commands: - codecov -R '.' -Z -f 'clover.xml' environment: - codecov_token: + CODECOV_TOKEN: from_secret: codecov-token services: From 9e1f7dc468b3e615e2345b691b89ecfc80364f87 Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 27 Dec 2024 10:26:20 +0000 Subject: [PATCH 302/388] Bluesky: Preparation to be able to fetch AT links --- bluesky/bluesky.php | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index d6b7624ba..1355f0002 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -97,27 +97,25 @@ function bluesky_item_by_link(array &$hookData) return; } - $token = DI::atProtocol()->getUserToken($hookData['uid']); - if (empty($token)) { - return; + if (substr($hookData['uri'], 0, 5) != 'at://') { + if (!preg_match('#^' . ATProtocol::WEB . '/profile/(.+)/post/(.+)#', $hookData['uri'], $matches)) { + return; + } + + $did = DI::atProtocol()->getDid($matches[1]); + if (empty($did)) { + return; + } + + Logger::debug('Found bluesky post', ['uri' => $hookData['uri'], 'did' => $did, 'cid' => $matches[2]]); + + $uri = 'at://' . $did . '/app.bsky.feed.post/' . $matches[2]; + } else { + $uri = $hookData['uri']; } - // @todo also support the URI format (at://did/app.bsky.feed.post/cid) - if (!preg_match('#^' . ATProtocol::WEB . '/profile/(.+)/post/(.+)#', $hookData['uri'], $matches)) { - return; - } - - $did = DI::atProtocol()->getDid($matches[1]); - if (empty($did)) { - return; - } - - Logger::debug('Found bluesky post', ['url' => $hookData['uri'], 'did' => $did, 'cid' => $matches[2]]); - - $uri = 'at://' . $did . '/app.bsky.feed.post/' . $matches[2]; - $uri = DI::atpProcessor()->fetchMissingPost($uri, $hookData['uid'], Item::PR_FETCHED, 0, 0); - Logger::debug('Got post', ['did' => $did, 'cid' => $matches[2], 'result' => $uri]); + Logger::debug('Got post', ['uri' => $uri]); if (!empty($uri)) { $item = Post::selectFirst(['id'], ['uri' => $uri, 'uid' => $hookData['uid']]); if (!empty($item['id'])) { From 995e81e951a7525f4aa9bbceb661dd0fc8e548ae Mon Sep 17 00:00:00 2001 From: Philipp Date: Wed, 1 Jan 2025 20:06:43 +0100 Subject: [PATCH 303/388] [CI] Fix releaser --- .woodpecker/.code_standards_check.yml | 2 +- .woodpecker/.continuous-deployment.yml | 2 +- .woodpecker/.messages.po_check.yml | 2 +- .woodpecker/.phpunit.yml | 2 +- .woodpecker/.releaser.yml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.woodpecker/.code_standards_check.yml b/.woodpecker/.code_standards_check.yml index fb5be33c5..50872d4c6 100644 --- a/.woodpecker/.code_standards_check.yml +++ b/.woodpecker/.code_standards_check.yml @@ -1,6 +1,6 @@ skip_clone: true -pipeline: +steps: clone_friendica_base: image: alpine/git commands: diff --git a/.woodpecker/.continuous-deployment.yml b/.woodpecker/.continuous-deployment.yml index 4d3bc5b78..6b41deaed 100644 --- a/.woodpecker/.continuous-deployment.yml +++ b/.woodpecker/.continuous-deployment.yml @@ -5,7 +5,7 @@ labels: skip_clone: true -pipeline: +steps: clone_friendica_base: image: alpine/git commands: diff --git a/.woodpecker/.messages.po_check.yml b/.woodpecker/.messages.po_check.yml index aa40ab4ee..e0239dcd2 100644 --- a/.woodpecker/.messages.po_check.yml +++ b/.woodpecker/.messages.po_check.yml @@ -1,6 +1,6 @@ skip_clone: true -pipeline: +steps: clone_friendica_base: image: alpine/git commands: diff --git a/.woodpecker/.phpunit.yml b/.woodpecker/.phpunit.yml index 6acbf787c..8b840f806 100644 --- a/.woodpecker/.phpunit.yml +++ b/.woodpecker/.phpunit.yml @@ -17,7 +17,7 @@ labels: skip_clone: true -pipeline: +steps: clone_friendica_base: image: alpine/git commands: diff --git a/.woodpecker/.releaser.yml b/.woodpecker/.releaser.yml index f12697b93..2d880a6b3 100644 --- a/.woodpecker/.releaser.yml +++ b/.woodpecker/.releaser.yml @@ -5,7 +5,7 @@ labels: skip_clone: true -pipeline: +steps: clone_friendica_base: image: alpine/git commands: From d034e311cbe5c45f808baf0c88efd88c484acd76 Mon Sep 17 00:00:00 2001 From: Matthew Exon Date: Sun, 5 Jan 2025 21:51:37 +0100 Subject: [PATCH 304/388] Ratioed: add help link --- ratioed/templates/ratioed.tpl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ratioed/templates/ratioed.tpl b/ratioed/templates/ratioed.tpl index 0d81b0d7a..5d92bff23 100644 --- a/ratioed/templates/ratioed.tpl +++ b/ratioed/templates/ratioed.tpl @@ -2,7 +2,10 @@
-

{{$title}} - {{$page}} ({{$count}})

+

+ {{$title}} - {{$page}} ({{$count}}) + +

{{$h_newuser}}

From 8e65141cb5e04be141ee0489d28aa8be62155553 Mon Sep 17 00:00:00 2001 From: Matthew Exon Date: Sun, 5 Jan 2025 21:57:18 +0100 Subject: [PATCH 305/388] Ratioed: bump version number --- ratioed/ratioed.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ratioed/ratioed.php b/ratioed/ratioed.php index 8ae0d48c7..581ef89b6 100644 --- a/ratioed/ratioed.php +++ b/ratioed/ratioed.php @@ -2,7 +2,7 @@ /** * Name: Ratioed * Description: Additional moderation user table with statistics about user behaviour - * Version: 0.1 + * Version: 0.2 * Author: Matthew Exon */ From 2ef9cb8add8bc28a5d6dea9f40276abea2814d97 Mon Sep 17 00:00:00 2001 From: Matthew Exon Date: Sat, 11 Jan 2025 19:36:06 +0100 Subject: [PATCH 306/388] Ratioed: fill in zeroes for empty values --- ratioed/RatioedPanel.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ratioed/RatioedPanel.php b/ratioed/RatioedPanel.php index bd9b44dcd..dac71752a 100644 --- a/ratioed/RatioedPanel.php +++ b/ratioed/RatioedPanel.php @@ -175,8 +175,10 @@ class RatioedPanel extends Active $user['ratioed'] = (float)($user['ratio']) >= 2.0; } else { + $user['reactions'] = 0; if ($user['comments'] == 0) { - $user['ratio'] = '0'; + $user['comments'] = 0; + $user['ratio'] = 0; $user['ratioed'] = false; } else { From d495810b2daf9e278cf317df9a12702b136d131c Mon Sep 17 00:00:00 2001 From: Matthew Exon Date: Sat, 11 Jan 2025 19:36:38 +0100 Subject: [PATCH 307/388] Ratioed: allow both sorting directions --- ratioed/RatioedPanel.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ratioed/RatioedPanel.php b/ratioed/RatioedPanel.php index dac71752a..08d94167e 100644 --- a/ratioed/RatioedPanel.php +++ b/ratioed/RatioedPanel.php @@ -70,10 +70,10 @@ class RatioedPanel extends Active $order = 'last-item'; $order_direction = '-'; - if (!empty($request['o'])) { - $new_order = $request['o']; - if ($new_order[0] === '-') { - $order_direction = '-'; + if (!empty($_REQUEST['o'])) { + $new_order = $_REQUEST['o']; + if ($new_order[0] === '+') { + $order_direction = '+'; $new_order = substr($new_order, 1); } From 81639ff61574c38769c3693bec6054b1b27bfefc Mon Sep 17 00:00:00 2001 From: Matthew Exon Date: Sat, 11 Jan 2025 19:38:29 +0100 Subject: [PATCH 308/388] Ratioed: fix sorting by columns --- ratioed/templates/ratioed.tpl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ratioed/templates/ratioed.tpl b/ratioed/templates/ratioed.tpl index 5d92bff23..d634993ec 100644 --- a/ratioed/templates/ratioed.tpl +++ b/ratioed/templates/ratioed.tpl @@ -22,9 +22,9 @@
- + {{if $order_users == $th.1}} {{if $order_direction_users == "+"}} ↓ @@ -66,11 +66,7 @@ {{$u.login_date}}{{$u.lastitem_date}}
From b360b553eddf3a7ad01c06f7b050b1a69734cdc7 Mon Sep 17 00:00:00 2001 From: Matthew Exon Date: Sat, 11 Jan 2025 20:07:18 +0100 Subject: [PATCH 310/388] Ratioed: remove actions --- ratioed/RatioedPanel.php | 30 ++++-------------------------- ratioed/templates/ratioed.tpl | 26 ++------------------------ 2 files changed, 6 insertions(+), 50 deletions(-) diff --git a/ratioed/RatioedPanel.php b/ratioed/RatioedPanel.php index 08d94167e..19f6dd446 100644 --- a/ratioed/RatioedPanel.php +++ b/ratioed/RatioedPanel.php @@ -24,7 +24,6 @@ class RatioedPanel extends Active return Renderer::replaceMacros($template, array('$config' => DI::baseUrl() . '/settings/addon')); } - $action = $this->parameters['action'] ?? ''; $uid = $this->parameters['uid'] ?? 0; $user = []; @@ -32,31 +31,10 @@ class RatioedPanel extends Active $user = User::getById($uid, ['username', 'blocked']); if (!$user) { $this->systemMessages->addNotice($this->t('User not found')); - $this->baseUrl->redirect('moderation/users'); + $this->baseUrl->redirect('ratioed'); } } - switch ($action) { - case 'delete': - if ($this->session->getLocalUserId() != $uid) { - self::checkFormSecurityTokenRedirectOnError('moderation/users/active', 'moderation_users_active', 't'); - // delete user - User::remove($uid); - - $this->systemMessages->addNotice($this->t('User "%s" deleted', $user['username'])); - } else { - $this->systemMessages->addNotice($this->t('You can\'t remove yourself')); - } - - $this->baseUrl->redirect('moderation/users/active'); - break; - case 'block': - self::checkFormSecurityTokenRedirectOnError('moderation/users/active', 'moderation_users_active', 't'); - User::block($uid); - $this->systemMessages->addNotice($this->t('User "%s" blocked', $user['username'])); - $this->baseUrl->redirect('moderation/users/active'); - break; - } $pager = new Pager($this->l10n, $this->args->getQueryString(), 100); $valid_orders = [ @@ -69,11 +47,11 @@ class RatioedPanel extends Active ]; $order = 'last-item'; - $order_direction = '-'; + $order_direction = '+'; if (!empty($_REQUEST['o'])) { $new_order = $_REQUEST['o']; - if ($new_order[0] === '+') { - $order_direction = '+'; + if ($new_order[0] === '-') { + $order_direction = '-'; $new_order = substr($new_order, 1); } diff --git a/ratioed/templates/ratioed.tpl b/ratioed/templates/ratioed.tpl index c64cb1dc0..24ae20b8e 100644 --- a/ratioed/templates/ratioed.tpl +++ b/ratioed/templates/ratioed.tpl @@ -11,12 +11,7 @@
- + {{foreach $th_users as $k=>$th}} {{if $k < 2 || $order_users == $th.1 || ($k==4 && !in_array($order_users,[$th_users.2.1, $th_users.3.1, $th_users.5.1])) }} @@ -42,16 +37,7 @@ {{foreach $users as $u}} - + @@ -151,14 +137,6 @@ {{/foreach}}
-
- - -
-
- {{if $u.is_deletable}} -
- - -
- {{else}} -   - {{/if}} -
{{$u.name}} {{$u.email}}
- {{$pager nofilter}} From 3441c9bd0e7bcf713b5358a3d316c091af1c459a Mon Sep 17 00:00:00 2001 From: Matthew Exon Date: Sun, 5 Jan 2025 00:23:51 +0100 Subject: [PATCH 311/388] Ratioed: add statistics about reply likes and reply guy score --- ratioed/RatioedPanel.php | 137 ++++++++++++++++++++++++++++++++++ ratioed/templates/help.tpl | 57 +++++++++++++- ratioed/templates/ratioed.tpl | 2 +- 3 files changed, 192 insertions(+), 4 deletions(-) diff --git a/ratioed/RatioedPanel.php b/ratioed/RatioedPanel.php index 19f6dd446..33a009cde 100644 --- a/ratioed/RatioedPanel.php +++ b/ratioed/RatioedPanel.php @@ -8,7 +8,9 @@ use Friendica\Core\Renderer; use Friendica\Database\DBA; use Friendica\DI; use Friendica\Model\User; +use Friendica\Model\Verb; use Friendica\Module\Moderation\Users\Active; +use Friendica\Protocol\Activity; /** * This class implements the "Behaviour" panel in Moderation/Users @@ -75,6 +77,11 @@ class RatioedPanel extends Active $this->t('Comments last 24h'), $this->t('Reactions last 24h'), $this->t('Ratio last 24h'), + $this->t('Replies last month'), + $this->t('Reply likes'), + $this->t('Respondee likes'), + $this->t('OP likes'), + $this->t('Reply guy score'), ]; $field_names = [ 'name', @@ -87,6 +94,11 @@ class RatioedPanel extends Active 'comments', 'reactions', 'ratio', + 'reply_count', + 'reply_likes', + 'reply_respondee_likes', + 'reply_op_likes', + 'reply_guy_score', ]; $th_users = array_map(null, $header_titles, $valid_orders, $field_names); @@ -125,6 +137,129 @@ class RatioedPanel extends Active ]); } + protected function getReplyGuyRow($contact_uid) + { + $like_vid = Verb::getID(Activity::LIKE); + $post_vid = Verb::getID(Activity::POST); + + /* + * This is a complicated query. + * + * The innermost select retrieves a chain of four posts: an + * original post, a target comment (possibly deep down in the + * thread), a reply from our user, and a like for that reply. + * If there's no like, we still want to count the reply, so we + * use an outer join. + * + * The second select adds "points" for different kinds of + * likes. The outermost select then counts up these points, + * and the number of distinct replies. + */ + $reply_guy_result = DBA::p(' +SELECT + COUNT(distinct reply_id) AS replies_total, + SUM(like_point) AS like_total, + SUM(target_like_point) AS target_like_total, + SUM(original_like_point) AS original_like_total +FROM ( + SELECT + reply_id, + like_date, + like_date IS NOT NULL AS like_point, + like_author = target_author AS target_like_point, + like_author = original_author AS original_like_point + FROM ( + SELECT + original_post.`uri-id` AS original_id, + original_post.`author-id` AS original_author, + original_post.created AS original_date, + target_post.`uri-id` AS target_id, + target_post.`author-id` AS target_author, + target_post.created AS target_date, + reply_post.`uri-id` AS reply_id, + reply_post.`author-id` AS reply_author, + reply_post.created AS reply_date, + like_post.`uri-id` AS like_id, + like_post.`author-id` AS like_author, + like_post.created AS like_date + FROM + post AS original_post + JOIN + post AS target_post + ON + original_post.`uri-id` = target_post.`parent-uri-id` + JOIN + post AS reply_post + ON + target_post.`uri-id` = reply_post.`thr-parent-id` AND + reply_post.`author-id` = ? AND + reply_post.`author-id` != target_post.`author-id` AND + reply_post.`author-id` != original_post.`author-id` AND + reply_post.`uri-id` != reply_post.`thr-parent-id` AND + reply_post.vid = ? AND + reply_post.created > CURDATE() - INTERVAL 1 MONTH + LEFT OUTER JOIN + post AS like_post + ON + reply_post.`uri-id` = like_post.`thr-parent-id` AND + like_post.vid = ? AND + like_post.`author-id` != reply_post.`author-id` + ) AS post_meta +) AS reply_counts +', $contact_uid, $post_vid, $like_vid); + return $reply_guy_result; + } + + // https://stackoverflow.com/a/48283297/235936 + protected function sigFig($value, $digits) + { + if ($value == 0) { + $decimalPlaces = $digits - 1; + } elseif ($value < 0) { + $decimalPlaces = $digits - floor(log10($value * -1)) - 1; + } else { + $decimalPlaces = $digits - floor(log10($value)) - 1; + } + + $answer = ($decimalPlaces > 0) ? + number_format($value, $decimalPlaces) : round($value, $decimalPlaces); + return $answer; + } + + protected function fillReplyGuyData(&$user) { + $reply_guy_result = $this->getReplyGuyRow($user['user_contact_uid']); + if (DBA::isResult($reply_guy_result)) { + $reply_guy_result_row = DBA::fetch($reply_guy_result); + $user['reply_count'] = $reply_guy_result_row['replies_total'] ?? 0; + $user['reply_likes'] = $reply_guy_result_row['like_total'] ?? 0; + $user['reply_respondee_likes'] = $reply_guy_result_row['target_like_total'] ?? 0; + $user['reply_op_likes'] = $reply_guy_result_row['original_like_total'] ?? 0; + + $denominator = $user['reply_likes'] + $user['reply_respondee_likes'] + $user['reply_op_likes']; + if ($user['reply_count'] == 0) { + $user['reply_guy'] = false; + $user['reply_guy_score'] = 0; + } + elseif ($denominator == 0) { + $user['reply_guy'] = true; + $user['reply_guy_score'] = '∞'; + } + else { + $reply_guy_score = $user['reply_count'] / $denominator; + $user['reply_guy'] = $reply_guy_score >= 1.0; + $user['reply_guy_score'] = $this->sigFig($reply_guy_score, 2); + } + } + else { + $user['reply_count'] = "error"; + $user['reply_likes'] = "error"; + $user['reply_respondee_likes'] = "error"; + $user['reply_op_likes'] = "error"; + $user['reply_guy'] = false; + $user['reply_guy_score'] = 0; + } + } + protected function setupUserCallback(): \Closure { Logger::debug("ratioed: setupUserCallback"); @@ -179,6 +314,8 @@ class RatioedPanel extends Active $user['ratioed'] = false; } + $this->fillReplyGuyData($user); + $user = $parentCallback($user); Logger::debug("ratioed: setupUserCallback", [ 'uid' => $user['uid'], diff --git a/ratioed/templates/help.tpl b/ratioed/templates/help.tpl index fee47e34b..db6480cff 100644 --- a/ratioed/templates/help.tpl +++ b/ratioed/templates/help.tpl @@ -2,7 +2,7 @@

Ratioed Plugin Help

- This plugin provides administrators with additional statistics about + This plugin provides moderators with additional statistics about the behaviour of users. These may be useful as early warning signs that warrant more carefully watching the behaviour of a user. They are not suitable as a trigger for instantly blocking, @@ -28,7 +28,7 @@

This plugin allows viewing of an actual ratio, calculated over the last 24 hours. This is a useful timeframe for sudden dogpiling - events that administrators might not otherwise notice. The plugin + events that moderators might not otherwise notice. The plugin also calculates other statistics.

Explanation of Statistics

@@ -68,10 +68,61 @@ 24h". It is intended to approximate the traditional ratio as understood on Twitter.

+

Replies last month

+

+ This is the number of times the user posted a reply to someone any time in the last month. +

+

Reply likes

+

+ This is the number of likes received by the user on their + replies to other people's posts in the last month. Replies that + receive likes can be assumed to be more of a valuable + contribution than replies that do not. +

+

Respondee likes

+

+ The number of times in the last month the user replied to + someone else's comment and that person then liked the reply. + Likes to replies are not necessarily a positive thing, but if + the person you're replying to approves the reply, that's a very + good sign. Of course it's also common in a debate for neither + side to like the other side's comments, but the debate still can + be valuable. +

+

OP likes

+

+ The number of times in the last month the user replied on a + thread and the original poster that started the thread liked the + reply. While there is no formal concept of "ownership" of a + thread, conventionally the original poster is assumed to have + started the thread for a reason, and making replies that do not + fulfil that purpose are bad etiquette. Getting approval from + the original poster therefore is a good sign that the user is + posting replies that are wanted. +

+

Reply guy score

+

+ A "reply + guy" is a common Internet phenomenon of people (disproportionately male) + posting unwanted comments on other (disproportionately female) + people's threads, derailing the + conversation. This score loosely approximates this phenomenon, + as the ratio betwen the number of replies and the sum of likes, + respondee likes, and OP likes. This formula gives extra weight + to particularly relevant likes: a reply to a top-level post that + is liked by the original poster scores the maximum of 3 + "points". A score above 1.0 might indicate cause for concern + for moderators. +

+

+ Since this is indicative of long-term behaviour, the score is + calculated over a month instead of 24 hours. +

+

Performance

The statistics are computed from scratch each time the page loads. - It's possible that this might put a heavy load on the database. and + It's possible that this might put a heavy load on the database, and the page may take a long time to load.

Extending

diff --git a/ratioed/templates/ratioed.tpl b/ratioed/templates/ratioed.tpl index 24ae20b8e..6ee6b1d01 100644 --- a/ratioed/templates/ratioed.tpl +++ b/ratioed/templates/ratioed.tpl @@ -36,7 +36,7 @@ {{foreach $users as $u}} - + {{$u.name}} From 8ba4cd5f6140a1ad64ad5404e603ed76b8d535f3 Mon Sep 17 00:00:00 2001 From: Matthew Exon Date: Sat, 11 Jan 2025 19:42:03 +0100 Subject: [PATCH 312/388] Ratioed: bump version number --- ratioed/ratioed.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ratioed/ratioed.php b/ratioed/ratioed.php index 581ef89b6..443fdaa90 100644 --- a/ratioed/ratioed.php +++ b/ratioed/ratioed.php @@ -2,7 +2,7 @@ /** * Name: Ratioed * Description: Additional moderation user table with statistics about user behaviour - * Version: 0.2 + * Version: 0.3 * Author: Matthew Exon */ From 807598dbd03b9dca3c3ac7d890fe0cb2f8a1bb9f Mon Sep 17 00:00:00 2001 From: Matthew Exon Date: Wed, 15 Jan 2025 19:32:55 +0100 Subject: [PATCH 313/388] Ratioed: wrap long lines --- ratioed/templates/help.tpl | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/ratioed/templates/help.tpl b/ratioed/templates/help.tpl index db6480cff..0d012ca7a 100644 --- a/ratioed/templates/help.tpl +++ b/ratioed/templates/help.tpl @@ -70,7 +70,9 @@

Replies last month

- This is the number of times the user posted a reply to someone any time in the last month. + This is the number of times the user posted a reply to someone + else, on a thread the user did not start, any time in the last + month.

Reply likes

@@ -86,8 +88,8 @@ Likes to replies are not necessarily a positive thing, but if the person you're replying to approves the reply, that's a very good sign. Of course it's also common in a debate for neither - side to like the other side's comments, but the debate still can - be valuable. + side to like the other side's comments without that indicating + an unhealthy interaction, so interpret this statistic cautiously.

OP likes

@@ -103,10 +105,10 @@

Reply guy score

A "reply - guy" is a common Internet phenomenon of people (disproportionately male) - posting unwanted comments on other (disproportionately female) - people's threads, derailing the - conversation. This score loosely approximates this phenomenon, + guy" is a common Internet phenomenon of people + (disproportionately male) posting unwanted comments on other + (disproportionately female) people's threads, derailing the + conversation. This score loosely quantifies this phenomenon, as the ratio betwen the number of replies and the sum of likes, respondee likes, and OP likes. This formula gives extra weight to particularly relevant likes: a reply to a top-level post that From ee8c852d38cd74ca770a8d2445c4975607260bfc Mon Sep 17 00:00:00 2001 From: Matthew Exon Date: Wed, 15 Jan 2025 19:33:11 +0100 Subject: [PATCH 314/388] Ratioed: remove action buttons --- ratioed/templates/ratioed.tpl | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/ratioed/templates/ratioed.tpl b/ratioed/templates/ratioed.tpl index 6ee6b1d01..2413ed9d2 100644 --- a/ratioed/templates/ratioed.tpl +++ b/ratioed/templates/ratioed.tpl @@ -121,18 +121,7 @@ {{/foreach}} - - {{if $u.is_deletable}} - - - - - - - {{else}} -   - {{/if}} - + {{/foreach}} From cb70a4eaffa1e603c5a910211118deab02e519e8 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 18 Jan 2025 15:25:50 +0000 Subject: [PATCH 315/388] Fix codestyle --- ratioed/RatioedPanel.php | 111 ++++++++++++++++++--------------------- 1 file changed, 52 insertions(+), 59 deletions(-) diff --git a/ratioed/RatioedPanel.php b/ratioed/RatioedPanel.php index 33a009cde..d0fac8adf 100644 --- a/ratioed/RatioedPanel.php +++ b/ratioed/RatioedPanel.php @@ -163,47 +163,47 @@ SELECT SUM(original_like_point) AS original_like_total FROM ( SELECT - reply_id, - like_date, - like_date IS NOT NULL AS like_point, - like_author = target_author AS target_like_point, - like_author = original_author AS original_like_point + reply_id, + like_date, + like_date IS NOT NULL AS like_point, + like_author = target_author AS target_like_point, + like_author = original_author AS original_like_point FROM ( - SELECT - original_post.`uri-id` AS original_id, - original_post.`author-id` AS original_author, - original_post.created AS original_date, - target_post.`uri-id` AS target_id, - target_post.`author-id` AS target_author, - target_post.created AS target_date, - reply_post.`uri-id` AS reply_id, - reply_post.`author-id` AS reply_author, - reply_post.created AS reply_date, - like_post.`uri-id` AS like_id, - like_post.`author-id` AS like_author, - like_post.created AS like_date - FROM - post AS original_post - JOIN - post AS target_post - ON - original_post.`uri-id` = target_post.`parent-uri-id` - JOIN - post AS reply_post - ON - target_post.`uri-id` = reply_post.`thr-parent-id` AND - reply_post.`author-id` = ? AND - reply_post.`author-id` != target_post.`author-id` AND - reply_post.`author-id` != original_post.`author-id` AND - reply_post.`uri-id` != reply_post.`thr-parent-id` AND - reply_post.vid = ? AND - reply_post.created > CURDATE() - INTERVAL 1 MONTH - LEFT OUTER JOIN - post AS like_post - ON - reply_post.`uri-id` = like_post.`thr-parent-id` AND - like_post.vid = ? AND - like_post.`author-id` != reply_post.`author-id` + SELECT + original_post.`uri-id` AS original_id, + original_post.`author-id` AS original_author, + original_post.created AS original_date, + target_post.`uri-id` AS target_id, + target_post.`author-id` AS target_author, + target_post.created AS target_date, + reply_post.`uri-id` AS reply_id, + reply_post.`author-id` AS reply_author, + reply_post.created AS reply_date, + like_post.`uri-id` AS like_id, + like_post.`author-id` AS like_author, + like_post.created AS like_date + FROM + post AS original_post + JOIN + post AS target_post + ON + original_post.`uri-id` = target_post.`parent-uri-id` + JOIN + post AS reply_post + ON + target_post.`uri-id` = reply_post.`thr-parent-id` AND + reply_post.`author-id` = ? AND + reply_post.`author-id` != target_post.`author-id` AND + reply_post.`author-id` != original_post.`author-id` AND + reply_post.`uri-id` != reply_post.`thr-parent-id` AND + reply_post.vid = ? AND + reply_post.created > CURDATE() - INTERVAL 1 MONTH + LEFT OUTER JOIN + post AS like_post + ON + reply_post.`uri-id` = like_post.`thr-parent-id` AND + like_post.vid = ? AND + like_post.`author-id` != reply_post.`author-id` ) AS post_meta ) AS reply_counts ', $contact_uid, $post_vid, $like_vid); @@ -226,7 +226,8 @@ FROM ( return $answer; } - protected function fillReplyGuyData(&$user) { + protected function fillReplyGuyData(&$user) + { $reply_guy_result = $this->getReplyGuyRow($user['user_contact_uid']); if (DBA::isResult($reply_guy_result)) { $reply_guy_result_row = DBA::fetch($reply_guy_result); @@ -235,22 +236,19 @@ FROM ( $user['reply_respondee_likes'] = $reply_guy_result_row['target_like_total'] ?? 0; $user['reply_op_likes'] = $reply_guy_result_row['original_like_total'] ?? 0; - $denominator = $user['reply_likes'] + $user['reply_respondee_likes'] + $user['reply_op_likes']; + $denominator = (int)($user['reply_likes'] + $user['reply_respondee_likes'] + $user['reply_op_likes']); if ($user['reply_count'] == 0) { $user['reply_guy'] = false; $user['reply_guy_score'] = 0; - } - elseif ($denominator == 0) { + } elseif ($denominator == 0) { $user['reply_guy'] = true; $user['reply_guy_score'] = '∞'; - } - else { + } else { $reply_guy_score = $user['reply_count'] / $denominator; $user['reply_guy'] = $reply_guy_score >= 1.0; $user['reply_guy_score'] = $this->sigFig($reply_guy_score, 2); } - } - else { + } else { $user['reply_count'] = "error"; $user['reply_likes'] = "error"; $user['reply_respondee_likes'] = "error"; @@ -272,9 +270,8 @@ FROM ( if (DBA::isResult($self_contact_result)) { $self_contact_result_row = DBA::fetch($self_contact_result); $user['user_contact_uid'] = $self_contact_result_row['user_contact_uid']; - } - else { - $user['user_contact_uid'] = NULL; + } else { + $user['user_contact_uid'] = null; } if ($user['user_contact_uid']) { @@ -286,28 +283,24 @@ FROM ( if ($user['reactions'] > 0) { $user['ratio'] = number_format($user['comments'] / $user['reactions'], 1, '.', ''); $user['ratioed'] = (float)($user['ratio']) >= 2.0; - } - else { + } else { $user['reactions'] = 0; if ($user['comments'] == 0) { $user['comments'] = 0; $user['ratio'] = 0; $user['ratioed'] = false; - } - else { + } else { $user['ratio'] = '∞'; $user['ratioed'] = false; } } - } - else { + } else { $user['comments'] = 'error'; $user['reactions'] = 'error'; $user['ratio'] = 'error'; $user['ratioed'] = false; } - } - else { + } else { $user['comments'] = 'error'; $user['reactions'] = 'error'; $user['ratio'] = 'error'; From 0d0aae36cd1a5a646ddbad15e1a4f548d6f14073 Mon Sep 17 00:00:00 2001 From: Matthew Exon Date: Wed, 22 Jan 2025 08:30:30 +0100 Subject: [PATCH 316/388] Clean up phpstan warning --- ratioed/RatioedPanel.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ratioed/RatioedPanel.php b/ratioed/RatioedPanel.php index d0fac8adf..b611b2560 100644 --- a/ratioed/RatioedPanel.php +++ b/ratioed/RatioedPanel.php @@ -236,7 +236,7 @@ FROM ( $user['reply_respondee_likes'] = $reply_guy_result_row['target_like_total'] ?? 0; $user['reply_op_likes'] = $reply_guy_result_row['original_like_total'] ?? 0; - $denominator = (int)($user['reply_likes'] + $user['reply_respondee_likes'] + $user['reply_op_likes']); + $denominator = intval($user['reply_likes']) + intval($user['reply_respondee_likes']) + intval($user['reply_op_likes']); if ($user['reply_count'] == 0) { $user['reply_guy'] = false; $user['reply_guy_score'] = 0; From 2741227bfa8bb174d29a69399403f72b94e00ba2 Mon Sep 17 00:00:00 2001 From: Art4 Date: Wed, 22 Jan 2025 08:42:18 +0000 Subject: [PATCH 317/388] Add phpstan in woodpacker --- .woodpecker/.code_standards_check.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.woodpecker/.code_standards_check.yml b/.woodpecker/.code_standards_check.yml index 50872d4c6..60a1bd2ac 100644 --- a/.woodpecker/.code_standards_check.yml +++ b/.woodpecker/.code_standards_check.yml @@ -56,6 +56,10 @@ steps: - /tmp/drone-cache:/tmp/cache when: event: pull_request + phpstan: + image: friendicaci/php8.3:php8.3.3 + commands: + - ./bin/composer.phar run phpstan; check: image: friendicaci/php-cs commands: From 7a7940a8eddcd39279afc953ea136ff78f854f8a Mon Sep 17 00:00:00 2001 From: Art4 Date: Wed, 22 Jan 2025 08:46:57 +0000 Subject: [PATCH 318/388] Fix PHPStan errors --- ratioed/RatioedPanel.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ratioed/RatioedPanel.php b/ratioed/RatioedPanel.php index b611b2560..916656408 100644 --- a/ratioed/RatioedPanel.php +++ b/ratioed/RatioedPanel.php @@ -231,13 +231,13 @@ FROM ( $reply_guy_result = $this->getReplyGuyRow($user['user_contact_uid']); if (DBA::isResult($reply_guy_result)) { $reply_guy_result_row = DBA::fetch($reply_guy_result); - $user['reply_count'] = $reply_guy_result_row['replies_total'] ?? 0; - $user['reply_likes'] = $reply_guy_result_row['like_total'] ?? 0; - $user['reply_respondee_likes'] = $reply_guy_result_row['target_like_total'] ?? 0; - $user['reply_op_likes'] = $reply_guy_result_row['original_like_total'] ?? 0; + $user['reply_count'] = (int) $reply_guy_result_row['replies_total'] ?? 0; + $user['reply_likes'] = (int) $reply_guy_result_row['like_total'] ?? 0; + $user['reply_respondee_likes'] = (int) $reply_guy_result_row['target_like_total'] ?? 0; + $user['reply_op_likes'] = (int) $reply_guy_result_row['original_like_total'] ?? 0; - $denominator = intval($user['reply_likes']) + intval($user['reply_respondee_likes']) + intval($user['reply_op_likes']); - if ($user['reply_count'] == 0) { + $denominator = $user['reply_likes'] + $user['reply_respondee_likes'] + $user['reply_op_likes']; + if ($user['reply_count'] === 0) { $user['reply_guy'] = false; $user['reply_guy_score'] = 0; } elseif ($denominator == 0) { From 2b5764c132bb02390d8a417bc80e0fb28f83df07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakobus=20Sch=C3=BCrz?= Date: Wed, 15 Jan 2025 10:42:08 +0100 Subject: [PATCH 319/388] rework saml addon fix #1587 remove css-side hiding of elements, which was broken. remove them or make them readonly via javascript --- saml/saml.css | 1 - saml/saml.php | 9 ++++----- 2 files changed, 4 insertions(+), 6 deletions(-) delete mode 100644 saml/saml.css diff --git a/saml/saml.css b/saml/saml.css deleted file mode 100644 index 087633cd9..000000000 --- a/saml/saml.css +++ /dev/null @@ -1 +0,0 @@ -#settings-form > div:first-of-type, #settings-form > h2:first-of-type, #wrapper_mpassword, #wrapper_email { display: none !important; } diff --git a/saml/saml.php b/saml/saml.php index 9f065355c..f3dd17742 100755 --- a/saml/saml.php +++ b/saml/saml.php @@ -75,11 +75,6 @@ function saml_install() Hook::register('footer', __FILE__, 'saml_footer'); } -function saml_head(string &$body) -{ - DI::page()->registerStylesheet(__DIR__ . '/saml.css'); -} - function saml_footer(string &$body) { $fragment = addslashes(BBCode::convertForUriId(User::getSystemUriId(), DI::config()->get('saml', 'settings_statement'))); @@ -87,6 +82,10 @@ function saml_footer(string &$body) EOL; } From 792f50f835ebb9181f7d627282e582a153373a1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakobus=20Sch=C3=BCrz?= Date: Thu, 16 Jan 2025 18:53:05 +0100 Subject: [PATCH 320/388] fix view in vier and frio --- saml/saml.php | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/saml/saml.php b/saml/saml.php index f3dd17742..7fdafc1ea 100755 --- a/saml/saml.php +++ b/saml/saml.php @@ -83,9 +83,22 @@ function saml_footer(string &$body) var target=$("#settings-nickname-desc"); if (target.length) { target.append("

$fragment

"); } document.getElementById('id_email').setAttribute('readonly', 'readonly'); -document.getElementById('password-settings').remove(); -document.getElementById('password-settings-collapse').remove(); -document.getElementById('id_mpassword_wrapper').remove(); +if ( document.getElementById('password-settings') != null ) { + document.getElementById('password-settings').remove(); +} +if ( document.getElementById('password-settings-collapse') != null ) { + document.getElementById('password-settings-collapse').remove(); +} +if ( document.getElementById('id_mpassword_wrapper') != null ) { + document.getElementById('id_mpassword_wrapper').remove(); +} +if ( document.getElementById('wrapper_mpassword') != null ) { + document.getElementById('wrapper_mpassword').remove(); +} +if ( document.getElementById('wrapper_password') != null ) { + document.getElementById('wrapper_password').parentNode.parentNode.children[0].remove(); + document.getElementById('wrapper_password').parentNode.remove(); +} EOL; } From c50636727361a153b5ed5f445ab6afed9497e663 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakobus=20Sch=C3=BCrz?= Date: Fri, 17 Jan 2025 03:04:31 +0100 Subject: [PATCH 321/388] replace password-handling with hint also add hint to email-field --- saml/saml.php | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/saml/saml.php b/saml/saml.php index 7fdafc1ea..81a6bfcc3 100755 --- a/saml/saml.php +++ b/saml/saml.php @@ -78,26 +78,32 @@ function saml_install() function saml_footer(string &$body) { $fragment = addslashes(BBCode::convertForUriId(User::getSystemUriId(), DI::config()->get('saml', 'settings_statement'))); + $samlhint = DI::l10n()->t('managed via SAML authentication'); $body .= << var target=$("#settings-nickname-desc"); if (target.length) { target.append("

$fragment

"); } document.getElementById('id_email').setAttribute('readonly', 'readonly'); -if ( document.getElementById('password-settings') != null ) { - document.getElementById('password-settings').remove(); -} +var saml_hint = document.createElement("span"); +var saml_hint_text = document.createTextNode('$samlhint'); +saml_hint.appendChild(saml_hint_text); +document.getElementById('id_email').parentNode.insertBefore(saml_hint, document.getElementById('id_email').nextSibling); +// Frio theme if ( document.getElementById('password-settings-collapse') != null ) { - document.getElementById('password-settings-collapse').remove(); + document.getElementById('password-settings-collapse').replaceChildren(saml_hint.cloneNode(true)); } if ( document.getElementById('id_mpassword_wrapper') != null ) { + document.getElementById('id_mpassword_wrapper').parentNode.appendChild(saml_hint.cloneNode(true)); document.getElementById('id_mpassword_wrapper').remove(); + document.getElementById('id_email').nextElementSibling.classList.add('help-block'); } +// Vier theme if ( document.getElementById('wrapper_mpassword') != null ) { document.getElementById('wrapper_mpassword').remove(); + document.getElementById('id_email').nextElementSibling.classList.add('field_help'); } if ( document.getElementById('wrapper_password') != null ) { - document.getElementById('wrapper_password').parentNode.parentNode.children[0].remove(); - document.getElementById('wrapper_password').parentNode.remove(); + document.getElementById('wrapper_password').parentNode.replaceChildren(saml_hint.cloneNode(true)); } EOL; From 0b4aaac9fd16bc26511f226ed470fb4e18395e22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakobus=20Sch=C3=BCrz?= Date: Fri, 17 Jan 2025 03:24:17 +0100 Subject: [PATCH 322/388] translation for saml-hint --- saml/lang/C/messages.po | 82 ++++++++++++++++++++--------------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/saml/lang/C/messages.po b/saml/lang/C/messages.po index 05579568c..b4a4c8cef 100644 --- a/saml/lang/C/messages.po +++ b/saml/lang/C/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-05-18 07:23+0200\n" +"POT-Creation-Date: 2025-01-17 03:23+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,82 +17,82 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: saml.php:231 +#: saml.php:81 +msgid "managed via SAML authentication" +msgstr "" + +#: saml.php:246 msgid "Settings statement" msgstr "" -#: saml.php:232 -msgid "" -"A statement on the settings page explaining where the user should go to " -"change their e-mail and password. BBCode allowed." -msgstr "" - -#: saml.php:237 -msgid "IdP ID" -msgstr "" - -#: saml.php:238 -msgid "" -"Identity provider (IdP) entity URI (e.g., https://example.com/auth/realms/" -"user)." -msgstr "" - -#: saml.php:242 -msgid "Client ID" -msgstr "" - -#: saml.php:243 -msgid "Identifier assigned to client by the identity provider (IdP)." -msgstr "" - #: saml.php:247 -msgid "IdP SSO URL" -msgstr "" - -#: saml.php:248 -msgid "The URL for your identity provider's SSO endpoint." +msgid "A statement on the settings page explaining where the user should go to change their e-mail and password. BBCode allowed." msgstr "" #: saml.php:252 -msgid "IdP SLO request URL" +msgid "IdP ID" msgstr "" #: saml.php:253 -msgid "The URL for your identity provider's SLO request endpoint." +msgid "Identity provider (IdP) entity URI (e.g., https://example.com/auth/realms/user)." msgstr "" #: saml.php:257 -msgid "IdP SLO response URL" +msgid "Client ID" msgstr "" #: saml.php:258 -msgid "The URL for your identity provider's SLO response endpoint." +msgid "Identifier assigned to client by the identity provider (IdP)." msgstr "" #: saml.php:262 -msgid "SP private key" +msgid "IdP SSO URL" msgstr "" #: saml.php:263 -msgid "The private key the addon should use to authenticate." +msgid "The URL for your identity provider's SSO endpoint." msgstr "" #: saml.php:267 -msgid "SP certificate" +msgid "IdP SLO request URL" msgstr "" #: saml.php:268 -msgid "The certficate for the addon's private key." +msgid "The URL for your identity provider's SLO request endpoint." msgstr "" #: saml.php:272 -msgid "IdP certificate" +msgid "IdP SLO response URL" msgstr "" #: saml.php:273 +msgid "The URL for your identity provider's SLO response endpoint." +msgstr "" + +#: saml.php:277 +msgid "SP private key" +msgstr "" + +#: saml.php:278 +msgid "The private key the addon should use to authenticate." +msgstr "" + +#: saml.php:282 +msgid "SP certificate" +msgstr "" + +#: saml.php:283 +msgid "The certficate for the addon's private key." +msgstr "" + +#: saml.php:287 +msgid "IdP certificate" +msgstr "" + +#: saml.php:288 msgid "The x509 certficate for your identity provider." msgstr "" -#: saml.php:276 +#: saml.php:291 msgid "Save Settings" msgstr "" From 4310c1355d42e7d0c9f071866c06624afd324f3a Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 24 Jan 2025 10:53:01 +0000 Subject: [PATCH 323/388] Replace call for Logger with DI::logger() --- advancedcontentfilter/advancedcontentfilter.php | 3 +-- birdavatar/birdavatar.php | 3 +-- blackout/blackout.php | 3 +-- catavatar/catavatar.php | 3 +-- fromapp/fromapp.php | 3 +-- geonames/geonames.php | 3 +-- gnot/gnot.php | 3 +-- googlemaps/googlemaps.php | 3 +-- gravatar/gravatar.php | 3 +-- impressum/impressum.php | 3 +-- keycloakpassword/keycloakpassword.php | 3 +-- krynn/krynn.php | 3 +-- leistungsschutzrecht/leistungsschutzrecht.php | 3 +-- libravatar/libravatar.php | 3 +-- newmemberwidget/newmemberwidget.php | 3 +-- numfriends/numfriends.php | 3 +-- opmlexport/opmlexport.php | 3 +-- piwik/piwik.php | 3 +-- pumpio/pumpio_sync.php | 4 ++-- securemail/securemail.php | 3 +-- 20 files changed, 21 insertions(+), 40 deletions(-) diff --git a/advancedcontentfilter/advancedcontentfilter.php b/advancedcontentfilter/advancedcontentfilter.php index c03034cd2..aeeff77c0 100644 --- a/advancedcontentfilter/advancedcontentfilter.php +++ b/advancedcontentfilter/advancedcontentfilter.php @@ -36,7 +36,6 @@ use Friendica\BaseModule; use Friendica\Content\Text\Markdown; use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\Database\DBA; use Friendica\Database\DBStructure; @@ -62,7 +61,7 @@ function advancedcontentfilter_install() Hook::add('dbstructure_definition' , __FILE__, 'advancedcontentfilter_dbstructure_definition'); DBStructure::performUpdate(); - Logger::notice('installed advancedcontentfilter'); + DI::logger()->notice('installed advancedcontentfilter'); } /* diff --git a/birdavatar/birdavatar.php b/birdavatar/birdavatar.php index 9a9dce0a6..cd49b1835 100644 --- a/birdavatar/birdavatar.php +++ b/birdavatar/birdavatar.php @@ -7,7 +7,6 @@ */ use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\Database\DBA; use Friendica\DI; @@ -27,7 +26,7 @@ function birdavatar_install() Hook::register('addon_settings', __FILE__, 'birdavatar_addon_settings'); Hook::register('addon_settings_post', __FILE__, 'birdavatar_addon_settings_post'); - Logger::info('registered birdavatar'); + DI::logger()->info('registered birdavatar'); } /** diff --git a/blackout/blackout.php b/blackout/blackout.php index a3f806ff2..ac1ee3e64 100644 --- a/blackout/blackout.php +++ b/blackout/blackout.php @@ -45,7 +45,6 @@ */ use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\Core\System; use Friendica\DI; @@ -77,7 +76,7 @@ function blackout_redirect ($b) } if (( $date1 <= $now ) && ( $now <= $date2 )) { - Logger::notice('redirecting user to blackout page'); + DI::logger()->notice('redirecting user to blackout page'); System::externalRedirect($myurl); } } diff --git a/catavatar/catavatar.php b/catavatar/catavatar.php index 2bdf0cca8..7b5f05c0d 100644 --- a/catavatar/catavatar.php +++ b/catavatar/catavatar.php @@ -7,7 +7,6 @@ */ use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\Database\DBA; use Friendica\DI; @@ -27,7 +26,7 @@ function catavatar_install() Hook::register('addon_settings', __FILE__, 'catavatar_addon_settings'); Hook::register('addon_settings_post', __FILE__, 'catavatar_addon_settings_post'); - Logger::notice('registered catavatar'); + DI::logger()->notice('registered catavatar'); } /** diff --git a/fromapp/fromapp.php b/fromapp/fromapp.php index 8bd276060..bb8a4fe61 100644 --- a/fromapp/fromapp.php +++ b/fromapp/fromapp.php @@ -8,7 +8,6 @@ */ use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\DI; @@ -17,7 +16,7 @@ function fromapp_install() Hook::register('post_local', 'addon/fromapp/fromapp.php', 'fromapp_post_hook'); Hook::register('addon_settings', 'addon/fromapp/fromapp.php', 'fromapp_settings'); Hook::register('addon_settings_post', 'addon/fromapp/fromapp.php', 'fromapp_settings_post'); - Logger::notice("installed fromapp"); + DI::logger()->notice("installed fromapp"); } function fromapp_settings_post($post) diff --git a/geonames/geonames.php b/geonames/geonames.php index d14b1e8fe..4c5e54d85 100644 --- a/geonames/geonames.php +++ b/geonames/geonames.php @@ -7,7 +7,6 @@ */ use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\DI; use Friendica\Core\Config\Util\ConfigFileManager; @@ -45,7 +44,7 @@ function geonames_post_hook(array &$item) * - The profile owner must have allowed our addon */ - Logger::notice('geonames invoked'); + DI::logger()->notice('geonames invoked'); if (!DI::userSession()->getLocalUserId()) { /* non-zero if this is a logged in user of this system */ return; diff --git a/gnot/gnot.php b/gnot/gnot.php index 5d0919cbd..3801a2101 100644 --- a/gnot/gnot.php +++ b/gnot/gnot.php @@ -9,7 +9,6 @@ */ use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\DI; use Friendica\Model\Notification; @@ -20,7 +19,7 @@ function gnot_install() Hook::register('addon_settings_post', 'addon/gnot/gnot.php', 'gnot_settings_post'); Hook::register('enotify_mail', 'addon/gnot/gnot.php', 'gnot_enotify_mail'); - Logger::notice("installed gnot"); + DI::logger()->notice("installed gnot"); } /** diff --git a/googlemaps/googlemaps.php b/googlemaps/googlemaps.php index b83a9cf99..a0bba8adf 100644 --- a/googlemaps/googlemaps.php +++ b/googlemaps/googlemaps.php @@ -8,13 +8,12 @@ */ use Friendica\Core\Hook; -use Friendica\Core\Logger; function googlemaps_install() { Hook::register('render_location', 'addon/googlemaps/googlemaps.php', 'googlemaps_location'); - Logger::notice('installed googlemaps'); + DI::logger()->notice('installed googlemaps'); } function googlemaps_location(&$item) diff --git a/gravatar/gravatar.php b/gravatar/gravatar.php index 6007c433e..7fe0d9551 100644 --- a/gravatar/gravatar.php +++ b/gravatar/gravatar.php @@ -8,7 +8,6 @@ use Friendica\BaseModule; use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\DI; use Friendica\Core\Config\Util\ConfigFileManager; @@ -20,7 +19,7 @@ function gravatar_install() { Hook::register('load_config', 'addon/gravatar/gravatar.php', 'gravatar_load_config'); Hook::register('avatar_lookup', 'addon/gravatar/gravatar.php', 'gravatar_lookup'); - Logger::notice("registered gravatar in avatar_lookup hook"); + DI::logger()->notice("registered gravatar in avatar_lookup hook"); } function gravatar_load_config(ConfigFileManager $loader) diff --git a/impressum/impressum.php b/impressum/impressum.php index f61d7182f..0ad34e405 100644 --- a/impressum/impressum.php +++ b/impressum/impressum.php @@ -9,7 +9,6 @@ use Friendica\Content\Text\BBCode; use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\DI; use Friendica\Core\Config\Util\ConfigFileManager; @@ -20,7 +19,7 @@ function impressum_install() Hook::register('load_config', 'addon/impressum/impressum.php', 'impressum_load_config'); Hook::register('about_hook', 'addon/impressum/impressum.php', 'impressum_show'); Hook::register('page_end', 'addon/impressum/impressum.php', 'impressum_footer'); - Logger::notice("installed impressum Addon"); + DI::logger()->notice("installed impressum Addon"); } /** diff --git a/keycloakpassword/keycloakpassword.php b/keycloakpassword/keycloakpassword.php index e9809f86a..11034ffe4 100644 --- a/keycloakpassword/keycloakpassword.php +++ b/keycloakpassword/keycloakpassword.php @@ -7,7 +7,6 @@ */ use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\Database\DBA; use Friendica\DI; @@ -37,7 +36,7 @@ function keycloakpassword_request($client_id, $secret, $url, $params = []) $res = curl_exec($ch); if (curl_errno($ch)) { - Logger::error(curl_error($ch)); + DI::logger()->error(curl_error($ch)); } curl_close($ch); diff --git a/krynn/krynn.php b/krynn/krynn.php index fa9db1331..b57d827e0 100644 --- a/krynn/krynn.php +++ b/krynn/krynn.php @@ -11,7 +11,6 @@ */ use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\DI; @@ -31,7 +30,7 @@ function krynn_install() Hook::register('addon_settings', 'addon/krynn/krynn.php', 'krynn_settings'); Hook::register('addon_settings_post', 'addon/krynn/krynn.php', 'krynn_settings_post'); - Logger::notice("installed krynn"); + DI::logger()->notice("installed krynn"); } function krynn_post_hook(&$item) diff --git a/leistungsschutzrecht/leistungsschutzrecht.php b/leistungsschutzrecht/leistungsschutzrecht.php index ec8091acb..891cb6cab 100644 --- a/leistungsschutzrecht/leistungsschutzrecht.php +++ b/leistungsschutzrecht/leistungsschutzrecht.php @@ -7,7 +7,6 @@ */ use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\DI; function leistungsschutzrecht_install() @@ -168,7 +167,7 @@ function leistungsschutzrecht_cron($b) if ($last) { $next = $last + 86400; if ($next > time()) { - Logger::notice('poll intervall not reached'); + DI::logger()->notice('poll intervall not reached'); return; } } diff --git a/libravatar/libravatar.php b/libravatar/libravatar.php index 4cd72c83e..6cb353317 100644 --- a/libravatar/libravatar.php +++ b/libravatar/libravatar.php @@ -8,7 +8,6 @@ use Friendica\Core\Addon; use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\DI; use Friendica\Core\Config\Util\ConfigFileManager; @@ -20,7 +19,7 @@ function libravatar_install() { Hook::register('load_config', 'addon/libravatar/libravatar.php', 'libravatar_load_config'); Hook::register('avatar_lookup', 'addon/libravatar/libravatar.php', 'libravatar_lookup'); - Logger::notice("registered libravatar in avatar_lookup hook"); + DI::logger()->notice("registered libravatar in avatar_lookup hook"); } function libravatar_load_config(ConfigFileManager $loader) diff --git a/newmemberwidget/newmemberwidget.php b/newmemberwidget/newmemberwidget.php index d3b68807a..ba7dfb392 100644 --- a/newmemberwidget/newmemberwidget.php +++ b/newmemberwidget/newmemberwidget.php @@ -8,7 +8,6 @@ use Friendica\Content\Text\BBCode; use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\DI; use Friendica\Model\User; @@ -16,7 +15,7 @@ use Friendica\Model\User; function newmemberwidget_install() { Hook::register( 'network_mod_init', 'addon/newmemberwidget/newmemberwidget.php', 'newmemberwidget_network_mod_init'); - Logger::notice('newmemberwidget installed'); + DI::logger()->notice('newmemberwidget installed'); } function newmemberwidget_network_mod_init ($b) diff --git a/numfriends/numfriends.php b/numfriends/numfriends.php index 66c9b74a1..5652c8f0d 100644 --- a/numfriends/numfriends.php +++ b/numfriends/numfriends.php @@ -7,7 +7,6 @@ */ use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\DI; @@ -16,7 +15,7 @@ function numfriends_install() { Hook::register('addon_settings', 'addon/numfriends/numfriends.php', 'numfriends_settings'); Hook::register('addon_settings_post', 'addon/numfriends/numfriends.php', 'numfriends_settings_post'); - Logger::notice("installed numfriends"); + DI::logger()->notice("installed numfriends"); } /** diff --git a/opmlexport/opmlexport.php b/opmlexport/opmlexport.php index 3df712752..be1d335cf 100644 --- a/opmlexport/opmlexport.php +++ b/opmlexport/opmlexport.php @@ -9,7 +9,6 @@ use Friendica\DI; use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Protocol; use Friendica\Model\Contact; use Friendica\Model\User; @@ -18,7 +17,7 @@ function opmlexport_install() { Hook::register('addon_settings', __FILE__, 'opmlexport_addon_settings'); Hook::register('addon_settings_post', __FILE__, 'opmlexport_addon_settings_post'); - Logger::notice('installed opmlexport Addon'); + DI::logger()->notice('installed opmlexport Addon'); } diff --git a/piwik/piwik.php b/piwik/piwik.php index fc459a875..b7e9e71c7 100644 --- a/piwik/piwik.php +++ b/piwik/piwik.php @@ -36,7 +36,6 @@ */ use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\DI; use Friendica\Core\Config\Util\ConfigFileManager; @@ -45,7 +44,7 @@ function piwik_install() { Hook::register('load_config', 'addon/piwik/piwik.php', 'piwik_load_config'); Hook::register('page_end', 'addon/piwik/piwik.php', 'piwik_analytics'); - Logger::notice("installed piwik addon"); + DI::logger()->notice("installed piwik addon"); } function piwik_load_config(ConfigFileManager $loader) diff --git a/pumpio/pumpio_sync.php b/pumpio/pumpio_sync.php index beaf6e81f..09548c6d5 100644 --- a/pumpio/pumpio_sync.php +++ b/pumpio/pumpio_sync.php @@ -1,5 +1,5 @@ DI::config()->get('system', 'maxloadavg', 50)) { - Logger::notice('system: load ' . $load[0] . ' too high. Pumpio sync deferred to next scheduled run.'); + DI::logger()->notice('system: load ' . $load[0] . ' too high. Pumpio sync deferred to next scheduled run.'); return; } } diff --git a/securemail/securemail.php b/securemail/securemail.php index b56c0cbcd..7b4123958 100644 --- a/securemail/securemail.php +++ b/securemail/securemail.php @@ -8,7 +8,6 @@ use Friendica\Addon\securemail\SecureTestEmail; use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\DI; use Friendica\Object\EMail\IEmail; @@ -22,7 +21,7 @@ function securemail_install() Hook::register('emailer_send_prepare', 'addon/securemail/securemail.php', 'securemail_emailer_send_prepare', 10); - Logger::notice('installed securemail'); + DI::logger()->notice('installed securemail'); } /** From 41f280f0c71f214e7d2c803363e83c4d5ca7dac6 Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 24 Jan 2025 11:34:33 +0000 Subject: [PATCH 324/388] Replace call for Logger with DI::logger() in blockbot addon --- blockbot/blockbot.php | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/blockbot/blockbot.php b/blockbot/blockbot.php index 022f188d4..163d0cbc6 100644 --- a/blockbot/blockbot.php +++ b/blockbot/blockbot.php @@ -11,7 +11,6 @@ use Friendica\Core\Hook; use Friendica\DI; use Jaybizzle\CrawlerDetect\CrawlerDetect; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\Core\System; use Friendica\Network\HTTPException\ForbiddenException; @@ -70,7 +69,7 @@ function blockbot_init_1() } if (empty($parts)) { - Logger::debug('Known frontend found - accept', $logdata); + DI::logger()->debug('Known frontend found - accept', $logdata); if ($isCrawler) { blockbot_save('badly-parsed-agents', $_SERVER['HTTP_USER_AGENT']); } @@ -80,66 +79,66 @@ function blockbot_init_1() blockbot_log_activitypub($_SERVER['REQUEST_URI'], $_SERVER['HTTP_USER_AGENT']); if (blockbot_is_crawler($parts)) { - Logger::debug('Crawler found - reject', $logdata); + DI::logger()->debug('Crawler found - reject', $logdata); blockbot_reject(); } if (blockbot_is_searchbot($parts)) { - Logger::debug('Search bot found - reject', $logdata); + DI::logger()->debug('Search bot found - reject', $logdata); blockbot_reject(); } if (blockbot_is_unwanted($parts)) { - Logger::debug('Uncategorized unwanted agent found - reject', $logdata); + DI::logger()->debug('Uncategorized unwanted agent found - reject', $logdata); blockbot_reject(); } if (blockbot_is_security_checker($parts)) { if (!DI::config()->get('blockbot', 'security_checker')) { - Logger::debug('Security checker found - reject', $logdata); + DI::logger()->debug('Security checker found - reject', $logdata); blockbot_reject(); } - Logger::debug('Security checker found - accept', $logdata); + DI::logger()->debug('Security checker found - accept', $logdata); return; } if (blockbot_is_social_media($parts)) { - Logger::debug('Social media service found - accept', $logdata); + DI::logger()->debug('Social media service found - accept', $logdata); return; } if (blockbot_is_fediverse_client($parts)) { - Logger::debug('Fediverse client found - accept', $logdata); + DI::logger()->debug('Fediverse client found - accept', $logdata); return; } if (blockbot_is_feed_reader($parts)) { - Logger::debug('Feed reader found - accept', $logdata); + DI::logger()->debug('Feed reader found - accept', $logdata); return; } if (blockbot_is_fediverse_tool($parts)) { - Logger::debug('Fediverse tool found - accept', $logdata); + DI::logger()->debug('Fediverse tool found - accept', $logdata); return; } if (blockbot_is_service_agent($parts)) { - Logger::debug('Service agent found - accept', $logdata); + DI::logger()->debug('Service agent found - accept', $logdata); return; } if (blockbot_is_monitor($parts)) { - Logger::debug('Monitoring service found - accept', $logdata); + DI::logger()->debug('Monitoring service found - accept', $logdata); return; } if (blockbot_is_validator($parts)) { - Logger::debug('Validation service found - accept', $logdata); + DI::logger()->debug('Validation service found - accept', $logdata); return; } if (blockbot_is_good_tool($parts)) { - Logger::debug('Uncategorized helpful service found - accept', $logdata); + DI::logger()->debug('Uncategorized helpful service found - accept', $logdata); return; } @@ -147,10 +146,10 @@ function blockbot_init_1() if (blockbot_is_http_library($parts)) { blockbot_check_login_attempt($_SERVER['REQUEST_URI'], $logdata); if (!DI::config()->get('blockbot', 'http_libraries')) { - Logger::debug('HTTP Library found - reject', $logdata); + DI::logger()->debug('HTTP Library found - reject', $logdata); blockbot_reject(); } - Logger::debug('HTTP Library found - accept', $logdata); + DI::logger()->debug('HTTP Library found - accept', $logdata); return; } @@ -161,12 +160,12 @@ function blockbot_init_1() if (!$isCrawler) { blockbot_save('good-agents', $_SERVER['HTTP_USER_AGENT']); - Logger::debug('Non-bot user agent detected', $logdata); + DI::logger()->debug('Non-bot user agent detected', $logdata); return; } blockbot_save('bad-agents', $_SERVER['HTTP_USER_AGENT']); - Logger::notice('Possible bot found - reject', $logdata); + DI::logger()->notice('Possible bot found - reject', $logdata); blockbot_reject(); } @@ -217,7 +216,7 @@ function blockbot_log_activitypub(string $url, string $agent) function blockbot_check_login_attempt(string $url, array $logdata) { if (in_array(trim(parse_url($url, PHP_URL_PATH), '/'), ['login', 'lostpass', 'register'])) { - Logger::debug('Login attempt detected - reject', $logdata); + DI::logger()->debug('Login attempt detected - reject', $logdata); blockbot_reject(); } } @@ -443,7 +442,7 @@ function blockbot_is_monitor(array $parts): bool } /** - * Services in the centralized and decentralized social media environment + * Services in the centralized and decentralized social media environment * * @param array $parts * @return boolean From d78ea50516c67f871ddb49ca18328379a95b4d57 Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 24 Jan 2025 11:36:23 +0000 Subject: [PATCH 325/388] Replace call for Logger with DI::logger() in bluesky addon --- bluesky/bluesky.php | 95 +++++++++++++++---------------- bluesky/bluesky_feed.php | 6 +- bluesky/bluesky_notifications.php | 6 +- bluesky/bluesky_timeline.php | 6 +- 4 files changed, 56 insertions(+), 57 deletions(-) diff --git a/bluesky/bluesky.php b/bluesky/bluesky.php index 5bf07afbe..7f6bb9e7a 100644 --- a/bluesky/bluesky.php +++ b/bluesky/bluesky.php @@ -30,7 +30,6 @@ use Friendica\Content\Text\Plaintext; use Friendica\Core\Cache\Enum\Duration; use Friendica\Core\Config\Util\ConfigFileManager; use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Protocol; use Friendica\Core\Renderer; use Friendica\Core\Worker; @@ -106,16 +105,16 @@ function bluesky_item_by_link(array &$hookData) if (empty($did)) { return; } - - Logger::debug('Found bluesky post', ['uri' => $hookData['uri'], 'did' => $did, 'cid' => $matches[2]]); - + + DI::logger()->debug('Found bluesky post', ['uri' => $hookData['uri'], 'did' => $did, 'cid' => $matches[2]]); + $uri = 'at://' . $did . '/app.bsky.feed.post/' . $matches[2]; } else { $uri = $hookData['uri']; } $uri = DI::atpProcessor()->fetchMissingPost($uri, $hookData['uid'], Item::PR_FETCHED, 0, 0); - Logger::debug('Got post', ['uri' => $uri]); + DI::logger()->debug('Got post', ['uri' => $uri]); if (!empty($uri)) { $item = Post::selectFirst(['id'], ['uri' => $uri, 'uid' => $hookData['uid']]); if (!empty($item['id'])) { @@ -138,7 +137,7 @@ function bluesky_follow(array &$hook_data) return; } - Logger::debug('Check if contact is bluesky', ['data' => $hook_data]); + DI::logger()->debug('Check if contact is bluesky', ['data' => $hook_data]); $contact = DBA::selectFirst('contact', [], ['network' => Protocol::BLUESKY, 'url' => $hook_data['url'], 'uid' => [0, $hook_data['uid']]]); if (empty($contact)) { return; @@ -159,7 +158,7 @@ function bluesky_follow(array &$hook_data) $activity = DI::atProtocol()->XRPCPost($hook_data['uid'], 'com.atproto.repo.createRecord', $post); if (!empty($activity->uri)) { $hook_data['contact'] = $contact; - Logger::debug('Successfully start following', ['url' => $contact['url'], 'uri' => $activity->uri]); + DI::logger()->debug('Successfully start following', ['url' => $contact['url'], 'uri' => $activity->uri]); } } @@ -213,7 +212,7 @@ function bluesky_block(array &$hook_data) if ($ucid) { Contact::remove($ucid); } - Logger::debug('Successfully blocked contact', ['url' => $hook_data['contact']['url'], 'uri' => $activity->uri]); + DI::logger()->debug('Successfully blocked contact', ['url' => $hook_data['contact']['url'], 'uri' => $activity->uri]); } } @@ -421,11 +420,11 @@ function bluesky_cron() if ($last) { $next = $last + ($poll_interval * 60); if ($next > time()) { - Logger::notice('poll interval not reached'); + DI::logger()->notice('poll interval not reached'); return; } } - Logger::notice('cron_start'); + DI::logger()->notice('cron_start'); $abandon_days = intval(DI::config()->get('system', 'account_abandon_days')); if ($abandon_days < 1) { @@ -437,19 +436,19 @@ function bluesky_cron() $pconfigs = DBA::selectToArray('pconfig', [], ["`cat` = ? AND `k` IN (?, ?) AND `v`", 'bluesky', 'import', 'import_feeds']); foreach ($pconfigs as $pconfig) { if (empty(DI::atProtocol()->getUserDid($pconfig['uid']))) { - Logger::debug('User has got no valid DID', ['uid' => $pconfig['uid']]); + DI::logger()->debug('User has got no valid DID', ['uid' => $pconfig['uid']]); continue; } if ($abandon_days != 0) { if (!DBA::exists('user', ["`uid` = ? AND `login_date` >= ?", $pconfig['uid'], $abandon_limit])) { - Logger::notice('abandoned account: timeline from user will not be imported', ['user' => $pconfig['uid']]); + DI::logger()->notice('abandoned account: timeline from user will not be imported', ['user' => $pconfig['uid']]); continue; } } // Refresh the token now, so that it doesn't need to be refreshed in parallel by the following workers - Logger::debug('Refresh the token', ['uid' => $pconfig['uid']]); + DI::logger()->debug('Refresh the token', ['uid' => $pconfig['uid']]); DI::atProtocol()->getUserToken($pconfig['uid']); $last_sync = DI::pConfig()->get($pconfig['uid'], 'bluesky', 'last_contact_sync'); @@ -463,32 +462,32 @@ function bluesky_cron() Worker::add(['priority' => Worker::PRIORITY_MEDIUM, 'force_priority' => true], 'addon/bluesky/bluesky_timeline.php', $pconfig['uid']); } if (DI::pConfig()->get($pconfig['uid'], 'bluesky', 'import_feeds')) { - Logger::debug('Fetch feeds for user', ['uid' => $pconfig['uid']]); + DI::logger()->debug('Fetch feeds for user', ['uid' => $pconfig['uid']]); $feeds = bluesky_get_feeds($pconfig['uid']); foreach ($feeds as $feed) { Worker::add(['priority' => Worker::PRIORITY_MEDIUM, 'force_priority' => true], 'addon/bluesky/bluesky_feed.php', $pconfig['uid'], $feed); } } - Logger::debug('Polling done for user', ['uid' => $pconfig['uid']]); + DI::logger()->debug('Polling done for user', ['uid' => $pconfig['uid']]); } - Logger::notice('Polling done for all users'); + DI::logger()->notice('Polling done for all users'); DI::keyValue()->set('bluesky_last_poll', time()); $last_clean = DI::keyValue()->get('bluesky_last_clean'); if (empty($last_clean) || ($last_clean + 86400 < time())) { - Logger::notice('Start contact cleanup'); + DI::logger()->notice('Start contact cleanup'); $contacts = DBA::select('account-user-view', ['id', 'pid'], ["`network` = ? AND `uid` != ? AND `rel` = ?", Protocol::BLUESKY, 0, Contact::NOTHING]); while ($contact = DBA::fetch($contacts)) { Worker::add(Worker::PRIORITY_LOW, 'MergeContact', $contact['pid'], $contact['id'], 0); } DBA::close($contacts); DI::keyValue()->set('bluesky_last_clean', time()); - Logger::notice('Contact cleanup done'); + DI::logger()->notice('Contact cleanup done'); } - Logger::notice('cron_end'); + DI::logger()->notice('cron_end'); } function bluesky_hook_fork(array &$b) @@ -508,7 +507,7 @@ function bluesky_hook_fork(array &$b) if (DI::pConfig()->get($post['uid'], 'bluesky', 'import')) { // Don't post if it isn't a reply to a bluesky post if (($post['gravity'] != Item::GRAVITY_PARENT) && !Post::exists(['id' => $post['parent'], 'network' => Protocol::BLUESKY])) { - Logger::notice('No bluesky parent found', ['item' => $post['id']]); + DI::logger()->notice('No bluesky parent found', ['item' => $post['id']]); $b['execute'] = false; return; } @@ -555,12 +554,12 @@ function bluesky_send(array &$b) } if ($b['gravity'] != Item::GRAVITY_PARENT) { - Logger::debug('Got comment', ['item' => $b]); + DI::logger()->debug('Got comment', ['item' => $b]); if ($b['deleted']) { $uri = DI::atpProcessor()->getUriClass($b['uri']); if (empty($uri)) { - Logger::debug('Not a bluesky post', ['uri' => $b['uri']]); + DI::logger()->debug('Not a bluesky post', ['uri' => $b['uri']]); return; } bluesky_delete_post($b['uri'], $b['uid']); @@ -571,12 +570,12 @@ function bluesky_send(array &$b) $parent = DI::atpProcessor()->getUriClass($b['thr-parent']); if (empty($root) || empty($parent)) { - Logger::debug('No bluesky post', ['parent' => $b['parent'], 'thr-parent' => $b['thr-parent']]); + DI::logger()->debug('No bluesky post', ['parent' => $b['parent'], 'thr-parent' => $b['thr-parent']]); return; } if ($b['gravity'] == Item::GRAVITY_COMMENT) { - Logger::debug('Posting comment', ['root' => $root, 'parent' => $parent]); + DI::logger()->debug('Posting comment', ['root' => $root, 'parent' => $parent]); bluesky_create_post($b, $root, $parent); return; } elseif (in_array($b['verb'], [Activity::LIKE, Activity::ANNOUNCE])) { @@ -635,10 +634,10 @@ function bluesky_create_activity(array $item, stdClass $parent = null) if (empty($activity->uri)) { return; } - Logger::debug('Activity done', ['return' => $activity]); + DI::logger()->debug('Activity done', ['return' => $activity]); $uri = DI::atpProcessor()->getUri($activity); Item::update(['extid' => $uri], ['guid' => $item['guid']]); - Logger::debug('Set extid', ['id' => $item['id'], 'extid' => $activity]); + DI::logger()->debug('Set extid', ['id' => $item['id'], 'extid' => $activity]); } function bluesky_create_post(array $item, stdClass $root = null, stdClass $parent = null) @@ -722,14 +721,14 @@ function bluesky_create_post(array $item, stdClass $root = null, stdClass $paren } return; } - Logger::debug('Posting done', ['return' => $parent]); + DI::logger()->debug('Posting done', ['return' => $parent]); if (empty($root)) { $root = $parent; } if (($key == 0) && ($item['gravity'] != Item::GRAVITY_PARENT)) { $uri = DI::atpProcessor()->getUri($parent); Item::update(['extid' => $uri], ['guid' => $item['guid']]); - Logger::debug('Set extid', ['id' => $item['id'], 'extid' => $uri]); + DI::logger()->debug('Set extid', ['id' => $item['id'], 'extid' => $uri]); } } } @@ -899,20 +898,20 @@ function bluesky_upload_blob(int $uid, array $photo): ?stdClass $new_size = strlen($content); if (($size != 0) && ($new_size == 0) && ($retrial == 0)) { - Logger::warning('Size is empty after resize, uploading original file', ['uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size]); + DI::logger()->warning('Size is empty after resize, uploading original file', ['uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size]); $content = Photo::getImageForPhoto($photo); } else { - Logger::info('Uploading', ['uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size]); + DI::logger()->info('Uploading', ['uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size]); } $data = DI::atProtocol()->post($uid, '/xrpc/com.atproto.repo.uploadBlob', $content, ['Content-type' => $photo['type'], 'Authorization' => ['Bearer ' . DI::atProtocol()->getUserToken($uid)]]); if (empty($data) || empty($data->blob)) { - Logger::info('Uploading failed', ['uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size]); + DI::logger()->info('Uploading failed', ['uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size]); return null; } Item::incrementOutbound(Protocol::BLUESKY); - Logger::debug('Uploaded blob', ['return' => $data, 'uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size]); + DI::logger()->debug('Uploaded blob', ['return' => $data, 'uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size]); return $data->blob; } @@ -920,11 +919,11 @@ function bluesky_delete_post(string $uri, int $uid) { $parts = DI::atpProcessor()->getUriParts($uri); if (empty($parts)) { - Logger::debug('No uri delected', ['uri' => $uri]); + DI::logger()->debug('No uri delected', ['uri' => $uri]); return; } DI::atProtocol()->XRPCPost($uid, 'com.atproto.repo.deleteRecord', $parts); - Logger::debug('Deleted', ['parts' => $parts]); + DI::logger()->debug('Deleted', ['parts' => $parts]); } function bluesky_fetch_timeline(int $uid) @@ -1026,10 +1025,10 @@ function bluesky_fetch_notifications(int $uid) foreach ($data->notifications as $notification) { $uri = DI::atpProcessor()->getUri($notification); if (Post::exists(['uri' => $uri, 'uid' => $uid]) || Post::exists(['extid' => $uri, 'uid' => $uid])) { - Logger::debug('Notification already processed', ['uid' => $uid, 'reason' => $notification->reason, 'uri' => $uri, 'indexedAt' => $notification->indexedAt]); + DI::logger()->debug('Notification already processed', ['uid' => $uid, 'reason' => $notification->reason, 'uri' => $uri, 'indexedAt' => $notification->indexedAt]); continue; } - Logger::debug('Process notification', ['uid' => $uid, 'reason' => $notification->reason, 'uri' => $uri, 'indexedAt' => $notification->indexedAt]); + DI::logger()->debug('Process notification', ['uid' => $uid, 'reason' => $notification->reason, 'uri' => $uri, 'indexedAt' => $notification->indexedAt]); switch ($notification->reason) { case 'like': $item = DI::atpProcessor()->getHeaderFromPost($notification, $uri, $uid, Conversation::PARCEL_CONNECTOR); @@ -1039,9 +1038,9 @@ function bluesky_fetch_notifications(int $uid) $item['thr-parent'] = DI::atpProcessor()->fetchMissingPost($item['thr-parent'], $uid, Item::PR_FETCHED, $item['contact-id'], 0); if (!empty($item['thr-parent'])) { $data = Item::insert($item); - Logger::debug('Got like', ['uid' => $uid, 'result' => $data, 'uri' => $uri]); + DI::logger()->debug('Got like', ['uid' => $uid, 'result' => $data, 'uri' => $uri]); } else { - Logger::info('Thread parent not found', ['uid' => $uid, 'parent' => $item['thr-parent'], 'uri' => $uri]); + DI::logger()->info('Thread parent not found', ['uid' => $uid, 'parent' => $item['thr-parent'], 'uri' => $uri]); } break; @@ -1053,37 +1052,37 @@ function bluesky_fetch_notifications(int $uid) $item['thr-parent'] = DI::atpProcessor()->fetchMissingPost($item['thr-parent'], $uid, Item::PR_FETCHED, $item['contact-id'], 0); if (!empty($item['thr-parent'])) { $data = Item::insert($item); - Logger::debug('Got repost', ['uid' => $uid, 'result' => $data, 'uri' => $uri]); + DI::logger()->debug('Got repost', ['uid' => $uid, 'result' => $data, 'uri' => $uri]); } else { - Logger::info('Thread parent not found', ['uid' => $uid, 'parent' => $item['thr-parent'], 'uri' => $uri]); + DI::logger()->info('Thread parent not found', ['uid' => $uid, 'parent' => $item['thr-parent'], 'uri' => $uri]); } break; case 'follow': $contact = DI::atpActor()->getContactByDID($notification->author->did, $uid, $uid); - Logger::debug('New follower', ['uid' => $uid, 'nick' => $contact['nick'], 'uri' => $uri]); + DI::logger()->debug('New follower', ['uid' => $uid, 'nick' => $contact['nick'], 'uri' => $uri]); break; case 'mention': $contact = DI::atpActor()->getContactByDID($notification->author->did, $uid, 0); $result = DI::atpProcessor()->fetchMissingPost($uri, $uid, Item::PR_TO, $contact['id'], 0); - Logger::debug('Got mention', ['uid' => $uid, 'nick' => $contact['nick'], 'result' => $result, 'uri' => $uri]); + DI::logger()->debug('Got mention', ['uid' => $uid, 'nick' => $contact['nick'], 'result' => $result, 'uri' => $uri]); break; case 'reply': $contact = DI::atpActor()->getContactByDID($notification->author->did, $uid, 0); $result = DI::atpProcessor()->fetchMissingPost($uri, $uid, Item::PR_COMMENT, $contact['id'], 0); - Logger::debug('Got reply', ['uid' => $uid, 'nick' => $contact['nick'], 'result' => $result, 'uri' => $uri]); + DI::logger()->debug('Got reply', ['uid' => $uid, 'nick' => $contact['nick'], 'result' => $result, 'uri' => $uri]); break; case 'quote': $contact = DI::atpActor()->getContactByDID($notification->author->did, $uid, 0); $result = DI::atpProcessor()->fetchMissingPost($uri, $uid, Item::PR_PUSHED, $contact['id'], 0); - Logger::debug('Got quote', ['uid' => $uid, 'nick' => $contact['nick'], 'result' => $result, 'uri' => $uri]); + DI::logger()->debug('Got quote', ['uid' => $uid, 'nick' => $contact['nick'], 'result' => $result, 'uri' => $uri]); break; default: - Logger::notice('Unhandled reason', ['reason' => $notification->reason, 'uri' => $uri]); + DI::logger()->notice('Unhandled reason', ['reason' => $notification->reason, 'uri' => $uri]); break; } } @@ -1114,16 +1113,16 @@ function bluesky_fetch_feed(int $uid, string $feed) $languages = $entry->post->record->langs ?? []; if (!Relay::isWantedLanguage($entry->post->record->text, 0, $contact['id'] ?? 0, $languages)) { - Logger::debug('Unwanted language detected', ['languages' => $languages, 'text' => $entry->post->record->text]); + DI::logger()->debug('Unwanted language detected', ['languages' => $languages, 'text' => $entry->post->record->text]); continue; } $causer = DI::atpActor()->getContactByDID($entry->post->author->did, $uid, 0); $uri_id = bluesky_complete_post($entry->post, $uid, Item::PR_TAG, $causer['id'], Conversation::PARCEL_CONNECTOR); if (!empty($uri_id)) { $stored = Post\Category::storeFileByURIId($uri_id, $uid, Post\Category::SUBCRIPTION, $feedname, $feedurl); - Logger::debug('Stored tag subscription for user', ['uri-id' => $uri_id, 'uid' => $uid, 'name' => $feedname, 'url' => $feedurl, 'stored' => $stored]); + DI::logger()->debug('Stored tag subscription for user', ['uri-id' => $uri_id, 'uid' => $uid, 'name' => $feedname, 'url' => $feedurl, 'stored' => $stored]); } else { - Logger::notice('Post not found', ['entry' => $entry]); + DI::logger()->notice('Post not found', ['entry' => $entry]); } if (!empty($entry->reason)) { bluesky_process_reason($entry->reason, DI::atpProcessor()->getUri($entry->post), $uid); diff --git a/bluesky/bluesky_feed.php b/bluesky/bluesky_feed.php index a20ef1b93..e4aa3fdcb 100644 --- a/bluesky/bluesky_feed.php +++ b/bluesky/bluesky_feed.php @@ -1,6 +1,6 @@ $argv[1], 'feed' => $argv[2]]); + DI::logger()->debug('Importing feed - start', ['user' => $argv[1], 'feed' => $argv[2]]); bluesky_fetch_feed($argv[1], $argv[2]); - Logger::debug('Importing feed - done', ['user' => $argv[1], 'feed' => $argv[2]]); + DI::logger()->debug('Importing feed - done', ['user' => $argv[1], 'feed' => $argv[2]]); } diff --git a/bluesky/bluesky_notifications.php b/bluesky/bluesky_notifications.php index 1fbc8f677..e1bf20471 100644 --- a/bluesky/bluesky_notifications.php +++ b/bluesky/bluesky_notifications.php @@ -1,6 +1,6 @@ $argv[1]]); + DI::logger()->notice('importing notifications - start', ['user' => $argv[1]]); bluesky_fetch_notifications($argv[1]); - Logger::notice('importing notifications - done', ['user' => $argv[1]]); + DI::logger()->notice('importing notifications - done', ['user' => $argv[1]]); } diff --git a/bluesky/bluesky_timeline.php b/bluesky/bluesky_timeline.php index fda846bab..37b22d99d 100644 --- a/bluesky/bluesky_timeline.php +++ b/bluesky/bluesky_timeline.php @@ -1,6 +1,6 @@ $argv[1]]); + DI::logger()->notice('importing timeline - start', ['user' => $argv[1]]); bluesky_fetch_timeline($argv[1]); - Logger::notice('importing timeline - done', ['user' => $argv[1]]); + DI::logger()->notice('importing timeline - done', ['user' => $argv[1]]); } From 77ebaca28102deb1c8ae398aeb18903c5188d0a6 Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 24 Jan 2025 11:37:28 +0000 Subject: [PATCH 326/388] Replace call for Logger with DI::logger() in ratioed addon --- ratioed/RatioedPanel.php | 5 ++--- ratioed/ratioed.php | 7 +++---- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/ratioed/RatioedPanel.php b/ratioed/RatioedPanel.php index 916656408..4cf5d7ff3 100644 --- a/ratioed/RatioedPanel.php +++ b/ratioed/RatioedPanel.php @@ -3,7 +3,6 @@ namespace Friendica\Addon\ratioed; use Friendica\Content\Pager; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\Database\DBA; use Friendica\DI; @@ -260,7 +259,7 @@ FROM ( protected function setupUserCallback(): \Closure { - Logger::debug("ratioed: setupUserCallback"); + DI::logger()->debug("ratioed: setupUserCallback"); $parentCallback = parent::setupUserCallback(); return function ($user) use ($parentCallback) { $blocked_count = DBA::count('user-contact', ['uid' => $user['uid'], 'is-blocked' => 1]); @@ -310,7 +309,7 @@ FROM ( $this->fillReplyGuyData($user); $user = $parentCallback($user); - Logger::debug("ratioed: setupUserCallback", [ + DI::logger()->debug("ratioed: setupUserCallback", [ 'uid' => $user['uid'], 'blocked_by' => $user['blocked_by'], 'comments' => $user['comments'], diff --git a/ratioed/ratioed.php b/ratioed/ratioed.php index 443fdaa90..5cc6d539f 100644 --- a/ratioed/ratioed.php +++ b/ratioed/ratioed.php @@ -8,7 +8,6 @@ use Friendica\Addon\ratioed\RatioedPanel; use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\DI; /** @@ -18,7 +17,7 @@ function ratioed_install() { Hook::register('moderation_users_tabs', 'addon/ratioed/ratioed.php', 'ratioed_users_tabs'); - Logger::info("ratioed: installed"); + DI::logger()->info("ratioed: installed"); } /** @@ -34,7 +33,7 @@ function ratioed_module() {} * @param array $arr Parameters, including "tabs" which is the list to modify, and "selectedTab", which is the currently selected tab ID */ function ratioed_users_tabs(array &$arr) { - Logger::debug("ratioed: users tabs"); + DI::logger()->debug("ratioed: users tabs"); array_push($arr['tabs'], [ 'label' => DI::l10n()->t('Behaviour'), @@ -50,7 +49,7 @@ function ratioed_users_tabs(array &$arr) { * @brief Displays the ratioed tab in the moderation panel */ function ratioed_content() { - Logger::debug("ratioed: content"); + DI::logger()->debug("ratioed: content"); $ratioed = DI::getDice()->create(RatioedPanel::class, [$_SERVER]); $httpException = DI::getDice()->create(Friendica\Module\Special\HTTPException::class); From 1d1a00df275d19e81fdf44580d126c2affc89f74 Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 24 Jan 2025 11:37:58 +0000 Subject: [PATCH 327/388] Replace call for Logger with DI::logger() in cld addon --- cld/cld.php | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/cld/cld.php b/cld/cld.php index 83361e2bb..d4fef6c57 100644 --- a/cld/cld.php +++ b/cld/cld.php @@ -7,7 +7,6 @@ */ use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\DI; function cld_install() @@ -18,17 +17,17 @@ function cld_install() function cld_detect_languages(array &$data) { if (!in_array('cld2', get_loaded_extensions())) { - Logger::warning('CLD2 is not installed.'); + DI::logger()->warning('CLD2 is not installed.'); return; } if (!class_exists('CLD2Detector')) { - Logger::warning('CLD2Detector class does not exist.'); + DI::logger()->warning('CLD2Detector class does not exist.'); return; } if (!class_exists('CLD2Encoding')) { - Logger::warning('CLD2Encoding class does not exist.'); + DI::logger()->warning('CLD2Encoding class does not exist.'); return; } @@ -53,7 +52,7 @@ function cld_detect_languages(array &$data) } if (!$result['is_reliable']) { - Logger::debug('Unreliable detection', ['uri-id' => $data['uri-id'], 'original' => $original, 'detected' => $detected, 'name' => $result['language_name'], 'probability' => $result['language_probability'], 'text' => $data['text']]); + DI::logger()->debug('Unreliable detection', ['uri-id' => $data['uri-id'], 'original' => $original, 'detected' => $detected, 'name' => $result['language_name'], 'probability' => $result['language_probability'], 'text' => $data['text']]); if (($original == $detected) && ($data['detected'][$original] < $result['language_probability'] / 100)) { $data['detected'][$original] = $result['language_probability'] / 100; } @@ -63,12 +62,12 @@ function cld_detect_languages(array &$data) $available = array_keys(DI::l10n()->getLanguageCodes()); if (!in_array($detected, $available)) { - Logger::debug('Unsupported language', ['uri-id' => $data['uri-id'], 'original' => $original, 'detected' => $detected, 'name' => $result['language_name'], 'probability' => $result['language_probability'], 'text' => $data['text']]); + DI::logger()->debug('Unsupported language', ['uri-id' => $data['uri-id'], 'original' => $original, 'detected' => $detected, 'name' => $result['language_name'], 'probability' => $result['language_probability'], 'text' => $data['text']]); return; } if ($original != $detected) { - Logger::debug('Detected different language', ['uri-id' => $data['uri-id'], 'original' => $original, 'detected' => $detected, 'name' => $result['language_name'], 'probability' => $result['language_probability'], 'text' => $data['text']]); + DI::logger()->debug('Detected different language', ['uri-id' => $data['uri-id'], 'original' => $original, 'detected' => $detected, 'name' => $result['language_name'], 'probability' => $result['language_probability'], 'text' => $data['text']]); } $length = count($data['detected']); From 4881e6004a9bc883714fe31eff59484a41ad8e2e Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 24 Jan 2025 11:38:27 +0000 Subject: [PATCH 328/388] Replace call for Logger with DI::logger() in diaspora addon --- diaspora/diaspora.php | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/diaspora/diaspora.php b/diaspora/diaspora.php index d6c98e342..3c4b4c0e7 100644 --- a/diaspora/diaspora.php +++ b/diaspora/diaspora.php @@ -11,7 +11,6 @@ require_once 'addon/diaspora/Diaspora_Connection.php'; use Friendica\Content\Text\BBCode; use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\Database\DBA; use Friendica\Core\Worker; @@ -186,7 +185,7 @@ function diaspora_send(array &$b) { $hostname = DI::baseUrl()->getHost(); - Logger::notice('diaspora_send: invoked'); + DI::logger()->notice('diaspora_send: invoked'); if ($b['deleted'] || ($b['private'] == Item::PRIVATE) || ($b['created'] !== $b['edited'])) { return; @@ -210,14 +209,14 @@ function diaspora_send(array &$b) return; } - Logger::info('diaspora_send: prepare posting'); + DI::logger()->info('diaspora_send: prepare posting'); $handle = DI::pConfig()->get($b['uid'], 'diaspora', 'handle'); $password = DI::pConfig()->get($b['uid'], 'diaspora', 'password'); $aspect = DI::pConfig()->get($b['uid'], 'diaspora', 'aspect'); if ($handle && $password) { - Logger::info('diaspora_send: all values seem to be okay'); + DI::logger()->info('diaspora_send: all values seem to be okay'); $title = $b['title']; $body = $b['body']; @@ -248,20 +247,20 @@ function diaspora_send(array &$b) require_once "addon/diaspora/diasphp.php"; try { - Logger::info('diaspora_send: prepare'); + DI::logger()->info('diaspora_send: prepare'); $conn = new Diaspora_Connection($handle, $password); - Logger::info('diaspora_send: try to log in ' . $handle); + DI::logger()->info('diaspora_send: try to log in ' . $handle); $conn->logIn(); - Logger::info('diaspora_send: try to send ' . $body); + DI::logger()->info('diaspora_send: try to send ' . $body); $conn->provider = $hostname; $conn->postStatusMessage($body, $aspect); - Logger::notice('diaspora_send: success'); + DI::logger()->notice('diaspora_send: success'); } catch (Exception $e) { - Logger::notice("diaspora_send: Error submitting the post: " . $e->getMessage()); + DI::logger()->notice("diaspora_send: Error submitting the post: " . $e->getMessage()); - Logger::info('diaspora_send: requeueing ' . $b['uid']); + DI::logger()->info('diaspora_send: requeueing ' . $b['uid']); Worker::defer(); } From b38c2d18be2d0174e7e5866cdbbae8cfa75b5b88 Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 24 Jan 2025 11:38:48 +0000 Subject: [PATCH 329/388] Replace call for Logger with DI::logger() in discourse addon --- discourse/discourse.php | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/discourse/discourse.php b/discourse/discourse.php index e97a4fd80..b8d0d9960 100644 --- a/discourse/discourse.php +++ b/discourse/discourse.php @@ -10,7 +10,6 @@ use Friendica\Content\Text\Markdown; use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Protocol; use Friendica\Core\Renderer; use Friendica\Database\DBA; @@ -79,13 +78,13 @@ function discourse_email_getmessage(&$message) // We do assume that all Discourse servers are running with SSL if (preg_match('=topic/(.*\d)/(.*\d)@(.*)=', $message['item']['uri'], $matches) && discourse_fetch_post_from_api($message, $matches[2], $matches[3])) { - Logger::info('Fetched comment via API (message-id mode)', ['host' => $matches[3], 'topic' => $matches[1], 'post' => $matches[2]]); + DI::logger()->info('Fetched comment via API (message-id mode)', ['host' => $matches[3], 'topic' => $matches[1], 'post' => $matches[2]]); return; } if (preg_match('=topic/(.*\d)@(.*)=', $message['item']['uri'], $matches) && discourse_fetch_topic_from_api($message, 'https://' . $matches[2], $matches[1], 1)) { - Logger::info('Fetched starting post via API (message-id mode)', ['host' => $matches[2], 'topic' => $matches[1]]); + DI::logger()->info('Fetched starting post via API (message-id mode)', ['host' => $matches[2], 'topic' => $matches[1]]); return; } @@ -95,16 +94,16 @@ function discourse_email_getmessage(&$message) } if (empty($message['item']['plink']) || !preg_match('=(http.*)/t/.*/(.*\d)/(.*\d)=', $message['item']['plink'], $matches)) { - Logger::info('This is no Discourse post'); + DI::logger()->info('This is no Discourse post'); return; } if (discourse_fetch_topic_from_api($message, $matches[1], $matches[2], $matches[3])) { - Logger::info('Fetched post via API (plink mode)', ['host' => $matches[1], 'topic' => $matches[2], 'id' => $matches[3]]); + DI::logger()->info('Fetched post via API (plink mode)', ['host' => $matches[1], 'topic' => $matches[2], 'id' => $matches[3]]); return; } - Logger::info('Fallback mode', ['plink' => $message['item']['plink']]); + DI::logger()->info('Fallback mode', ['plink' => $message['item']['plink']]); // Search in the HTML part for the discourse entry and the author profile if (!empty($message['html'])) { $message = discourse_get_html($message); @@ -121,7 +120,7 @@ function discourse_fetch_post($host, $topic, $pid) $url = $host . '/t/' . $topic . '/' . $pid . '.json'; $curlResult = DI::httpClient()->get($url); if (!$curlResult->isSuccess()) { - Logger::info('No success', ['url' => $url]); + DI::logger()->info('No success', ['url' => $url]); return false; } @@ -133,11 +132,11 @@ function discourse_fetch_post($host, $topic, $pid) /// @todo Possibly fetch missing posts here continue; } - Logger::info('Got post data from topic', $post); + DI::logger()->info('Got post data from topic', $post); return $post; } - Logger::info('Post not found', ['host' => $host, 'topic' => $topic, 'pid' => $pid]); + DI::logger()->info('Post not found', ['host' => $host, 'topic' => $topic, 'pid' => $pid]); return false; } @@ -169,7 +168,7 @@ function discourse_fetch_post_from_api(&$message, $post, $host) $message = discourse_process_post($message, $data, $hostaddr); - Logger::info('Got API data', $message); + DI::logger()->info('Got API data', $message); return true; } @@ -202,7 +201,7 @@ function discourse_get_user($post, $hostaddr) $contact['url'] = $hostaddr . '/u/' . $contact['nick']; $contact['nurl'] = Strings::normaliseLink($contact['url']); $contact['baseurl'] = $hostaddr; - Logger::info('Contact', $contact); + DI::logger()->info('Contact', $contact); $contact['id'] = Contact::getIdForURL($contact['url'], 0, false, $contact); if (!empty($contact['id'])) { $avatar = $contact['photo']; @@ -268,11 +267,11 @@ function discourse_get_html($message) $div = $doc2->importNode($result->item(0), true); $doc2->appendChild($div); $message['html'] = $doc2->saveHTML(); - Logger::info('Found html body', ['html' => $message['html']]); + DI::logger()->info('Found html body', ['html' => $message['html']]); $profile = discourse_get_profile($xpath); if (!empty($profile['url'])) { - Logger::info('Found profile', $profile); + DI::logger()->info('Found profile', $profile); $message['item']['author-id'] = Contact::getIdForURL($profile['url'], 0, false, $profile); $message['item']['author-link'] = $profile['url']; $message['item']['author-name'] = $profile['name']; @@ -288,21 +287,21 @@ function discourse_get_text($message) $text = str_replace("\r", '', $text); $pos = strpos($text, "\n---\n"); if ($pos == 0) { - Logger::info('No separator found', ['text' => $text]); + DI::logger()->info('No separator found', ['text' => $text]); return $message; } $message['text'] = trim(substr($text, 0, $pos)); - Logger::info('Found text body', ['text' => $message['text']]); + DI::logger()->info('Found text body', ['text' => $message['text']]); $message['text'] = Markdown::toBBCode($message['text']); $text = substr($text, $pos); - Logger::info('Found footer', ['text' => $text]); + DI::logger()->info('Found footer', ['text' => $text]); if (preg_match('=\((http.*/t/.*/.*\d/.*\d)\)=', $text, $link)) { $message['item']['plink'] = $link[1]; - Logger::info('Found plink', ['plink' => $message['item']['plink']]); + DI::logger()->info('Found plink', ['plink' => $message['item']['plink']]); } return $message; } From 1db552ead93ef398b6f3fb689c95d763c4d93a72 Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 24 Jan 2025 11:39:11 +0000 Subject: [PATCH 330/388] Replace call for Logger with DI::logger() in dwpost addon --- dwpost/dwpost.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dwpost/dwpost.php b/dwpost/dwpost.php index 7ce30086e..7bad85dc9 100644 --- a/dwpost/dwpost.php +++ b/dwpost/dwpost.php @@ -10,7 +10,6 @@ use Friendica\Content\Text\BBCode; use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\DI; use Friendica\Model\Item; @@ -185,12 +184,12 @@ function dwpost_send(array &$b) EOT; - Logger::debug('dwpost: data: ' . $xml); + DI::logger()->debug('dwpost: data: ' . $xml); if ($dw_blog !== 'test') { $x = DI::httpClient()->post($dw_blog, $xml, ['Content-Type' => 'text/xml'])->getBodyString(); } - Logger::info('posted to dreamwidth: ' . ($x) ? $x : ''); + DI::logger()->info('posted to dreamwidth: ' . ($x) ? $x : ''); } } From e7755584cbbd3850389495420613ebfe2b59ddb1 Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 24 Jan 2025 11:40:12 +0000 Subject: [PATCH 331/388] Replace call for Logger with DI::logger() in geocoordinates addon --- geocoordinates/geocoordinates.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/geocoordinates/geocoordinates.php b/geocoordinates/geocoordinates.php index eb56f093a..5af1defcc 100644 --- a/geocoordinates/geocoordinates.php +++ b/geocoordinates/geocoordinates.php @@ -7,7 +7,6 @@ */ use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\DI; @@ -51,25 +50,25 @@ function geocoordinates_resolve_item(array &$item) $s = DI::httpClient()->fetch('https://api.opencagedata.com/geocode/v1/json?q=' . $coords[0] . ',' . $coords[1] . '&key=' . $key . '&language=' . $language); if (!$s) { - Logger::info('API could not be queried'); + DI::logger()->info('API could not be queried'); return; } $data = json_decode($s); if ($data->status->code != '200') { - Logger::info('API returned error ' . $data->status->code . ' ' . $data->status->message); + DI::logger()->info('API returned error ' . $data->status->code . ' ' . $data->status->message); return; } if (($data->total_results == 0) || (count($data->results) == 0)) { - Logger::info('No results found for coordinates ' . $item['coord']); + DI::logger()->info('No results found for coordinates ' . $item['coord']); return; } $item['location'] = $data->results[0]->formatted; - Logger::info('Got location for coordinates ' . $coords[0] . '-' . $coords[1] . ': ' . $item['location']); + DI::logger()->info('Got location for coordinates ' . $coords[0] . '-' . $coords[1] . ': ' . $item['location']); if ($item['location'] != '') { DI::cache()->set('geocoordinates:' . $language.':' . $coords[0] . '-' . $coords[1], $item['location']); From 15a951235f1f2d2039315851eb0a38831b77c05a Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 24 Jan 2025 11:40:32 +0000 Subject: [PATCH 332/388] Replace call for Logger with DI::logger() in ifttt addon --- ifttt/ifttt.php | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/ifttt/ifttt.php b/ifttt/ifttt.php index 51fa8db81..cb23032be 100644 --- a/ifttt/ifttt.php +++ b/ifttt/ifttt.php @@ -8,7 +8,6 @@ */ use Friendica\Content\PageInfo; use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\Core\Worker; use Friendica\Database\DBA; @@ -86,16 +85,16 @@ function ifttt_post() $user = DBA::selectFirst('user', ['uid'], ['nickname' => $nickname]); if (!DBA::isResult($user)) { - Logger::info('User ' . $nickname . ' not found.'); + DI::logger()->info('User ' . $nickname . ' not found.'); return; } $uid = $user['uid']; - Logger::info('Received a post for user ' . $uid . ' from ifttt ' . print_r($_REQUEST, true)); + DI::logger()->info('Received a post for user ' . $uid . ' from ifttt ' . print_r($_REQUEST, true)); if (!isset($_REQUEST['key'])) { - Logger::notice('No key found.'); + DI::logger()->notice('No key found.'); return; } @@ -103,7 +102,7 @@ function ifttt_post() // Check the key if ($key != DI::pConfig()->get($uid, 'ifttt', 'key')) { - Logger::info('Invalid key for user ' . $uid); + DI::logger()->info('Invalid key for user ' . $uid); return; } @@ -114,7 +113,7 @@ function ifttt_post() } if (!in_array($item['type'], ['status', 'link', 'photo'])) { - Logger::info('Unknown item type ' . $item['type']); + DI::logger()->info('Unknown item type ' . $item['type']); return; } From 50023180895a4c1e70163762bd90d56d38d823ba Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 24 Jan 2025 11:41:02 +0000 Subject: [PATCH 333/388] Replace call for Logger with DI::logger() in ijpost addon --- ijpost/ijpost.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ijpost/ijpost.php b/ijpost/ijpost.php index 37c3cd45e..9fe502afd 100644 --- a/ijpost/ijpost.php +++ b/ijpost/ijpost.php @@ -10,7 +10,6 @@ use Friendica\Content\Text\BBCode; use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\DI; use Friendica\Model\Item; @@ -178,11 +177,11 @@ function ijpost_send(array &$b) EOT; - Logger::debug('ijpost: data: ' . $xml); + DI::logger()->debug('ijpost: data: ' . $xml); if ($ij_blog !== 'test') { $x = DI::httpClient()->post($ij_blog, $xml, ['Content-Type' => 'text/xml'])->getBodyString(); } - Logger::info('posted to insanejournal: ' . $x ? $x : ''); + DI::logger()->info('posted to insanejournal: ' . $x ? $x : ''); } } From 5d51c5b56ecbbc220332fd5b2bea6bb34c436e5f Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 24 Jan 2025 11:42:25 +0000 Subject: [PATCH 334/388] Replace call for Logger with DI::logger() in js_upload addon --- js_upload/js_upload.php | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/js_upload/js_upload.php b/js_upload/js_upload.php index f1d85aa32..c0a2467da 100644 --- a/js_upload/js_upload.php +++ b/js_upload/js_upload.php @@ -8,7 +8,6 @@ */ use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\DI; use Friendica\Util\Images; @@ -68,7 +67,7 @@ function js_upload_post_init(array &$b) $js_upload_jsonresponse = htmlspecialchars(json_encode($result), ENT_NOQUOTES); if (isset($result['error'])) { - Logger::info('mod/photos.php: photos_post(): error uploading photo: ' . $result['error']); + DI::logger()->info('mod/photos.php: photos_post(): error uploading photo: ' . $result['error']); echo json_encode($result); exit(); } @@ -91,7 +90,7 @@ function js_upload_post_end(int &$b) { global $js_upload_jsonresponse; - Logger::notice('upload_post_end'); + DI::logger()->notice('upload_post_end'); if (!empty($js_upload_jsonresponse)) { echo $js_upload_jsonresponse; exit(); @@ -187,6 +186,10 @@ class js_upload_qqFileUploader { private $allowedExtensions; private $sizeLimit; + + /** + * @var js_upload_qqUploadedFileXhr|js_upload_qqUploadedFileForm + */ private $file; function __construct(array $allowedExtensions = [], $sizeLimit) @@ -234,7 +237,7 @@ class js_upload_qqFileUploader $filename = $pathinfo['filename']; if (!isset($pathinfo['extension'])) { - Logger::warning('extension isn\'t set.', ['filename' => $filename]); + DI::logger()->warning('extension isn\'t set.', ['filename' => $filename]); } $ext = $pathinfo['extension'] ?? ''; From a488f2513159b44765400fa03f3351f5885e851f Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 24 Jan 2025 11:44:48 +0000 Subject: [PATCH 335/388] Replace call for Logger with DI::logger() in ldapauth addon --- ldapauth/ldapauth.php | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/ldapauth/ldapauth.php b/ldapauth/ldapauth.php index f834b4d54..b80c52266 100644 --- a/ldapauth/ldapauth.php +++ b/ldapauth/ldapauth.php @@ -30,7 +30,6 @@ */ use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Database\DBA; use Friendica\DI; use Friendica\Model\User; @@ -69,54 +68,54 @@ function ldapauth_authenticate($username, $password) $ldap_autocreateaccount_nameattribute = DI::config()->get('ldapauth', 'ldap_autocreateaccount_nameattribute'); if (!extension_loaded('ldap') || !strlen($ldap_server)) { - Logger::error('Addon not configured or missing php-ldap extension', ['extension_loaded' => extension_loaded('ldap'), 'server' => $ldap_server]); + DI::logger()->error('Addon not configured or missing php-ldap extension', ['extension_loaded' => extension_loaded('ldap'), 'server' => $ldap_server]); return false; } if (!strlen($password)) { - Logger::error('Empty password disallowed', ['provided_password_length' => strlen($password)]); + DI::logger()->error('Empty password disallowed', ['provided_password_length' => strlen($password)]); return false; } $connect = @ldap_connect($ldap_server); if ($connect === false) { - Logger::warning('Could not connect to LDAP server', ['server' => $ldap_server]); + DI::logger()->warning('Could not connect to LDAP server', ['server' => $ldap_server]); return false; } @ldap_set_option($connect, LDAP_OPT_PROTOCOL_VERSION, 3); @ldap_set_option($connect, LDAP_OPT_REFERRALS, 0); if ((@ldap_bind($connect, $ldap_binddn, $ldap_bindpw)) === false) { - Logger::warning('Could not bind to LDAP server', ['server' => $ldap_server, 'binddn' => $ldap_binddn, 'errno' => ldap_errno($connect), 'error' => ldap_error($connect)]); + DI::logger()->warning('Could not bind to LDAP server', ['server' => $ldap_server, 'binddn' => $ldap_binddn, 'errno' => ldap_errno($connect), 'error' => ldap_error($connect)]); return false; } $res = @ldap_search($connect, $ldap_searchdn, $ldap_userattr . '=' . $username); if (!$res) { - Logger::notice('LDAP user not found.', ['searchdn' => $ldap_searchdn, 'userattr' => $ldap_userattr, 'username' => $username, 'errno' => ldap_errno($connect), 'error' => ldap_error($connect)]); + DI::logger()->notice('LDAP user not found.', ['searchdn' => $ldap_searchdn, 'userattr' => $ldap_userattr, 'username' => $username, 'errno' => ldap_errno($connect), 'error' => ldap_error($connect)]); return false; } $id = @ldap_first_entry($connect, $res); if (!$id) { - Logger::notice('Could not retrieve first LDAP entry.', ['searchdn' => $ldap_searchdn, 'userattr' => $ldap_userattr, 'username' => $username, 'errno' => ldap_errno($connect), 'error' => ldap_error($connect)]); + DI::logger()->notice('Could not retrieve first LDAP entry.', ['searchdn' => $ldap_searchdn, 'userattr' => $ldap_userattr, 'username' => $username, 'errno' => ldap_errno($connect), 'error' => ldap_error($connect)]); return false; } $dn = @ldap_get_dn($connect, $id); if (!@ldap_bind($connect, $dn, $password)) { - Logger::notice('Could not authenticate LDAP user with provided password', ['errno' => ldap_errno($connect), 'error' => ldap_error($connect)]); + DI::logger()->notice('Could not authenticate LDAP user with provided password', ['errno' => ldap_errno($connect), 'error' => ldap_error($connect)]); return false; } if (strlen($ldap_group) && @ldap_compare($connect, $ldap_group, 'member', $dn) !== true) { $errno = @ldap_errno($connect); if ($errno === 32) { - Logger::notice('LDAP Access Control Group does not exist', ['errno' => $errno, 'error' => ldap_error($connect)]); + DI::logger()->notice('LDAP Access Control Group does not exist', ['errno' => $errno, 'error' => ldap_error($connect)]); } elseif ($errno === 16) { - Logger::notice('LDAP membership attribute does not exist in access control group', ['errno' => $errno, 'error' => ldap_error($connect)]); + DI::logger()->notice('LDAP membership attribute does not exist in access control group', ['errno' => $errno, 'error' => ldap_error($connect)]); } else { - Logger::notice('LDAP user isn\'t part of the authorized group', ['dn' => $dn]); + DI::logger()->notice('LDAP user isn\'t part of the authorized group', ['dn' => $dn]); } @ldap_close($connect); @@ -140,7 +139,7 @@ function ldapauth_authenticate($username, $password) $authentication = User::getAuthenticationInfo($username); return User::getById($authentication['uid']); } catch (Exception $e) { - Logger::notice('LDAP authentication error: ' . $e->getMessage()); + DI::logger()->notice('LDAP authentication error: ' . $e->getMessage()); return false; } } @@ -148,7 +147,7 @@ function ldapauth_authenticate($username, $password) function ldap_createaccount($username, $password, $email, $name) { if (!strlen($email) || !strlen($name)) { - Logger::notice('Could not create local user from LDAP data, no email or nickname provided'); + DI::logger()->notice('Could not create local user from LDAP data, no email or nickname provided'); return false; } @@ -160,10 +159,10 @@ function ldap_createaccount($username, $password, $email, $name) 'password' => $password, 'verified' => 1 ]); - Logger::info('Local user created from LDAP data', ['username' => $username, 'name' => $name]); + DI::logger()->info('Local user created from LDAP data', ['username' => $username, 'name' => $name]); return $user; } catch (Exception $ex) { - Logger::error('Could not create local user from LDAP data', ['username' => $username, 'exception' => $ex->getMessage()]); + DI::logger()->error('Could not create local user from LDAP data', ['username' => $username, 'exception' => $ex->getMessage()]); } return false; From f08750199df1a0b7833e2eaba774f41c88cfe049 Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 24 Jan 2025 11:45:25 +0000 Subject: [PATCH 336/388] Replace call for Logger with DI::logger() in libertree addon --- libertree/libertree.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libertree/libertree.php b/libertree/libertree.php index c138e5977..1489a0297 100644 --- a/libertree/libertree.php +++ b/libertree/libertree.php @@ -8,7 +8,6 @@ use Friendica\Content\Text\BBCode; use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\Database\DBA; use Friendica\DI; @@ -130,7 +129,7 @@ function libertree_post_local(array &$b) function libertree_send(array &$b) { - Logger::notice('libertree_send: invoked'); + DI::logger()->notice('libertree_send: invoked'); if ($b['deleted'] || ($b['private'] == Item::PRIVATE) || ($b['created'] !== $b['edited'])) { return; @@ -196,6 +195,6 @@ function libertree_send(array &$b) ]; $result = DI::httpClient()->post($ltree_blog, $params)->getBodyString(); - Logger::notice('libertree: ' . $result); + DI::logger()->notice('libertree: ' . $result); } } From 9ed02034f1755ae5832b96d34800a7758ad37bf5 Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 24 Jan 2025 11:46:04 +0000 Subject: [PATCH 337/388] Replace call for Logger with DI::logger() in ljpost addon --- ljpost/ljpost.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ljpost/ljpost.php b/ljpost/ljpost.php index b416c6059..fd7d1bd8e 100644 --- a/ljpost/ljpost.php +++ b/ljpost/ljpost.php @@ -10,7 +10,6 @@ use Friendica\Content\Text\BBCode; use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\DI; use Friendica\Model\Item; @@ -200,7 +199,7 @@ function ljpost_send(array &$b) EOT; - Logger::debug('ljpost: data: ' . $xml); + DI::logger()->debug('ljpost: data: ' . $xml); $x = ''; @@ -208,6 +207,6 @@ EOT; $x = DI::httpClient()->post($lj_blog, $xml, ['Content-Type' => 'text/xml'])->getBodyString(); } - Logger::info('posted to livejournal: ' . $x); + DI::logger()->info('posted to livejournal: ' . $x); } } From 9a91bae363392fd1df0849afb4a21e24de994579 Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 24 Jan 2025 11:46:30 +0000 Subject: [PATCH 338/388] Replace call for Logger with DI::logger() in mailstream addon --- mailstream/mailstream.php | 45 +++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/mailstream/mailstream.php b/mailstream/mailstream.php index 9910a63df..5228b168a 100644 --- a/mailstream/mailstream.php +++ b/mailstream/mailstream.php @@ -8,7 +8,6 @@ use Friendica\Content\Text\BBCode; use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\Core\System; use Friendica\Core\Worker; @@ -32,7 +31,7 @@ function mailstream_install() Hook::register('post_remote_end', 'addon/mailstream/mailstream.php', 'mailstream_post_hook'); Hook::register('mailstream_send_hook', 'addon/mailstream/mailstream.php', 'mailstream_send_hook'); - Logger::info("installed mailstream"); + DI::logger()->info("installed mailstream"); } /** @@ -86,7 +85,7 @@ function mailstream_generate_id(string $uri): string $host = DI::baseUrl()->getHost(); $resource = hash('md5', $uri); $message_id = "<" . $resource . "@" . $host . ">"; - Logger::debug('generated message ID', ['id' => $message_id, 'uri' => $uri]); + DI::logger()->debug('generated message ID', ['id' => $message_id, 'uri' => $uri]); return $message_id; } @@ -95,20 +94,20 @@ function mailstream_send_hook(array $data) $criteria = array('uid' => $data['uid'], 'contact-id' => $data['contact-id'], 'uri' => $data['uri']); $item = Post::selectFirst([], $criteria); if (empty($item)) { - Logger::error('could not find item'); + DI::logger()->error('could not find item'); return; } $user = User::getById($item['uid']); if (empty($user)) { - Logger::error('could not find user', ['uid' => $item['uid']]); + DI::logger()->error('could not find user', ['uid' => $item['uid']]); return; } if (!mailstream_send($data['message_id'], $item, $user)) { - Logger::debug('send failed, will retry', $data); + DI::logger()->debug('send failed, will retry', $data); if (!Worker::defer()) { - Logger::error('failed and could not defer', $data); + DI::logger()->error('failed and could not defer', $data); } } } @@ -124,32 +123,32 @@ function mailstream_send_hook(array $data) function mailstream_post_hook(array &$item) { if ($item['uid'] === 0) { - Logger::debug('mailstream: root user, skipping item ' . $item['id']); + DI::logger()->debug('mailstream: root user, skipping item ' . $item['id']); return; } if (!DI::pConfig()->get($item['uid'], 'mailstream', 'enabled')) { - Logger::debug('mailstream: not enabled.', ['item' => $item['id'], ' uid ' => $item['uid']]); + DI::logger()->debug('mailstream: not enabled.', ['item' => $item['id'], ' uid ' => $item['uid']]); return; } if (!$item['contact-id']) { - Logger::debug('no contact-id', ['item' => $item['id']]); + DI::logger()->debug('no contact-id', ['item' => $item['id']]); return; } if (!$item['uri']) { - Logger::debug('no uri', ['item' => $item['id']]); + DI::logger()->debug('no uri', ['item' => $item['id']]); return; } if ($item['verb'] == Activity::ANNOUNCE) { - Logger::debug('ignoring announce', ['item' => $item['id']]); + DI::logger()->debug('ignoring announce', ['item' => $item['id']]); return; } if (DI::pConfig()->get($item['uid'], 'mailstream', 'nolikes')) { if ($item['verb'] == Activity::LIKE) { - Logger::debug('ignoring like', ['item' => $item['id']]); + DI::logger()->debug('ignoring like', ['item' => $item['id']]); return; } if ($item['verb'] == Activity::DISLIKE) { - Logger::debug('ignoring dislike', ['item' => $item['id']]); + DI::logger()->debug('ignoring dislike', ['item' => $item['id']]); return; } } @@ -200,7 +199,7 @@ function mailstream_do_images(array &$item, array &$attachments) try { $curlResult = DI::httpClient()->get($url, HttpClientAccept::DEFAULT, [HttpClientOptions::COOKIEJAR => $cookiejar]); if (!$curlResult->isSuccess()) { - Logger::debug('mailstream: fetch image url failed', [ + DI::logger()->debug('mailstream: fetch image url failed', [ 'url' => $url, 'item_id' => $item['id'], 'return_code' => $curlResult->getReturnCode() @@ -208,7 +207,7 @@ function mailstream_do_images(array &$item, array &$attachments) continue; } } catch (InvalidArgumentException $e) { - Logger::error('exception fetching url', ['url' => $url, 'item_id' => $item['id']]); + DI::logger()->error('exception fetching url', ['url' => $url, 'item_id' => $item['id']]); continue; } $attachments[$url] = [ @@ -309,7 +308,7 @@ function mailstream_subject(array $item): string } $contact = Contact::selectFirst([], ['id' => $item['contact-id'], 'uid' => $item['uid']]); if (!DBA::isResult($contact)) { - Logger::error('no contact', [ + DI::logger()->error('no contact', [ 'item' => $item['id'], 'plink' => $item['plink'], 'contact id' => $item['contact-id'], @@ -351,16 +350,16 @@ function mailstream_subject(array $item): string function mailstream_send(string $message_id, array $item, array $user): bool { if (!is_array($item)) { - Logger::error('item is empty', ['message_id' => $message_id]); + DI::logger()->error('item is empty', ['message_id' => $message_id]); return false; } if (!$item['visible']) { - Logger::debug('item not yet visible', ['item uri' => $item['uri']]); + DI::logger()->debug('item not yet visible', ['item uri' => $item['uri']]); return false; } if (!$message_id) { - Logger::error('no message ID supplied', ['item uri' => $item['uri'], 'user email' => $user['email']]); + DI::logger()->error('no message ID supplied', ['item uri' => $item['uri'], 'user email' => $user['email']]); return true; } @@ -418,15 +417,15 @@ function mailstream_send(string $message_id, array $item, array $user): bool if (!$mail->Send()) { throw new Exception($mail->ErrorInfo); } - Logger::debug('sent message', [ + DI::logger()->debug('sent message', [ 'message ID' => $mail->MessageID, 'subject' => $mail->Subject, 'address' => $address ]); } catch (phpmailerException $e) { - Logger::debug('PHPMailer exception sending message', ['id' => $message_id, 'error' => $e->errorMessage()]); + DI::logger()->debug('PHPMailer exception sending message', ['id' => $message_id, 'error' => $e->errorMessage()]); } catch (Exception $e) { - Logger::debug('exception sending message', ['id' => $message_id, 'error' => $e->getMessage()]); + DI::logger()->debug('exception sending message', ['id' => $message_id, 'error' => $e->getMessage()]); } return true; From 9ceff8f5929d7899b91cc8b1acc26e47cd3dfce7 Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 24 Jan 2025 11:46:58 +0000 Subject: [PATCH 339/388] Replace call for Logger with DI::logger() in nominatim addon --- nominatim/nominatim.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/nominatim/nominatim.php b/nominatim/nominatim.php index a3d14af5e..3a567b7ba 100644 --- a/nominatim/nominatim.php +++ b/nominatim/nominatim.php @@ -7,7 +7,6 @@ */ use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\DI; @@ -45,19 +44,19 @@ function nominatim_resolve_item(array &$item) $s = DI::httpClient()->fetch('https://nominatim.openstreetmap.org/reverse?lat=' . $coords[0] . '&lon=' . $coords[1] . '&format=json&addressdetails=0&accept-language=' . $language); if (empty($s)) { - Logger::info('API could not be queried'); + DI::logger()->info('API could not be queried'); return; } $data = json_decode($s, true); if (empty($data['display_name'])) { - Logger::info('No results found for coordinates', ['coordinates' => $item['coord'], 'data' => $data]); + DI::logger()->info('No results found for coordinates', ['coordinates' => $item['coord'], 'data' => $data]); return; } $item['location'] = $data['display_name']; - Logger::info('Got location', ['lat' => $coords[0], 'long' => $coords[1], 'location' => $item['location']]); + DI::logger()->info('Got location', ['lat' => $coords[0], 'long' => $coords[1], 'location' => $item['location']]); if (!empty($item['location'])) { DI::cache()->set('nominatim:' . $language . ':' . $coords[0] . '-' . $coords[1], $item['location']); From 757d72c360396a06a58f91c4c9d14f7726a9f644 Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 24 Jan 2025 11:47:24 +0000 Subject: [PATCH 340/388] Replace call for Logger with DI::logger() in openstreetmap addon --- openstreetmap/openstreetmap.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/openstreetmap/openstreetmap.php b/openstreetmap/openstreetmap.php index fc5ebbbeb..bf0f54b69 100644 --- a/openstreetmap/openstreetmap.php +++ b/openstreetmap/openstreetmap.php @@ -11,7 +11,6 @@ use Friendica\Core\Cache\Enum\Duration; use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\DI; use Friendica\Core\Config\Util\ConfigFileManager; @@ -31,7 +30,7 @@ function openstreetmap_install() Hook::register('Map::getCoordinates', 'addon/openstreetmap/openstreetmap.php', 'openstreetmap_get_coordinates'); Hook::register('page_header', 'addon/openstreetmap/openstreetmap.php', 'openstreetmap_alterheader'); - Logger::notice("installed openstreetmap"); + DI::logger()->notice("installed openstreetmap"); } function openstreetmap_load_config(ConfigFileManager $loader) @@ -154,8 +153,8 @@ function openstreetmap_generate_map(array &$b) $lat = $b['lat']; // round($b['lat'], 5); $lon = $b['lon']; // round($b['lon'], 5); - Logger::debug('lat: ' . $lat); - Logger::debug('lon: ' . $lon); + DI::logger()->debug('lat: ' . $lat); + DI::logger()->debug('lon: ' . $lon); $cardlink = 'notice("installed planets"); } /** @@ -39,7 +38,7 @@ function planets_install() */ function planets_post_hook(&$item) { - Logger::notice('planets invoked'); + DI::logger()->notice('planets invoked'); if (!DI::userSession()->getLocalUserId()) { /* non-zero if this is a logged in user of this system */ From 119ba0a78e1d578d802bf87b1d39e6da35a02da6 Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 24 Jan 2025 11:48:21 +0000 Subject: [PATCH 342/388] Replace call for Logger with DI::logger() in pnut addon --- pnut/pnut.php | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/pnut/pnut.php b/pnut/pnut.php index f298997b4..5460b9915 100644 --- a/pnut/pnut.php +++ b/pnut/pnut.php @@ -14,7 +14,6 @@ use Friendica\Content\Text\BBCode; use Friendica\Content\Text\Plaintext; use Friendica\Core\Config\Util\ConfigFileManager; use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\Core\System; use Friendica\DI; @@ -76,7 +75,7 @@ function pnut_connect() try { $token = $nut->getAccessToken($callback_url); - Logger::debug('Got Token', [$token]); + DI::logger()->debug('Got Token', [$token]); $o = DI::l10n()->t('You are now authenticated with pnut.io.'); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'pnut', 'access_token', $token); } catch (phpnutException $e) { @@ -266,8 +265,8 @@ function pnut_post_hook(array &$b) return; } - Logger::notice('PNUT post invoked', ['id' => $b['id'], 'guid' => $b['guid'], 'plink' => $b['plink']]); - Logger::debug('PNUT array', $b); + DI::logger()->notice('PNUT post invoked', ['id' => $b['id'], 'guid' => $b['guid'], 'plink' => $b['plink']]); + DI::logger()->debug('PNUT array', $b); $token = DI::pConfig()->get($b['uid'], 'pnut', 'access_token'); $nut = new phpnut\phpnut($token); @@ -276,7 +275,7 @@ function pnut_post_hook(array &$b) $text = $msgarr['text']; $raw = []; - Logger::debug('PNUT msgarr', $msgarr); + DI::logger()->debug('PNUT msgarr', $msgarr); if (count($msgarr['parts']) > 1) { $tstamp = time(); @@ -292,23 +291,23 @@ function pnut_post_hook(array &$b) if ($msgarr['type'] == 'photo') { $fileraw = ['type' => 'dev.mcmillian.friendica.image', 'kind' => 'image', 'is_public' => true]; foreach ($msgarr['images'] as $image) { - Logger::debug('PNUT image', $image); + DI::logger()->debug('PNUT image', $image); if (!empty($image['id'])) { $photo = Photo::selectFirst([], ['id' => $image['id']]); - Logger::debug('PNUT selectFirst'); + DI::logger()->debug('PNUT selectFirst'); } else { $photo = Photo::createPhotoForExternalResource($image['url']); - Logger::debug('PNUT createPhotoForExternalResource'); + DI::logger()->debug('PNUT createPhotoForExternalResource'); } $picturedata = Photo::getImageForPhoto($photo); - Logger::debug('PNUT photo', $photo); + DI::logger()->debug('PNUT photo', $photo); $picurefile = tempnam(System::getTempPath(), 'pnut'); file_put_contents($picurefile, $picturedata); - Logger::debug('PNUT got file?', ['filename' => $picurefile]); + DI::logger()->debug('PNUT got file?', ['filename' => $picurefile]); $imagefile = $nut->createFile($picurefile, $fileraw); - Logger::debug('PNUT file', ['pnutimagefile' => $imagefile]); + DI::logger()->debug('PNUT file', ['pnutimagefile' => $imagefile]); unlink($picurefile); $raw['io.pnut.core.oembed'][] = ['+io.pnut.core.file' => ['file_id' => $imagefile['id'], 'file_token' => $imagefile['file_token'], 'format' => 'oembed']]; @@ -318,5 +317,5 @@ function pnut_post_hook(array &$b) $raw['io.pnut.core.crosspost'][] = ['canonical_url' => $b['plink']]; $nut->createPost($text, ['raw' => $raw]); - Logger::debug('PNUT post complete', ['id' => $b['id'], 'text' => $text, 'raw' => $raw]); + DI::logger()->debug('PNUT post complete', ['id' => $b['id'], 'text' => $text, 'raw' => $raw]); } From e32ba1ce7b0a1baad29d47df9dcb6328834fbd94 Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 24 Jan 2025 11:54:34 +0000 Subject: [PATCH 343/388] Replace call for Logger with DI::logger() in public_server addon --- public_server/public_server.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/public_server/public_server.php b/public_server/public_server.php index eb7af1e75..9cd0f6673 100644 --- a/public_server/public_server.php +++ b/public_server/public_server.php @@ -8,7 +8,6 @@ use Friendica\BaseModule; use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\Database\DBA; use Friendica\DI; @@ -47,7 +46,7 @@ function public_server_register_account($b) function public_server_cron($b) { - Logger::notice("public_server: cron start"); + DI::logger()->notice("public_server: cron start"); $users = DBA::selectToArray('user', [], ["`account_expires_on` > ? AND `account_expires_on` < ? AND `expire_notification_sent` <= ?", DBA::NULL_DATETIME, DateTimeFormat::utc('now + 5 days'), DBA::NULL_DATETIME]); @@ -96,7 +95,7 @@ function public_server_cron($b) } } - Logger::notice("public_server: cron end"); + DI::logger()->notice("public_server: cron end"); } function public_server_enotify(array &$b) From d50650b8cfe7284ee17b482f261e0a8778ad3758 Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 24 Jan 2025 11:55:13 +0000 Subject: [PATCH 344/388] Replace call for Logger with DI::logger() in pumpio addon --- pumpio/pumpio.php | 73 +++++++++++++++++++++++------------------------ 1 file changed, 36 insertions(+), 37 deletions(-) diff --git a/pumpio/pumpio.php b/pumpio/pumpio.php index ffe5f187a..c3445b483 100644 --- a/pumpio/pumpio.php +++ b/pumpio/pumpio.php @@ -10,7 +10,6 @@ use Friendica\Content\Text\BBCode; use Friendica\Content\Text\HTML; use Friendica\Core\Addon; use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Protocol; use Friendica\Core\Renderer; use Friendica\Core\Worker; @@ -107,7 +106,7 @@ function pumpio_registerclient($host) $params['logo_url'] = DI::baseUrl() . '/images/friendica-256.png'; $params['redirect_uris'] = DI::baseUrl() . '/pumpio/connect'; - Logger::info('pumpio_registerclient: ' . $url . ' parameters', $params); + DI::logger()->info('pumpio_registerclient: ' . $url . ' parameters', $params); // @TODO Rewrite this to our own HTTP client $ch = curl_init($url); @@ -122,10 +121,10 @@ function pumpio_registerclient($host) if ($curl_info['http_code'] == '200') { $values = json_decode($s); - Logger::info('pumpio_registerclient: success ', (array)$values); + DI::logger()->info('pumpio_registerclient: success ', (array)$values); return $values; } - Logger::info('pumpio_registerclient: failed: ', $curl_info); + DI::logger()->info('pumpio_registerclient: failed: ', $curl_info); return false; } @@ -138,7 +137,7 @@ function pumpio_connect() $hostname = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'pumpio', 'host'); if ((($consumer_key == '') || ($consumer_secret == '')) && ($hostname != '')) { - Logger::notice('pumpio_connect: register client'); + DI::logger()->notice('pumpio_connect: register client'); $clientdata = pumpio_registerclient($hostname); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'pumpio', 'consumer_key', $clientdata->client_id); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'pumpio', 'consumer_secret', $clientdata->client_secret); @@ -146,11 +145,11 @@ function pumpio_connect() $consumer_key = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'pumpio', 'consumer_key'); $consumer_secret = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'pumpio', 'consumer_secret'); - Logger::info('pumpio_connect: ckey: ' . $consumer_key . ' csecrect: ' . $consumer_secret); + DI::logger()->info('pumpio_connect: ckey: ' . $consumer_key . ' csecrect: ' . $consumer_secret); } if (($consumer_key == '') || ($consumer_secret == '')) { - Logger::notice('pumpio_connect: '.sprintf('Unable to register the client at the pump.io server "%s".', $hostname)); + DI::logger()->notice('pumpio_connect: '.sprintf('Unable to register the client at the pump.io server "%s".', $hostname)); return DI::l10n()->t("Unable to register the client at the pump.io server '%s'.", $hostname); } @@ -179,7 +178,7 @@ function pumpio_connect() if (($success = $client->Initialize())) { if (($success = $client->Process())) { if (strlen($client->access_token)) { - Logger::info('pumpio_connect: otoken: ' . $client->access_token . ', osecrect: ' . $client->access_token_secret); + DI::logger()->info('pumpio_connect: otoken: ' . $client->access_token . ', osecrect: ' . $client->access_token_secret); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'pumpio', 'oauth_token', $client->access_token); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'pumpio', 'oauth_token_secret', $client->access_token_secret); } @@ -191,11 +190,11 @@ function pumpio_connect() } if ($success) { - Logger::notice('pumpio_connect: authenticated'); + DI::logger()->notice('pumpio_connect: authenticated'); $o = DI::l10n()->t('You are now authenticated to pumpio.'); $o .= '
' . DI::l10n()->t('return to the connector page') . ''; } else { - Logger::notice('pumpio_connect: could not connect'); + DI::logger()->notice('pumpio_connect: could not connect'); $o = 'Could not connect to pumpio. Refresh the page or try again later.'; } @@ -345,7 +344,7 @@ function pumpio_hook_fork(array &$b) if (DI::pConfig()->get($post['uid'], 'pumpio', 'import')) { // Don't fork if it isn't a reply to a pump.io post if (($post['gravity'] != Item::GRAVITY_PARENT) && !Post::exists(['id' => $post['parent'], 'network' => Protocol::PUMPIO])) { - Logger::notice('No pump.io parent found for item ' . $post['id']); + DI::logger()->notice('No pump.io parent found for item ' . $post['id']); $b['execute'] = false; return; } @@ -389,7 +388,7 @@ function pumpio_send(array &$b) return; } - Logger::debug('pumpio_send: parameter ', $b); + DI::logger()->debug('pumpio_send: parameter ', $b); $b['body'] = Post\Media::addAttachmentsToBody($b['uri-id'], DI::contentItem()->addSharedPost($b)); @@ -399,7 +398,7 @@ function pumpio_send(array &$b) $orig_post = Post::selectFirst([], $condition); if (!DBA::isResult($orig_post)) { - Logger::notice('pumpio_send: no pumpio post ' . $b['parent']); + DI::logger()->notice('pumpio_send: no pumpio post ' . $b['parent']); return; } else { $iscomment = true; @@ -409,7 +408,7 @@ function pumpio_send(array &$b) $receiver = pumpio_getreceiver($b); - Logger::notice('pumpio_send: receiver ', $receiver); + DI::logger()->notice('pumpio_send: receiver ', $receiver); if (!count($receiver) && ($b['private'] == Item::PRIVATE) || !strstr($b['postopts'], 'pumpio')) { return; @@ -543,13 +542,13 @@ function pumpio_send(array &$b) } $post_id = $user->object->id; - Logger::notice('pumpio_send ' . $username . ': success ' . $post_id); + DI::logger()->notice('pumpio_send ' . $username . ': success ' . $post_id); if ($post_id && $iscomment) { - Logger::notice('pumpio_send ' . $username . ': Update extid ' . $post_id . ' for post id ' . $b['id']); + DI::logger()->notice('pumpio_send ' . $username . ': Update extid ' . $post_id . ' for post id ' . $b['id']); Item::update(['extid' => $post_id], ['id' => $b['id']]); } } else { - Logger::notice('pumpio_send '.$username.': '.$url.' general error: ' . print_r($user, true)); + DI::logger()->notice('pumpio_send '.$username.': '.$url.' general error: ' . print_r($user, true)); Worker::defer(); } } @@ -619,9 +618,9 @@ function pumpio_action(int $uid, string $uri, string $action, string $content = } if ($success) { - Logger::notice('pumpio_action '.$username.' '.$action.': success '.$uri); + DI::logger()->notice('pumpio_action '.$username.' '.$action.': success '.$uri); } else { - Logger::notice('pumpio_action '.$username.' '.$action.': general error: '.$uri); + DI::logger()->notice('pumpio_action '.$username.' '.$action.': general error: '.$uri); Worker::defer(); } } @@ -639,15 +638,15 @@ function pumpio_sync() if ($last) { $next = $last + ($poll_interval * 60); if ($next > time()) { - Logger::notice('pumpio: poll intervall not reached'); + DI::logger()->notice('pumpio: poll intervall not reached'); return; } } - Logger::notice('pumpio: cron_start'); + DI::logger()->notice('pumpio: cron_start'); $pconfigs = DBA::selectToArray('pconfig', ['uid'], ['cat' => 'pumpio', 'k' => 'mirror', 'v' => '1']); foreach ($pconfigs as $rr) { - Logger::notice('pumpio: mirroring user '.$rr['uid']); + DI::logger()->notice('pumpio: mirroring user '.$rr['uid']); pumpio_fetchtimeline($rr['uid']); } @@ -662,12 +661,12 @@ function pumpio_sync() foreach ($pconfigs as $rr) { if ($abandon_days != 0) { if (DBA::exists('user', ["uid = ? AND `login_date` >= ?", $rr['uid'], $abandon_limit])) { - Logger::notice('abandoned account: timeline from user '.$rr['uid'].' will not be imported'); + DI::logger()->notice('abandoned account: timeline from user '.$rr['uid'].' will not be imported'); continue; } } - Logger::notice('pumpio: importing timeline from user '.$rr['uid']); + DI::logger()->notice('pumpio: importing timeline from user '.$rr['uid']); pumpio_fetchinbox($rr['uid']); // check for new contacts once a day @@ -684,7 +683,7 @@ function pumpio_sync() } } - Logger::notice('pumpio: cron_end'); + DI::logger()->notice('pumpio: cron_end'); DI::keyValue()->set('pumpio_last_poll', time()); } @@ -729,7 +728,7 @@ function pumpio_fetchtimeline(int $uid) $url = 'https://'.$hostname.'/api/user/'.$username.'/feed/major'; - Logger::notice('pumpio: fetching for user ' . $uid . ' ' . $url . ' C:' . $client->client_id . ' CS:' . $client->client_secret . ' T:' . $client->access_token . ' TS:' . $client->access_token_secret); + DI::logger()->notice('pumpio: fetching for user ' . $uid . ' ' . $url . ' C:' . $client->client_id . ' CS:' . $client->client_secret . ' T:' . $client->access_token . ' TS:' . $client->access_token_secret); $useraddr = $username.'@'.$hostname; @@ -741,7 +740,7 @@ function pumpio_fetchtimeline(int $uid) } if (!$success) { - Logger::notice('pumpio: error fetching posts for user ' . $uid . ' ' . $useraddr . ' ', $user); + DI::logger()->notice('pumpio: error fetching posts for user ' . $uid . ' ' . $useraddr . ' ', $user); return; } @@ -801,11 +800,11 @@ function pumpio_fetchtimeline(int $uid) } } - Logger::notice('pumpio: posting for user ' . $uid); + DI::logger()->notice('pumpio: posting for user ' . $uid); Item::insert($postarray, true); - Logger::notice('pumpio: posting done - user ' . $uid); + DI::logger()->notice('pumpio: posting done - user ' . $uid); } } } @@ -846,16 +845,16 @@ function pumpio_dounlike(int $uid, array $self, $post, string $own_id) Item::markForDeletion(['verb' => Activity::LIKE, 'uid' => $uid, 'contact-id' => $contactid, 'thr-parent' => $orig_post['uri']]); if (DBA::isResult($contact)) { - Logger::notice('pumpio_dounlike: unliked existing like. User ' . $own_id . ' ' . $uid . ' Contact: ' . $contactid . ' URI ' . $orig_post['uri']); + DI::logger()->notice('pumpio_dounlike: unliked existing like. User ' . $own_id . ' ' . $uid . ' Contact: ' . $contactid . ' URI ' . $orig_post['uri']); } else { - Logger::notice('pumpio_dounlike: not found. User ' . $own_id . ' ' . $uid . ' Contact: ' . $contactid . ' Url ' . $orig_post['uri']); + DI::logger()->notice('pumpio_dounlike: not found. User ' . $own_id . ' ' . $uid . ' Contact: ' . $contactid . ' Url ' . $orig_post['uri']); } } function pumpio_dolike(int $uid, array $self, $post, string $own_id, $threadcompletion = true) { if (empty($post->object->id)) { - Logger::info('Got empty like: '.print_r($post, true)); + DI::logger()->info('Got empty like: '.print_r($post, true)); return; } @@ -900,7 +899,7 @@ function pumpio_dolike(int $uid, array $self, $post, string $own_id, $threadcomp ]; if (Post::exists($condition)) { - Logger::notice('pumpio_dolike: found existing like. User ' . $own_id . ' ' . $uid . ' Contact: ' . $contactid . ' URI ' . $orig_post['uri']); + DI::logger()->notice('pumpio_dolike: found existing like. User ' . $own_id . ' ' . $uid . ' Contact: ' . $contactid . ' URI ' . $orig_post['uri']); return; } @@ -934,7 +933,7 @@ function pumpio_dolike(int $uid, array $self, $post, string $own_id, $threadcomp $ret = Item::insert($likedata); - Logger::notice('pumpio_dolike: ' . $ret . ' User ' . $own_id . ' ' . $uid . ' Contact: ' . $contactid . ' URI ' . $orig_post['uri']); + DI::logger()->notice('pumpio_dolike: ' . $ret . ' User ' . $own_id . ' ' . $uid . ' Contact: ' . $contactid . ' URI ' . $orig_post['uri']); } function pumpio_get_contact($uid, $contact, $no_insert = false) @@ -1405,7 +1404,7 @@ function pumpio_fetchallcomments($uid, $id) $hostname = DI::pConfig()->get($uid, 'pumpio', 'host'); $username = DI::pConfig()->get($uid, 'pumpio', 'user'); - Logger::notice('pumpio_fetchallcomments: completing comment for user ' . $uid . ' post id ' . $id); + DI::logger()->notice('pumpio_fetchallcomments: completing comment for user ' . $uid . ' post id ' . $id); $own_id = 'https://' . $hostname . '/' . $username; @@ -1430,7 +1429,7 @@ function pumpio_fetchallcomments($uid, $id) $client->access_token = $otoken; $client->access_token_secret = $osecret; - Logger::notice('pumpio_fetchallcomments: fetching comment for user ' . $uid . ', URL ' . $url); + DI::logger()->notice('pumpio_fetchallcomments: fetching comment for user ' . $uid . ', URL ' . $url); $item = new \stdClass(); @@ -1495,7 +1494,7 @@ function pumpio_fetchallcomments($uid, $id) $post->object = $item; - Logger::notice('pumpio_fetchallcomments: posting comment ' . $post->object->id . ' ', json_decode(json_encode($post), true)); + DI::logger()->notice('pumpio_fetchallcomments: posting comment ' . $post->object->id . ' ', json_decode(json_encode($post), true)); pumpio_dopost($client, $uid, $self, $post, $own_id, false); } } From 32a3160445d6a148b81daadd169705ddfe5558af Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 24 Jan 2025 11:56:09 +0000 Subject: [PATCH 345/388] Replace call for Logger with DI::logger() in randplace addon --- randplace/randplace.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/randplace/randplace.php b/randplace/randplace.php index 5cb075970..89a75f98e 100644 --- a/randplace/randplace.php +++ b/randplace/randplace.php @@ -20,7 +20,6 @@ */ use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\DI; @@ -40,7 +39,7 @@ function randplace_install() Hook::register('addon_settings', 'addon/randplace/randplace.php', 'randplace_settings'); Hook::register('addon_settings_post', 'addon/randplace/randplace.php', 'randplace_settings_post'); - Logger::notice("installed randplace"); + DI::logger()->notice("installed randplace"); } function randplace_uninstall() @@ -50,7 +49,7 @@ function randplace_uninstall() * * Except hooks, they are all unregistered automatically and don't need to be unregistered manually. */ - Logger::notice("removed randplace"); + DI::logger()->notice("removed randplace"); } function randplace_post_hook(&$item) @@ -61,7 +60,7 @@ function randplace_post_hook(&$item) * - A status post by a profile owner * - The profile owner must have allowed our addon */ - Logger::notice('randplace invoked'); + DI::logger()->notice('randplace invoked'); if (!DI::userSession()->getLocalUserId()) { /* non-zero if this is a logged in user of this system */ From ac6c1d7a49a386555c054faa6d13bb108856ebd0 Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 24 Jan 2025 11:56:29 +0000 Subject: [PATCH 346/388] Replace call for Logger with DI::logger() in saml addon --- saml/saml.php | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/saml/saml.php b/saml/saml.php index 81a6bfcc3..c8824b46b 100755 --- a/saml/saml.php +++ b/saml/saml.php @@ -8,7 +8,6 @@ use Friendica\Content\Text\BBCode; use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\Database\DBA; use Friendica\DI; @@ -63,7 +62,7 @@ function saml_metadata() ); } } catch (Exception $e) { - Logger::error($e->getMessage()); + DI::logger()->error($e->getMessage()); } } @@ -125,7 +124,7 @@ function saml_is_configured() function saml_sso_initiate(string &$body) { if (!saml_is_configured()) { - Logger::warning('SAML SSO tried to trigger, but the SAML addon is not configured yet!'); + DI::logger()->warning('SAML SSO tried to trigger, but the SAML addon is not configured yet!'); return; } @@ -154,7 +153,7 @@ function saml_sso_reply() if (!empty($errors)) { echo 'Errors encountered.'; - Logger::error(implode(', ', $errors)); + DI::logger()->error(implode(', ', $errors)); exit(); } @@ -190,7 +189,7 @@ function saml_sso_reply() function saml_slo_initiate() { if (!saml_is_configured()) { - Logger::warning('SAML SLO tried to trigger, but the SAML addon is not configured yet!'); + DI::logger()->warning('SAML SLO tried to trigger, but the SAML addon is not configured yet!'); return; } @@ -221,7 +220,7 @@ function saml_slo_reply() if (empty($errors)) { $auth->redirectTo(DI::baseUrl()); } else { - Logger::error(implode(', ', $errors)); + DI::logger()->error(implode(', ', $errors)); } } @@ -314,7 +313,7 @@ function saml_addon_admin_post() function saml_create_user($username, $email, $name) { if (!strlen($email) || !strlen($name)) { - Logger::error('Could not create user: no email or username given.'); + DI::logger()->error('Could not create user: no email or username given.'); return false; } @@ -336,7 +335,7 @@ function saml_create_user($username, $email, $name) return $user; } catch (Exception $e) { - Logger::error( + DI::logger()->error( 'Exception while creating user', [ 'username' => $username, From bfdccb451ce391361de025d01565b4a52af99d6c Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 24 Jan 2025 11:56:45 +0000 Subject: [PATCH 347/388] Replace call for Logger with DI::logger() in statusnet addon --- statusnet/statusnet.php | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/statusnet/statusnet.php b/statusnet/statusnet.php index bd115115e..8663aaea7 100644 --- a/statusnet/statusnet.php +++ b/statusnet/statusnet.php @@ -40,7 +40,6 @@ require_once __DIR__ . DIRECTORY_SEPARATOR . 'library' . DIRECTORY_SEPARATOR . ' use CodebirdSN\CodebirdSN; use Friendica\Content\Text\Plaintext; use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\Core\System; use Friendica\Database\DBA; @@ -58,7 +57,7 @@ function statusnet_install() Hook::register('hook_fork', 'addon/statusnet/statusnet.php', 'statusnet_hook_fork'); Hook::register('post_local', 'addon/statusnet/statusnet.php', 'statusnet_post_local'); Hook::register('jot_networks', 'addon/statusnet/statusnet.php', 'statusnet_jot_nets'); - Logger::notice('installed GNU Social'); + DI::logger()->notice('installed GNU Social'); } function statusnet_jot_nets(array &$jotnets_fields) @@ -355,7 +354,7 @@ function statusnet_post_hook(array &$b) return; } - Logger::notice('GNU Socialpost invoked'); + DI::logger()->notice('GNU Socialpost invoked'); DI::pConfig()->load($b['uid'], 'statusnet'); @@ -407,7 +406,7 @@ function statusnet_post_hook(array &$b) $cb->setToken($otoken, $osecret); $result = $cb->statuses_update($postdata); //$result = $dent->post('statuses/update', $postdata); - Logger::info('statusnet_post send, result: ' . print_r($result, true) . + DI::logger()->info('statusnet_post send, result: ' . print_r($result, true) . "\nmessage: " . $msg . "\nOriginal post: " . print_r($b, true) . "\nPost Data: " . print_r($postdata, true)); if (!empty($result->source)) { @@ -415,9 +414,9 @@ function statusnet_post_hook(array &$b) } if (!empty($result->error)) { - Logger::notice('Send to GNU Social failed: "' . $result->error . '"'); + DI::logger()->notice('Send to GNU Social failed: "' . $result->error . '"'); } elseif ($iscomment) { - Logger::notice('statusnet_post: Update extid ' . $result->id . ' for post id ' . $b['id']); + DI::logger()->notice('statusnet_post: Update extid ' . $result->id . ' for post id ' . $b['id']); Item::update(['extid' => $hostname . '::' . $result->id, 'body' => $result->text], ['id' => $b['id']]); } } From 763c5026f237a569f9f6cc9b4b65311556ca0087 Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 24 Jan 2025 11:57:12 +0000 Subject: [PATCH 348/388] Replace call for Logger with DI::logger() in tumblr addon --- tumblr/tumblr.php | 99 +++++++++++++++++++++++------------------------ 1 file changed, 49 insertions(+), 50 deletions(-) diff --git a/tumblr/tumblr.php b/tumblr/tumblr.php index 12f13aa8f..819c0ca5c 100644 --- a/tumblr/tumblr.php +++ b/tumblr/tumblr.php @@ -14,7 +14,6 @@ use Friendica\Content\Text\NPF; use Friendica\Core\Cache\Enum\Duration; use Friendica\Core\Config\Util\ConfigFileManager; use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Protocol; use Friendica\Core\Renderer; use Friendica\Core\System; @@ -60,7 +59,7 @@ function tumblr_install() Hook::register('check_item_notification', __FILE__, 'tumblr_check_item_notification'); Hook::register('probe_detect', __FILE__, 'tumblr_probe_detect'); Hook::register('item_by_link', __FILE__, 'tumblr_item_by_link'); - Logger::info('installed tumblr'); + DI::logger()->info('installed tumblr'); } function tumblr_load_config(ConfigFileManager $loader) @@ -121,16 +120,16 @@ function tumblr_item_by_link(array &$hookData) return; } - Logger::debug('Found tumblr post', ['url' => $hookData['uri'], 'blog' => $matches[1], 'id' => $matches[2]]); + DI::logger()->debug('Found tumblr post', ['url' => $hookData['uri'], 'blog' => $matches[1], 'id' => $matches[2]]); $parameters = ['id' => $matches[2], 'reblog_info' => false, 'notes_info' => false, 'npf' => false]; $result = tumblr_get($hookData['uid'], 'blog/' . $matches[1] . '/posts', $parameters); if ($result->meta->status > 399) { - Logger::notice('Error fetching status', ['meta' => $result->meta, 'response' => $result->response, 'errors' => $result->errors, 'blog' => $matches[1], 'id' => $matches[2]]); + DI::logger()->notice('Error fetching status', ['meta' => $result->meta, 'response' => $result->response, 'errors' => $result->errors, 'blog' => $matches[1], 'id' => $matches[2]]); return []; } - Logger::debug('Got post', ['blog' => $matches[1], 'id' => $matches[2], 'result' => $result->response->posts]); + DI::logger()->debug('Got post', ['blog' => $matches[1], 'id' => $matches[2], 'result' => $result->response->posts]); if (!empty($result->response->posts)) { $hookData['item_id'] = tumblr_process_post($result->response->posts[0], $hookData['uid'], Item::PR_FETCHED); Item::incrementInbound(Protocol::TUMBLR); @@ -159,20 +158,20 @@ function tumblr_follow(array &$hook_data) return; } - Logger::debug('Check if contact is Tumblr', ['url' => $hook_data['url']]); + DI::logger()->debug('Check if contact is Tumblr', ['url' => $hook_data['url']]); $fields = tumblr_get_contact_by_url($hook_data['url'], $uid); if (empty($fields)) { - Logger::debug('Contact is not a Tumblr contact', ['url' => $hook_data['url']]); + DI::logger()->debug('Contact is not a Tumblr contact', ['url' => $hook_data['url']]); return; } $result = tumblr_post($uid, 'user/follow', ['url' => $fields['url']]); if ($result->meta->status <= 399) { $hook_data['contact'] = $fields; - Logger::debug('Successfully start following', ['url' => $fields['url']]); + DI::logger()->debug('Successfully start following', ['url' => $fields['url']]); } else { - Logger::notice('Following failed', ['meta' => $result->meta, 'response' => $result->response, 'errors' => $result->errors, 'url' => $fields['url']]); + DI::logger()->notice('Following failed', ['meta' => $result->meta, 'response' => $result->response, 'errors' => $result->errors, 'url' => $fields['url']]); } } @@ -415,11 +414,11 @@ function tumblr_cron() if ($last) { $next = $last + ($poll_interval * 60); if ($next > time()) { - Logger::notice('poll interval not reached'); + DI::logger()->notice('poll interval not reached'); return; } } - Logger::notice('cron_start'); + DI::logger()->notice('cron_start'); $abandon_days = intval(DI::config()->get('system', 'account_abandon_days')); if ($abandon_days < 1) { @@ -432,30 +431,30 @@ function tumblr_cron() foreach ($pconfigs as $pconfig) { if ($abandon_days != 0) { if (!DBA::exists('user', ["`uid` = ? AND `login_date` >= ?", $pconfig['uid'], $abandon_limit])) { - Logger::notice('abandoned account: timeline from user will not be imported', ['user' => $pconfig['uid']]); + DI::logger()->notice('abandoned account: timeline from user will not be imported', ['user' => $pconfig['uid']]); continue; } } - Logger::notice('importing timeline - start', ['user' => $pconfig['uid']]); + DI::logger()->notice('importing timeline - start', ['user' => $pconfig['uid']]); tumblr_fetch_dashboard($pconfig['uid'], $last); tumblr_fetch_tags($pconfig['uid'], $last); - Logger::notice('importing timeline - done', ['user' => $pconfig['uid']]); + DI::logger()->notice('importing timeline - done', ['user' => $pconfig['uid']]); } $last_clean = DI::keyValue()->get('tumblr_last_clean'); if (empty($last_clean) || ($last_clean + 86400 < time())) { - Logger::notice('Start contact cleanup'); + DI::logger()->notice('Start contact cleanup'); $contacts = DBA::select('account-user-view', ['id', 'pid'], ["`network` = ? AND `uid` != ? AND `rel` = ?", Protocol::TUMBLR, 0, Contact::NOTHING]); while ($contact = DBA::fetch($contacts)) { Worker::add(Worker::PRIORITY_LOW, 'MergeContact', $contact['pid'], $contact['id'], 0); } DBA::close($contacts); DI::keyValue()->set('tumblr_last_clean', time()); - Logger::notice('Contact cleanup done'); + DI::logger()->notice('Contact cleanup done'); } - Logger::notice('cron_end'); + DI::logger()->notice('cron_end'); DI::keyValue()->set('tumblr_last_poll', time()); } @@ -478,7 +477,7 @@ function tumblr_hook_fork(array &$b) if (DI::pConfig()->get($post['uid'], 'tumblr', 'import')) { // Don't post if it isn't a reply to a tumblr post if (($post['gravity'] != Item::GRAVITY_PARENT) && !Post::exists(['id' => $post['parent'], 'network' => Protocol::TUMBLR])) { - Logger::notice('No tumblr parent found', ['item' => $post['id']]); + DI::logger()->notice('No tumblr parent found', ['item' => $post['id']]); $b['execute'] = false; return; } @@ -525,20 +524,20 @@ function tumblr_send(array &$b) } if ($b['gravity'] != Item::GRAVITY_PARENT) { - Logger::debug('Got comment', ['item' => $b]); + DI::logger()->debug('Got comment', ['item' => $b]); $parent = tumblr_get_post_from_uri($b['thr-parent']); if (empty($parent)) { - Logger::notice('No tumblr post', ['thr-parent' => $b['thr-parent']]); + DI::logger()->notice('No tumblr post', ['thr-parent' => $b['thr-parent']]); return; } - Logger::debug('Parent found', ['parent' => $parent]); + DI::logger()->debug('Parent found', ['parent' => $parent]); $page = tumblr_get_page($b['uid']); if ($b['gravity'] == Item::GRAVITY_COMMENT) { - Logger::notice('Commenting is not supported (yet)'); + DI::logger()->notice('Commenting is not supported (yet)'); } else { if (($b['verb'] == Activity::LIKE) && !$b['deleted']) { $params = ['id' => $parent['id'], 'reblog_key' => $parent['reblog_key']]; @@ -562,12 +561,12 @@ function tumblr_send(array &$b) } if ($result->meta->status < 400) { - Logger::info('Successfully performed activity', ['verb' => $b['verb'], 'deleted' => $b['deleted'], 'meta' => $result->meta, 'response' => $result->response]); + DI::logger()->info('Successfully performed activity', ['verb' => $b['verb'], 'deleted' => $b['deleted'], 'meta' => $result->meta, 'response' => $result->response]); if (!$b['deleted'] && !empty($result->response->id_string)) { Item::update(['extid' => 'tumblr::' . $result->response->id_string], ['guid' => $b['guid']]); } } else { - Logger::notice('Error while performing activity', ['verb' => $b['verb'], 'deleted' => $b['deleted'], 'meta' => $result->meta, 'response' => $result->response, 'errors' => $result->errors, 'params' => $params]); + DI::logger()->notice('Error while performing activity', ['verb' => $b['verb'], 'deleted' => $b['deleted'], 'meta' => $result->meta, 'response' => $result->response, 'errors' => $result->errors, 'params' => $params]); } } return; @@ -665,9 +664,9 @@ function tumblr_send_legacy(array $b) $result = tumblr_post($b['uid'], 'blog/' . $page . '/post', $params); if ($result->meta->status < 400) { - Logger::info('Success (legacy)', ['blog' => $page, 'meta' => $result->meta, 'response' => $result->response]); + DI::logger()->info('Success (legacy)', ['blog' => $page, 'meta' => $result->meta, 'response' => $result->response]); } else { - Logger::notice('Error posting blog (legacy)', ['blog' => $page, 'meta' => $result->meta, 'response' => $result->response, 'errors' => $result->errors, 'params' => $params]); + DI::logger()->notice('Error posting blog (legacy)', ['blog' => $page, 'meta' => $result->meta, 'response' => $result->response, 'errors' => $result->errors, 'params' => $params]); } } @@ -676,7 +675,7 @@ function tumblr_send_npf(array $post): bool $page = tumblr_get_page($post['uid']); if (empty($page)) { - Logger::notice('Missing page, post will not be send to Tumblr.', ['uid' => $post['uid'], 'page' => $page, 'id' => $post['id']]); + DI::logger()->notice('Missing page, post will not be send to Tumblr.', ['uid' => $post['uid'], 'page' => $page, 'id' => $post['id']]); // "true" is returned, since the legacy function will fail as well. return true; } @@ -707,10 +706,10 @@ function tumblr_send_npf(array $post): bool $result = tumblr_post($post['uid'], 'blog/' . $page . '/posts', $params); if ($result->meta->status < 400) { - Logger::info('Success (NPF)', ['blog' => $page, 'meta' => $result->meta, 'response' => $result->response]); + DI::logger()->info('Success (NPF)', ['blog' => $page, 'meta' => $result->meta, 'response' => $result->response]); return true; } else { - Logger::notice('Error posting blog (NPF)', ['blog' => $page, 'meta' => $result->meta, 'response' => $result->response, 'errors' => $result->errors, 'params' => $params]); + DI::logger()->notice('Error posting blog (NPF)', ['blog' => $page, 'meta' => $result->meta, 'response' => $result->response, 'errors' => $result->errors, 'params' => $params]); return false; } } @@ -747,10 +746,10 @@ function tumblr_fetch_tags(int $uid, int $last_poll) foreach (array_reverse($data->response) as $post) { $id = tumblr_process_post($post, $uid, Item::PR_TAG, $last_poll); if (!empty($id)) { - Logger::debug('Tag post imported', ['tag' => $tag, 'id' => $id]); + DI::logger()->debug('Tag post imported', ['tag' => $tag, 'id' => $id]); $post = Post::selectFirst(['uri-id'], ['id' => $id]); $stored = Post\Category::storeFileByURIId($post['uri-id'], $uid, Post\Category::SUBCRIPTION, $tag); - Logger::debug('Stored tag subscription for user', ['uri-id' => $post['uri-id'], 'uid' => $uid, 'tag' => $tag, 'stored' => $stored]); + DI::logger()->debug('Stored tag subscription for user', ['uri-id' => $post['uri-id'], 'uid' => $uid, 'tag' => $tag, 'stored' => $stored]); Item::incrementInbound(Protocol::TUMBLR); } } @@ -775,7 +774,7 @@ function tumblr_fetch_dashboard(int $uid, int $last_poll) $dashboard = tumblr_get($uid, 'user/dashboard', $parameters); if ($dashboard->meta->status > 399) { - Logger::notice('Error fetching dashboard', ['meta' => $dashboard->meta, 'response' => $dashboard->response, 'errors' => $dashboard->errors]); + DI::logger()->notice('Error fetching dashboard', ['meta' => $dashboard->meta, 'response' => $dashboard->response, 'errors' => $dashboard->errors]); return []; } @@ -788,7 +787,7 @@ function tumblr_fetch_dashboard(int $uid, int $last_poll) $last = $post->id; } - Logger::debug('Importing post', ['uid' => $uid, 'created' => date(DateTimeFormat::MYSQL, $post->timestamp), 'id' => $post->id_string]); + DI::logger()->debug('Importing post', ['uid' => $uid, 'created' => date(DateTimeFormat::MYSQL, $post->timestamp), 'id' => $post->id_string]); tumblr_process_post($post, $uid, Item::PR_NONE, $last_poll); Item::incrementInbound(Protocol::TUMBLR); @@ -1063,7 +1062,7 @@ function tumblr_get_type_replacement(array $data, string $plink): string } default: - Logger::notice('Unknown type', ['type' => $data['type'], 'data' => $data, 'plink' => $plink]); + DI::logger()->notice('Unknown type', ['type' => $data['type'], 'data' => $data, 'plink' => $plink]); $body = ''; } @@ -1118,9 +1117,9 @@ function tumblr_get_contact(stdClass $blog, int $uid): array $cid = $contact['id']; Contact::update($fields, ['id' => $cid], true); } - Logger::debug('Get user contact', ['id' => $cid, 'uid' => $uid, 'update' => $update]); + DI::logger()->debug('Get user contact', ['id' => $cid, 'uid' => $uid, 'update' => $update]); } else { - Logger::debug('Get public contact', ['id' => $cid, 'uid' => $uid, 'update' => $update]); + DI::logger()->debug('Get public contact', ['id' => $cid, 'uid' => $uid, 'update' => $update]); } if (!empty($avatar)) { @@ -1156,13 +1155,13 @@ function tumblr_get_contact_fields(stdClass $blog, int $uid, bool $update): arra ]; if (!$update) { - Logger::debug('Got contact fields', ['uid' => $uid, 'url' => $fields['url']]); + DI::logger()->debug('Got contact fields', ['uid' => $uid, 'url' => $fields['url']]); return $fields; } $info = tumblr_get($uid, 'blog/' . $blog->uuid . '/info'); if ($info->meta->status > 399) { - Logger::notice('Error fetching blog info', ['meta' => $info->meta, 'response' => $info->response, 'errors' => $info->errors]); + DI::logger()->notice('Error fetching blog info', ['meta' => $info->meta, 'response' => $info->response, 'errors' => $info->errors]); return $fields; } Item::incrementInbound(Protocol::TUMBLR); @@ -1184,7 +1183,7 @@ function tumblr_get_contact_fields(stdClass $blog, int $uid, bool $update): arra $fields['header'] = $info->response->blog->theme->header_image_focused; - Logger::debug('Got updated contact fields', ['uid' => $uid, 'url' => $fields['url']]); + DI::logger()->debug('Got updated contact fields', ['uid' => $uid, 'url' => $fields['url']]); return $fields; } @@ -1226,7 +1225,7 @@ function tumblr_get_blogs(int $uid): array { $userinfo = tumblr_get($uid, 'user/info'); if ($userinfo->meta->status > 399) { - Logger::notice('Error fetching blogs', ['meta' => $userinfo->meta, 'response' => $userinfo->response, 'errors' => $userinfo->errors]); + DI::logger()->notice('Error fetching blogs', ['meta' => $userinfo->meta, 'response' => $userinfo->response, 'errors' => $userinfo->errors]); return []; } @@ -1282,15 +1281,15 @@ function tumblr_get_contact_by_url(string $url, int $uid): ?array return null; } - Logger::debug('Update Tumblr blog data', ['url' => $url, 'blog' => $blog, 'uid' => $uid]); + DI::logger()->debug('Update Tumblr blog data', ['url' => $url, 'blog' => $blog, 'uid' => $uid]); $info = tumblr_get($uid, 'blog/' . $blog . '/info'); if ($info->meta->status > 399) { - Logger::notice('Error fetching blog info', ['meta' => $info->meta, 'response' => $info->response, 'errors' => $info->errors, 'blog' => $blog, 'uid' => $uid]); + DI::logger()->notice('Error fetching blog info', ['meta' => $info->meta, 'response' => $info->response, 'errors' => $info->errors, 'blog' => $blog, 'uid' => $uid]); return null; } - Logger::debug('Got data', ['blog' => $blog, 'meta' => $info->meta]); + DI::logger()->debug('Got data', ['blog' => $blog, 'meta' => $info->meta]); Item::incrementInbound(Protocol::TUMBLR); $baseurl = 'https://tumblr.com'; @@ -1419,7 +1418,7 @@ function tumblr_get_token(int $uid, string $code = ''): string $refresh_token = DI::pConfig()->get($uid, 'tumblr', 'refresh_token'); if (empty($code) && !empty($access_token) && ($expires_at > (time()))) { - Logger::debug('Got token', ['uid' => $uid, 'expires_at' => date('c', $expires_at)]); + DI::logger()->debug('Got token', ['uid' => $uid, 'expires_at' => date('c', $expires_at)]); return $access_token; } @@ -1431,11 +1430,11 @@ function tumblr_get_token(int $uid, string $code = ''): string if (empty($refresh_token) && empty($code)) { $result = tumblr_exchange_token($uid); if (empty($result->refresh_token)) { - Logger::info('Invalid result while exchanging token', ['uid' => $uid]); + DI::logger()->info('Invalid result while exchanging token', ['uid' => $uid]); return ''; } $expires_at = time() + $result->expires_in; - Logger::debug('Updated token from OAuth1 to OAuth2', ['uid' => $uid, 'expires_at' => date('c', $expires_at)]); + DI::logger()->debug('Updated token from OAuth1 to OAuth2', ['uid' => $uid, 'expires_at' => date('c', $expires_at)]); } else { if (!empty($code)) { $parameters['code'] = $code; @@ -1447,18 +1446,18 @@ function tumblr_get_token(int $uid, string $code = ''): string $curlResult = DI::httpClient()->post('https://api.tumblr.com/v2/oauth2/token', $parameters); if (!$curlResult->isSuccess()) { - Logger::info('Error fetching token', ['uid' => $uid, 'code' => $code, 'result' => $curlResult->getBodyString(), 'parameters' => $parameters]); + DI::logger()->info('Error fetching token', ['uid' => $uid, 'code' => $code, 'result' => $curlResult->getBodyString(), 'parameters' => $parameters]); return ''; } $result = json_decode($curlResult->getBodyString()); if (empty($result)) { - Logger::info('Invalid result when updating token', ['uid' => $uid]); + DI::logger()->info('Invalid result when updating token', ['uid' => $uid]); return ''; } $expires_at = time() + $result->expires_in; - Logger::debug('Renewed token', ['uid' => $uid, 'expires_at' => date('c', $expires_at)]); + DI::logger()->debug('Renewed token', ['uid' => $uid, 'expires_at' => date('c', $expires_at)]); } DI::pConfig()->set($uid, 'tumblr', 'access_token', $result->access_token); @@ -1502,7 +1501,7 @@ function tumblr_exchange_token(int $uid): stdClass $response = $client->post('oauth2/exchange', ['auth' => 'oauth']); return json_decode($response->getBody()->getContents()); } catch (RequestException $exception) { - Logger::notice('Exchange failed', ['code' => $exception->getCode(), 'message' => $exception->getMessage()]); + DI::logger()->notice('Exchange failed', ['code' => $exception->getCode(), 'message' => $exception->getMessage()]); return new stdClass; } } From a7b26f64538159e72799fae87679d1d10e0b1bb3 Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 24 Jan 2025 11:57:34 +0000 Subject: [PATCH 349/388] Replace call for Logger with DI::logger() in tesseract addon --- tesseract/tesseract.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tesseract/tesseract.php b/tesseract/tesseract.php index 4c630dbb5..ea048032e 100644 --- a/tesseract/tesseract.php +++ b/tesseract/tesseract.php @@ -7,7 +7,6 @@ */ use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\System; use thiagoalessio\TesseractOCR\TesseractOCR; @@ -17,7 +16,7 @@ function tesseract_install() { Hook::register('ocr-detection', __FILE__, 'tesseract_ocr_detection'); - Logger::notice('installed tesseract'); + DI::logger()->notice('installed tesseract'); } function tesseract_ocr_detection(&$media) @@ -33,6 +32,6 @@ function tesseract_ocr_detection(&$media) $ocr->imageData($media['img_str'], strlen($media['img_str'])); $media['description'] = $ocr->run(); } catch (\Throwable $th) { - Logger::info('Error calling TesseractOCR', ['message' => $th->getMessage()]); + DI::logger()->info('Error calling TesseractOCR', ['message' => $th->getMessage()]); } } From e4d14cab62755aa91d986584b4898d75054b3471 Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 24 Jan 2025 11:58:10 +0000 Subject: [PATCH 350/388] Replace call for Logger with DI::logger() in twitter addon --- tesseract/tesseract.php | 1 + twitter/twitter.php | 31 +++++++++++++++---------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/tesseract/tesseract.php b/tesseract/tesseract.php index ea048032e..a07c690c7 100644 --- a/tesseract/tesseract.php +++ b/tesseract/tesseract.php @@ -8,6 +8,7 @@ use Friendica\Core\Hook; use Friendica\Core\System; +use Friendica\DI; use thiagoalessio\TesseractOCR\TesseractOCR; require_once __DIR__ . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php'; diff --git a/twitter/twitter.php b/twitter/twitter.php index ea4ae3569..a96544057 100644 --- a/twitter/twitter.php +++ b/twitter/twitter.php @@ -38,7 +38,6 @@ use Friendica\Content\Text\BBCode; use Friendica\Content\Text\Plaintext; use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\Core\Worker; use Friendica\DI; @@ -217,7 +216,7 @@ function twitter_post_hook(array &$b) $b['body'] = Post\Media::addAttachmentsToBody($b['uri-id'], DI::contentItem()->addSharedPost($b)); - Logger::notice('twitter post invoked', ['id' => $b['id'], 'guid' => $b['guid']]); + DI::logger()->notice('twitter post invoked', ['id' => $b['id'], 'guid' => $b['guid']]); DI::pConfig()->load($b['uid'], 'twitter'); @@ -227,17 +226,17 @@ function twitter_post_hook(array &$b) $access_secret = DI::pConfig()->get($b['uid'], 'twitter', 'access_secret'); if (empty($api_key) || empty($api_secret) || empty($access_token) || empty($access_secret)) { - Logger::info('Missing keys, secrets or tokens.'); + DI::logger()->info('Missing keys, secrets or tokens.'); return; } $msgarr = Plaintext::getPost($b, 280, true, BBCode::TWITTER); - Logger::debug('Got plaintext', ['id' => $b['id'], 'message' => $msgarr]); + DI::logger()->debug('Got plaintext', ['id' => $b['id'], 'message' => $msgarr]); $media_ids = []; if (!empty($msgarr['images']) || !empty($msgarr['remote_images'])) { - Logger::info('Got images', ['id' => $b['id'], 'images' => $msgarr['images'] ?? []]); + DI::logger()->info('Got images', ['id' => $b['id'], 'images' => $msgarr['images'] ?? []]); $retrial = Worker::getRetrial(); if ($retrial > 4) { @@ -250,7 +249,7 @@ function twitter_post_hook(array &$b) try { $media_ids[] = twitter_upload_image($b['uid'], $image, $retrial); } catch (RequestException $exception) { - Logger::warning('Error while uploading image', ['image' => $image, 'code' => $exception->getCode(), 'message' => $exception->getMessage()]); + DI::logger()->warning('Error while uploading image', ['image' => $image, 'code' => $exception->getCode(), 'message' => $exception->getMessage()]); Worker::defer(); return; } @@ -259,13 +258,13 @@ function twitter_post_hook(array &$b) $in_reply_to_tweet_id = 0; - Logger::debug('Post message', ['id' => $b['id'], 'parts' => count($msgarr['parts'])]); + DI::logger()->debug('Post message', ['id' => $b['id'], 'parts' => count($msgarr['parts'])]); foreach ($msgarr['parts'] as $key => $part) { try { $id = twitter_post_status($b['uid'], $part, $media_ids, $in_reply_to_tweet_id); - Logger::info('twitter_post send', ['part' => $key, 'id' => $b['id'], 'result' => $id]); + DI::logger()->info('twitter_post send', ['part' => $key, 'id' => $b['id'], 'result' => $id]); } catch (RequestException $exception) { - Logger::warning('Error while posting message', ['part' => $key, 'id' => $b['id'], 'code' => $exception->getCode(), 'message' => $exception->getMessage()]); + DI::logger()->warning('Error while posting message', ['part' => $key, 'id' => $b['id'], 'code' => $exception->getCode(), 'message' => $exception->getMessage()]); $status = [ 'code' => $exception->getCode(), 'reason' => $exception->getResponse()->getReasonPhrase(), @@ -319,9 +318,9 @@ function twitter_upload_image(int $uid, array $image, int $retrial) $picturedata = $picture->asString(); $new_size = strlen($picturedata); - Logger::info('Uploading', ['uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size, 'image' => $image]); + DI::logger()->info('Uploading', ['uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size, 'image' => $image]); $media = twitter_post($uid, 'https://upload.twitter.com/1.1/media/upload.json', 'form_params', ['media' => base64_encode($picturedata)]); - Logger::info('Uploading done', ['uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size, 'image' => $image]); + DI::logger()->info('Uploading done', ['uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size, 'image' => $image]); if (isset($media->media_id_string)) { $media_id = $media->media_id_string; @@ -334,10 +333,10 @@ function twitter_upload_image(int $uid, array $image, int $retrial) ] ]; $ret = twitter_post($uid, 'https://upload.twitter.com/1.1/media/metadata/create.json', 'json', $data); - Logger::info('Metadata create', ['uid' => $uid, 'data' => $data, 'return' => $ret]); + DI::logger()->info('Metadata create', ['uid' => $uid, 'data' => $data, 'return' => $ret]); } } else { - Logger::error('Failed upload', ['uid' => $uid, 'size' => strlen($picturedata), 'image' => $image['url'], 'return' => $media]); + DI::logger()->error('Failed upload', ['uid' => $uid, 'size' => strlen($picturedata), 'image' => $image['url'], 'return' => $media]); throw new Exception('Failed upload of ' . $image['url']); } @@ -373,7 +372,7 @@ function twitter_post(int $uid, string $url, string $type, array $data): stdClas DI::pConfig()->set($uid, 'twitter', 'last_status', $status); $content = json_decode($body) ?? new stdClass; - Logger::debug('Success', ['content' => $content]); + DI::logger()->debug('Success', ['content' => $content]); return $content; } @@ -402,7 +401,7 @@ function twitter_test_connection(int $uid) 'content' => $response->getBody()->getContents() ]; DI::pConfig()->set(1, 'twitter', 'last_status', $status); - Logger::info('Test successful', ['uid' => $uid]); + DI::logger()->info('Test successful', ['uid' => $uid]); } catch (RequestException $exception) { $status = [ 'code' => $exception->getCode(), @@ -410,6 +409,6 @@ function twitter_test_connection(int $uid) 'content' => $exception->getMessage() ]; DI::pConfig()->set(1, 'twitter', 'last_status', $status); - Logger::info('Test failed', ['uid' => $uid]); + DI::logger()->info('Test failed', ['uid' => $uid]); } } From dd775645d48b0309e08f604500e2baf85171800f Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 24 Jan 2025 11:58:32 +0000 Subject: [PATCH 351/388] Replace call for Logger with DI::logger() in wppost addon --- wppost/wppost.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/wppost/wppost.php b/wppost/wppost.php index f2ee5d210..de2168068 100644 --- a/wppost/wppost.php +++ b/wppost/wppost.php @@ -9,7 +9,6 @@ use Friendica\Content\Text\BBCode; use Friendica\Content\Text\HTML; use Friendica\Core\Hook; -use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\Database\DBA; use Friendica\DI; @@ -257,13 +256,13 @@ function wppost_send(array &$b) EOT; - Logger::debug('wppost: data: ' . $xml); + DI::logger()->debug('wppost: data: ' . $xml); $x = ''; if ($wp_blog !== 'test') { $x = DI::httpClient()->post($wp_blog, $xml)->getBodyString(); } - Logger::info('posted to wordpress: ' . $x); + DI::logger()->info('posted to wordpress: ' . $x); } } From 4c8c262b07f61d08a6f9a67c325a54dcb95b4c75 Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 24 Jan 2025 12:10:58 +0000 Subject: [PATCH 352/388] fix in googlemaps addon --- googlemaps/googlemaps.php | 1 + 1 file changed, 1 insertion(+) diff --git a/googlemaps/googlemaps.php b/googlemaps/googlemaps.php index a0bba8adf..94a3a96bf 100644 --- a/googlemaps/googlemaps.php +++ b/googlemaps/googlemaps.php @@ -8,6 +8,7 @@ */ use Friendica\Core\Hook; +use Friendica\DI; function googlemaps_install() { From cbfcfb33494d1662de1a5f5689caa23d723d6bca Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 25 Jan 2025 02:44:54 +0000 Subject: [PATCH 353/388] Issue 14692: Avoid loop situation --- blockbot/blockbot.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blockbot/blockbot.php b/blockbot/blockbot.php index 163d0cbc6..71e35c930 100644 --- a/blockbot/blockbot.php +++ b/blockbot/blockbot.php @@ -208,7 +208,7 @@ function blockbot_log_activitypub(string $url, string $agent) blockbot_save('activitypub-inbox-agents', $agent); } - if (!empty($_SERVER['HTTP_SIGNATURE']) && !empty(HTTPSignature::getSigner('', $_SERVER))) { + if (!empty($_SERVER['HTTP_SIGNATURE']) && !empty(HTTPSignature::getSigner('', $_SERVER, false))) { blockbot_save('activitypub-signature-agents', $agent); } } From 8384b74696b54c126a2b2c835a010403b6413b7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakobus=20Sch=C3=BCrz?= Date: Thu, 23 Jan 2025 16:32:22 +0100 Subject: [PATCH 354/388] add condition for selected theme --- saml/saml.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/saml/saml.php b/saml/saml.php index c8824b46b..83e4d3fde 100755 --- a/saml/saml.php +++ b/saml/saml.php @@ -82,11 +82,13 @@ function saml_footer(string &$body)

&2HkSF3%@nLp98uSM#+_3HLXY45tTW~cO4{M)U1 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 ez&_3$| z6E*6Afn#aXyEGHKw8!-f80DR^c>p8{VC3s~Nwpp*KTffDy#j*yBv-3fGQ-3ks^ki8 znrUX1wBQ;UMGjgqm0hn2))1)Hitzb)LgqxhL3w(N>JfUuqDy=8hJq6VOwTX)AHi?d z%zDoo--ARyq9Ap={GY`iU#2NhC2n#bWt{sHS;kOtN^H?SS?w&{Zq>czzoOBLzfa7H zUc1@ve0_LeYt4%CTPE>&wqwp(NcQSSOSlA}`~Xus+e>=@E@AzuJ0%bIBpT_dCE4vf z`6yw7_;Vc#{vjOA2xZUDS43g4G<_JG^8)+lFYajFHCDRYiF>ApV>=t|Sydj1UxH&c zEL!Sw1_-A`2E)d6MR(&$gZD8$k^B2l5g+0ahu)0n2C|SmwwE49U-IiJEWe`WeTkcv z;Ty(reJqY5RcV-B@n=qHG2}Xvx7pj3=`fnnZyYCv$<>ZX!QyYUC*k@ zRS-cokR7JhryR>|zgIYabp~s-Gg_zIglP~ALT}9jwe6h3xLjnW*u;Z>(&>0l918=I zV_GJyLBNT>YoT9dumQkp`pi9!#fU@cEKUWTWtB9ch@|2vQVH0+_c(K#4obn2Q4?O~ zjJDQ{N2I$;Z+I?@ z1PlFFnQW;L;~Ho|Ng_hiVoH4B{c%%h?w8jV#AI4-63HIpmyI={;NwpS#+6N^jXMR# zhPfON$PF@jhfL}Fhu_u>+F7i;0B7UxiMcp&pM+3m1IH)yz#r^{=SsJ70Qhc>0+^~e zp^JUM%;^=!uCUlba31O4JmRZBKL$|~pxXJ{;fn*r0U%~4 zHjoND_JvdkQNrUtIYK>EI|$eL3LxXUBta5lA~;PhzMlQzy$k~w@4JGZLE zuo^{j5u`aQ%eN4_1YDmCFa;Zv(M-z?sclf|q!|{7Pl#ZI5)Ceo%+Btf86e|H_*y!h z;%V*S1j2kI4X-3veUR-!;o=$xs2TzunX+bh9GEVI3>3P?wy>e`v8Au+-$qmr!-FcV zi+}}Cv;h6LP+}hb}xQ%HB@oEV))6T2+gf!{YY8@J2E2bsm2=2i2a`E>IdsY^RwXn<-n-}Pi-^YDy`EF;QTq%~CWJ5ijC!j)s-MV#`PoovPk#}MQ9 zCk7sd%psv^tsx)kQ{cvnuyImMZcRLJq6gN?Sd*i5Q`(=; zR?O$PLAi(#wZ`3ny~a679#bCf7%`AhUpsyXUMAf*Jg!B|z&5l<-{O<9P_fPZFmCB5 z1h}7L-ML%6u95>CbgFvBt;-^CVhm^yNPTsqvWcfZcA}jEr*(1y&NlU7!UT_xi{8f<{>F_H< zO4__)&Vkiy&QTB}D6tS3m_sU1Sg8aQ#xILN=mtVWm5G5@b*XqpFtf9pEX}5`h!=fD z`537=!7Pn{uZKxyDgBR)IfC=r(=gN`Lkzelzwp&slzS0>u!TuOiat)CBooM>K|c$$ zBnU|z2>jaIcv2+BwVj7*wXoI6PyvUacC)&?y8E|V@#=l2)OeAB0F9&C*mo?Pi^A=u@97oy9Y!@U}qM)C+CSE$C^ z4MQ_;I#3s>YV9LrxWMfss0Wu8cS-=156UUKwRcb1xE4E_YHBQ%yN~RQc0!w{hti9- zWV@BO(>PI4ziB;_Pcurs+#F&R8H!jIQDc1ⅈD+8&b)((iczYqzfVNSIqPg)QL}T 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